61fd6d76fe27d726b32848f541cdefb7bf3cffe6
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / Parser.java
1 /**********************************************************************
2 Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Common Public License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/legal/cpl-v10.html
7
8 Contributors:
9     Klaus Hartlage - www.eclipseproject.de
10 **********************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.parser;
12
13 import java.text.MessageFormat;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Hashtable;
17
18 import net.sourceforge.phpdt.core.compiler.*;
19 import net.sourceforge.phpdt.internal.compiler.parser.*;
20 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
21 import net.sourceforge.phpeclipse.actions.PHPStartApacheAction;
22 import net.sourceforge.phpeclipse.phpeditor.PHPString;
23 import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords;
24
25 import org.eclipse.core.resources.IFile;
26 import org.eclipse.core.resources.IMarker;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IPath;
29 import org.eclipse.jface.preference.IPreferenceStore;
30 import org.eclipse.ui.texteditor.MarkerUtilities;
31
32 public class Parser extends PHPKeywords implements ITerminalSymbols {
33   // strings for external parser call
34   private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$
35   private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$
36
37   public static final int ERROR = 2;
38   public static final int WARNING = 1;
39   public static final int INFO = 0;
40
41   public static final boolean DEBUG = false;
42   //scanner token 
43   public Scanner scanner;
44
45   private IFile fileToParse;
46   private ArrayList phpList;
47
48   private int currentPHPString;
49   private boolean phpEnd;
50
51   private static HashMap keywordMap = null;
52   private String str;
53
54   // current character
55 //  char ch;
56   // current token
57   int token;
58
59   // row counter for syntax errors:
60   //int rowCount;
61   // column counter for syntax errors:
62   //int columnCount;
63
64   //int chIndx;
65   //
66   //    // current identifier
67   //    String identifier;
68
69   Long longNumber;
70   Double doubleNumber;
71
72   private String stringValue;
73
74   /** Contains the current expression. */
75  // private StringBuffer expression;
76
77   private boolean phpMode;
78
79   //    final static int TokenNameEOF = 0;
80   //    final static int TokenNameERROR = 1;
81   //    final static int TokenNameHTML = 2;
82   //
83   //    final static int TokenNameREMAINDER = 30;
84   //    final static int TokenNameNOT = 31;
85   //    final static int TokenNameDOT = 32;
86   //    final static int TokenNameXOR = 33;
87   //    final static int TokenNameDIVIDE = 34;
88   //    final static int TokenNameMULTIPLY = 35;
89   //    final static int TokenNameMINUS = 36;
90   //    final static int TokenNamePLUS = 37;
91   //    final static int TokenNameEQUAL_EQUAL = 38;
92   //    final static int TokenNameNOT_EQUAL = 39;
93   //    final static int TokenNameGREATER = 40;
94   //    final static int TokenNameGREATER_EQUAL = 41;
95   //    final static int TokenNameLESS = 42;
96   //    final static int TokenNameLESS_EQUAL = 43;
97   //    final static int TokenNameAND_AND = 44;
98   //    final static int TokenNameOR_OR = 45;
99   //    // final static int TokenNameHASH = 46; 
100   //    final static int TokenNameCOLON = 47;
101   //    final static int TokenNameDOT_EQUAL = 48;
102   //
103   //    final static int TokenNameEQUAL = 49;
104   //    final static int TokenNameMINUS_GREATER = 50; // ->
105   //    final static int TokenNameFOREACH = 51;
106   //    final static int TokenNameAND = 52;
107   //    //final static int TokenNameDOLLARLISTOPEN = 53;
108   //    final static int TokenNameTWIDDLE = 54;
109   //    final static int TokenNameTWIDDLE_EQUAL = 55;
110   //    final static int TokenNameREMAINDER_EQUAL = 56;
111   //    final static int TokenNameXOR_EQUAL = 57;
112   //    final static int TokenNameRIGHT_SHIFT_EQUAL = 58;
113   //    final static int TokenNameLEFT_SHIFT_EQUAL = 59;
114   //    final static int TokenNameAND_EQUAL = 60;
115   //    final static int TokenNameOR_EQUAL = 61;
116   //    final static int TokenNameQUESTION = 62;
117   //    final static int TokenNameCOLON_COLON = 63;
118   //    final static int TokenNameAT = 63;
119   //    // final static int TokenNameHEREDOC = 64;
120   //
121   //    final static int TokenNameDOLLAROPEN = 127;
122   //    final static int TokenNameLPAREN = 128;
123   //    final static int TokenNameRPAREN = 129;
124   //    final static int TokenNameLBRACE = 130;
125   //    final static int TokenNameRBRACE = 131;
126   //    final static int TokenNameLBRACKET = 132;
127   //    final static int TokenNameRBRACKET = 133;
128   //    final static int TokenNameCOMMA = 134;
129   //
130   //    final static int TokenNameStringLiteral = 136;
131   //    final static int TokenNameIdentifier = 138;
132   //    // final static int TokenNameDIGIT = 139;
133   //    final static int TokenNameSEMICOLON = 140;
134   //    // final static int TokenNameSLOT = 141;
135   //    // final static int TokenNameSLOTSEQUENCE = 142;
136   //    final static int TokenNameMINUS_MINUS = 144;
137   //    final static int TokenNamePLUS_PLUS = 145;
138   //    final static int TokenNamePLUS_EQUAL = 146;
139   //    final static int TokenNameDIVIDE_EQUAL = 147;
140   //    final static int TokenNameMINUS_EQUAL = 148;
141   //    final static int TokenNameMULTIPLY_EQUAL = 149;
142   //    final static int TokenNameVariable = 150;
143   //    final static int TokenNameIntegerLiteral = 151;
144   //    final static int TokenNameDoubleLiteral = 152;
145   //    final static int TokenNameStringInterpolated = 153;
146   //    final static int TokenNameStringConstant = 154;
147   //
148   //    final static int TokenNameLEFT_SHIFT = 155;
149   //    final static int TokenNameRIGHT_SHIFT = 156;
150   //    final static int TokenNameEQUAL_EQUAL_EQUAL = 157;
151   //    final static int TokenNameNOT_EQUAL_EQUAL = 158;
152   //    final static int TokenNameOR = 159;
153   //  final static int TokenNameAT = 153; // @
154   /**
155    *  Class Constructor.
156    *
157    *@param  s
158    *@param  sess  Description of Parameter
159    *@see
160    */
161   public Parser(IFile fileToParse) {
162     if (keywordMap == null) {
163       keywordMap = new HashMap();
164       for (int i = 0; i < PHP_KEYWORS.length; i++) {
165         keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
166       }
167     }
168     this.currentPHPString = 0;
169     this.fileToParse = fileToParse;
170     this.phpList = null;
171     this.str = "";
172     this.token = TokenNameEOF;
173 //    this.chIndx = 0;
174 //    this.rowCount = 1;
175 //    this.columnCount = 0;
176     this.phpEnd = false;
177     //   getNextToken();
178
179     this.initializeScanner();
180   }
181
182   public void initializeScanner() {
183     this.scanner = new Scanner(false, false, false, false);
184   }
185   /**
186    * Create marker for the parse error
187    */
188   private void setMarker(
189     String message,
190     int charStart,
191     int charEnd,
192     int errorLevel)
193     throws CoreException {
194     setMarker(fileToParse, message, charStart, charEnd, errorLevel);
195   }
196
197   public static void setMarker(
198     IFile file,
199     String message,
200     int charStart,
201     int charEnd,
202     int errorLevel)
203     throws CoreException {
204     if (file != null) {
205       Hashtable attributes = new Hashtable();
206       MarkerUtilities.setMessage(attributes, message);
207       switch (errorLevel) {
208         case ERROR :
209           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
210           break;
211         case WARNING :
212           attributes.put(
213             IMarker.SEVERITY,
214             new Integer(IMarker.SEVERITY_WARNING));
215           break;
216         case INFO :
217           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
218           break;
219       }
220       MarkerUtilities.setCharStart(attributes, charStart);
221       MarkerUtilities.setCharEnd(attributes, charEnd);
222       // setLineNumber(attributes, lineNumber);
223       MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
224     }
225   }
226
227   /**
228    * This method will throw the SyntaxError.
229    * It will add the good lines and columns to the Error
230    * @param error the error message
231    * @throws SyntaxError the error raised
232    */
233   private void throwSyntaxError(String error) {
234
235 //    if (str.length() < chIndx) {
236 //      chIndx--;
237 //    }
238 //    // read until end-of-line
239 //    int eol = chIndx;
240 //    while (str.length() > eol) {
241 //      ch = str.charAt(eol++);
242 //      if (ch == '\n') {
243 //        eol--;
244 //        break;
245 //      }
246 //    }
247 //    throw new SyntaxError(
248 //      rowCount,
249 //      chIndx - columnCount + 1,
250 //      str.substring(columnCount, eol),
251 //      error);
252     throw new SyntaxError(
253       1,
254       1,
255       "",
256       error);
257   }
258
259   /**
260    * This method will throw the SyntaxError.
261    * It will add the good lines and columns to the Error
262    * @param error the error message
263    * @throws SyntaxError the error raised
264    */
265   private void throwSyntaxError(String error, int startRow) {
266     throw new SyntaxError(startRow, 0, " ", error);
267   }
268
269   /**
270    *  Method Declaration.
271    *
272    *@see
273    */
274 //  private void getChar() {
275 //    if (str.length() > chIndx) {
276 //      ch = str.charAt(chIndx++);
277 //
278 //      return;
279 //    }
280 //
281 //    chIndx = str.length() + 1;
282 //    ch = ' ';
283 //    //  token = TokenNameEOF;
284 //    phpEnd = true;
285 //  }
286
287   /**
288    * gets the next token from input
289    */
290   private void getNextToken() throws CoreException {
291     try {
292       token = scanner.getNextToken();
293       if (DEBUG) {
294         int currentEndPosition = scanner.getCurrentTokenEndPosition();
295         int currentStartPosition = scanner.getCurrentTokenStartPosition();
296
297         System.out.print(
298           currentStartPosition + "," + currentEndPosition + ": ");
299         System.out.println(scanner.toStringAction(token));
300       }
301     } catch (InvalidInputException e) {
302       token = TokenNameERROR;
303     }
304     return;
305
306     //          boolean phpFound = false;
307     //          char ch2;
308     //
309     //          phpEnd = false;
310     //          try {
311     //                  if (!phpMode) {
312     //
313     //                          while (str.length() > chIndx) {
314     //                                  token = TokenNameERROR;
315     //                                  ch = str.charAt(chIndx++);
316     //
317     //                                  if (ch == '\n') {
318     //                                          rowCount++;
319     //                                  }
320     //                                  if (ch == '<') {
321     //                                          ch2 = str.charAt(chIndx++);
322     //                                          if (ch2 == '?') {
323     //                                                  ch2 = str.charAt(chIndx++);
324     //                                                  if (Character.isWhitespace(ch2)) {
325     //                                                          // php start
326     //                                                          phpMode = true;
327     //                                                          phpFound = true;
328     //                                                          break;
329     //                                                  } else if (ch2 == 'p' || ch2 == 'P') {
330     //                                                          ch2 = str.charAt(chIndx++);
331     //                                                          if (ch2 == 'h' || ch2 == 'H') {
332     //                                                                  ch2 = str.charAt(chIndx++);
333     //                                                                  if (ch2 == 'p' || ch2 == 'P') {
334     //                                                                          phpMode = true;
335     //                                                                          phpFound = true;
336     //                                                                          break;
337     //                                                                  }
338     //                                                                  chIndx--;
339     //                                                          }
340     //                                                          chIndx--;
341     //                                                  }
342     //                                                  chIndx--;
343     //                                          }
344     //                                          chIndx--;
345     //                                  }
346     //                          }
347     //
348     //                  }
349     //
350     //                  if (phpMode) {
351     //                          while (str.length() > chIndx) {
352     //                                  ch = str.charAt(chIndx++);
353     //                                  token = TokenNameERROR;
354     //                                  if (ch == '\n') {
355     //                                          rowCount++;
356     //                                          columnCount = chIndx;
357     //                                          continue; // while loop
358     //                                  }
359     //                                  if (str.length() == chIndx) {
360     //                                          phpEnd = true;
361     //                                  }
362     //                                  if (!Character.isWhitespace(ch)) {
363     //                                          if (ch == '$') {
364     //                                                  if (str.length() > chIndx) {
365     //                                                          if (str.charAt(chIndx) == '{') {
366     //                                                                  chIndx++;
367     //                                                                  token = TokenNameDOLLAROPEN;
368     //                                                                  return;
369     //                                                          }
370     //                                                  }
371     //                                                  getIdentifier();
372     //                                                  return;
373     //                                          }
374     //                                          if ((ch >= 'a' && ch <= 'z')
375     //                                                  || (ch >= 'A' && ch <= 'Z')
376     //                                                  || (ch == '_')
377     //                                                  || (ch == '$')) {
378     //                                                  getIdentifier();
379     //                                                  return;
380     //                                          }
381     //                                          if (ch >= '0' && ch <= '9') {
382     //                                                  getNumber();
383     //                                                  return;
384     //                                          }
385     //                                          if (ch == '/') {
386     //                                                  if (str.length() > chIndx) {
387     //                                                          if (str.charAt(chIndx) == '/') {
388     //                                                                  ch = '/';
389     //                                                                  chIndx++;
390     //                                                                  // read comment until end of line:
391     //                                                                  while ((str.length() > chIndx)
392     //                                                                          && (ch != '\n')) {
393     //                                                                          ch = str.charAt(chIndx++);
394     //                                                                          if (ch == '?') {
395     //                                                                                  ch2 = str.charAt(chIndx);
396     //                                                                                  if (ch2 == '>') {
397     //                                                                                          chIndx++;
398     //                                                                                          token = TokenNameHTML;
399     //                                                                                          // php end
400     //                                                                                          phpMode = false;
401     //                                                                                          phpEnd = true;
402     //                                                                                          return;
403     //                                                                                  }
404     //                                                                          }
405     //                                                                  }
406     //                                                                  rowCount++;
407     //                                                                  continue;
408     //
409     //                                                          } else if (str.charAt(chIndx) == '*') {
410     //                                                                  chIndx++;
411     //                                                                  // multi line comment:
412     //                                                                  while (str.length() > chIndx) {
413     //                                                                          if (str.charAt(chIndx) == '*'
414     //                                                                                  && (str.length() > (chIndx + 1))
415     //                                                                                  && str.charAt(chIndx + 1) == '/') {
416     //                                                                                  chIndx += 2;
417     //                                                                                  break;
418     //                                                                          }
419     //                                                                          ch = str.charAt(chIndx++);
420     //                                                                          if (ch == '\n') {
421     //                                                                                  rowCount++;
422     //                                                                                  columnCount = chIndx;
423     //                                                                          }
424     //                                                                  }
425     //                                                                  continue;
426     //                                                          }
427     //                                                  }
428     //                                          } else if (ch == '#') {
429     //                                                  // read comment until end of line:
430     //                                                  while ((str.length() > chIndx) && (ch != '\n')) {
431     //                                                          ch = str.charAt(chIndx++);
432     //                                                          if (ch == '?') {
433     //                                                                  ch2 = str.charAt(chIndx);
434     //                                                                  if (ch2 == '>') {
435     //                                                                          chIndx++;
436     //                                                                          token = TokenNameHTML;
437     //                                                                          // php end
438     //                                                                          phpMode = false;
439     //                                                                          phpEnd = true;
440     //                                                                          return;
441     //                                                                  }
442     //                                                          }
443     //                                                  }
444     //                                                  rowCount++;
445     //                                                  continue;
446     //
447     //                                          } else if (ch == '"') {
448     //                                                  getString(
449     //                                                          '"',
450     //                                                          TokenNameStringInterpolated,
451     //                                                          "Open string character '\"' at end of file.");
452     //                                                  return;
453     //                                          } else if (ch == '\'') {
454     //                                                  getString(
455     //                                                          '\'',
456     //                                                          TokenNameStringConstant,
457     //                                                          "Open string character \"'\" at end of file.");
458     //                                                  return;
459     //                                          } else if (ch == '`') {
460     //                                                  getString(
461     //                                                          '`',
462     //                                                          TokenNameStringConstant,
463     //                                                          "Open string character \"`\" at end of file.");
464     //                                                  setMarker(
465     //                                                          "Other string delimiters prefered (found \"`\").",
466     //                                                          rowCount,
467     //                                                          PHPParser.INFO);
468     //                                                  return;
469     //                                          }
470     //
471     //                                          switch (ch) {
472     //
473     //                                                  case '(' :
474     //                                                          token = TokenNameLPAREN;
475     //
476     //                                                          break;
477     //                                                  case ')' :
478     //                                                          token = TokenNameRPAREN;
479     //
480     //                                                          break;
481     //                                                  case '{' :
482     //                                                          token = TokenNameLBRACE;
483     //
484     //                                                          break;
485     //                                                  case '}' :
486     //                                                          token = TokenNameRBRACE;
487     //
488     //                                                          break;
489     //                                                  case '[' :
490     //                                                          token = TokenNameLBRACKET;
491     //
492     //                                                          break;
493     //                                                  case ']' :
494     //                                                          token = TokenNameRBRACKET;
495     //
496     //                                                          break;
497     //                                                  case ',' :
498     //                                                          token = TokenNameCOMMA;
499     //
500     //                                                          break;
501     //                                                  case '?' :
502     //                                                          token = TokenNameQUESTION;
503     //                                                          if (str.length() > chIndx) {
504     //                                                                  if (str.charAt(chIndx) == '>') {
505     //                                                                          chIndx++;
506     //                                                                          token = TokenNameHTML;
507     //                                                                          // php end
508     //                                                                          phpMode = false;
509     //                                                                          phpEnd = true;
510     //                                                                          break;
511     //                                                                  }
512     //                                                          }
513     //
514     //                                                          break;
515     //                                                  case '@' :
516     //                                                          token = TokenNameAT;
517     //                                                          break;
518     //                                                  case '~' :
519     //                                                          token = TokenNameTWIDDLE;
520     //                                                          if (str.length() > chIndx) {
521     //                                                                  if (str.charAt(chIndx) == '=') {
522     //                                                                          chIndx++;
523     //                                                                          token = TokenNameTWIDDLE_EQUAL;
524     //
525     //                                                                          break;
526     //                                                                  }
527     //                                                          }
528     //                                                          break;
529     //                                                  case '.' :
530     //                                                          token = TokenNameDOT;
531     //                                                          if (str.length() > chIndx) {
532     //                                                                  if (str.charAt(chIndx) == '=') {
533     //                                                                          chIndx++;
534     //                                                                          token = TokenNameDOT_EQUAL;
535     //
536     //                                                                          break;
537     //                                                                  }
538     //                                                          }
539     //
540     //                                                          break;
541     //                                                  case '"' :
542     //                                                          token = TokenNameStringLiteral;
543     //
544     //                                                          break;
545     //                                                  case '%' :
546     //                                                          token = TokenNameREMAINDER;
547     //                                                          if (str.length() > chIndx) {
548     //                                                                  if (str.charAt(chIndx) == '=') {
549     //                                                                          chIndx++;
550     //                                                                          token = TokenNameREMAINDER_EQUAL;
551     //
552     //                                                                          break;
553     //                                                                  }
554     //                                                          }
555     //                                                          break;
556     //                                                  case ';' :
557     //                                                          token = TokenNameSEMICOLON;
558     //
559     //                                                          break;
560     //                                                  case '^' :
561     //                                                          token = TokenNameXOR;
562     //                                                          if (str.length() > chIndx) {
563     //                                                                  if (str.charAt(chIndx) == '=') {
564     //                                                                          chIndx++;
565     //                                                                          token = TokenNameXOR_EQUAL;
566     //
567     //                                                                          break;
568     //                                                                  }
569     //                                                          }
570     //                                                          break;
571     //                                                  case '/' :
572     //                                                          token = TokenNameDIVIDE;
573     //
574     //                                                          if (str.length() > chIndx) {
575     //                                                                  if (str.charAt(chIndx) == '=') {
576     //                                                                          chIndx++;
577     //                                                                          token = TokenNameDIVIDE_EQUAL;
578     //
579     //                                                                          break;
580     //                                                                  }
581     //                                                          }
582     //
583     //                                                          break;
584     //                                                  case '*' :
585     //                                                          token = TokenNameMULTIPLY;
586     //                                                          if (str.length() > chIndx) {
587     //                                                                  if (str.charAt(chIndx) == '*') {
588     //                                                                          chIndx++;
589     //                                                                          token = TokenNameXOR;
590     //
591     //                                                                          break;
592     //                                                                  }
593     //                                                                  if (str.charAt(chIndx) == '=') {
594     //                                                                          chIndx++;
595     //                                                                          token = TokenNameMULTIPLY_EQUAL;
596     //
597     //                                                                          break;
598     //                                                                  }
599     //                                                          }
600     //
601     //                                                          break;
602     //                                                  case '+' :
603     //                                                          token = TokenNamePLUS;
604     //                                                          if (str.length() > chIndx) {
605     //                                                                  if (str.charAt(chIndx) == '+') {
606     //                                                                          chIndx++;
607     //                                                                          token = TokenNamePLUS_PLUS;
608     //
609     //                                                                          break;
610     //                                                                  }
611     //                                                                  if (str.charAt(chIndx) == '=') {
612     //                                                                          chIndx++;
613     //                                                                          token = TokenNamePLUS_EQUAL;
614     //
615     //                                                                          break;
616     //                                                                  }
617     //                                                          }
618     //                                                          break;
619     //                                                  case '-' :
620     //                                                          token = TokenNameMINUS;
621     //                                                          if (str.length() > chIndx) {
622     //                                                                  if (str.charAt(chIndx) == '-') {
623     //                                                                          chIndx++;
624     //                                                                          token = TokenNameMINUS_MINUS;
625     //
626     //                                                                          break;
627     //                                                                  }
628     //                                                                  if (str.charAt(chIndx) == '=') {
629     //                                                                          chIndx++;
630     //                                                                          token = TokenNameMINUS_EQUAL;
631     //
632     //                                                                          break;
633     //                                                                  }
634     //                                                                  if (str.charAt(chIndx) == '>') {
635     //                                                                          chIndx++;
636     //                                                                          token = TokenNameMINUS_GREATER;
637     //
638     //                                                                          break;
639     //                                                                  }
640     //                                                          }
641     //
642     //                                                          break;
643     //                                                  case '=' :
644     //                                                          token = TokenNameEQUAL;
645     //
646     //                                                          if (str.length() > chIndx) {
647     //                                                                  ch = str.charAt(chIndx);
648     //
649     //                                                                  if (ch == '=') {
650     //                                                                          chIndx++;
651     //                                                                          token = TokenNameEQUAL_EQUAL;
652     //                                                                          if (str.length() > chIndx) {
653     //                                                                                  ch = str.charAt(chIndx);
654     //
655     //                                                                                  if (ch == '=') {
656     //                                                                                          chIndx++;
657     //                                                                                          token =
658     //                                                                                                  TokenNameEQUAL_EQUAL_EQUAL;
659     //                                                                                  }
660     //                                                                          }
661     //                                                                          break;
662     //                                                                  }
663     //                                                                  if (ch == '>') {
664     //                                                                          chIndx++;
665     //                                                                          token = TokenNameEQUAL_GREATER;
666     //
667     //                                                                          break;
668     //                                                                  }
669     //                                                          }
670     //
671     //                                                          break;
672     //                                                  case '!' :
673     //                                                          token = TokenNameNOT;
674     //
675     //                                                          if (str.length() > chIndx) {
676     //                                                                  if (str.charAt(chIndx) == '=') {
677     //                                                                          chIndx++;
678     //                                                                          token = TokenNameNOT_EQUAL;
679     //                                                                          if (str.length() > chIndx) {
680     //                                                                                  ch = str.charAt(chIndx);
681     //
682     //                                                                                  if (ch == '=') {
683     //                                                                                          chIndx++;
684     //                                                                                          token =
685     //                                                                                                  TokenNameNOT_EQUAL_EQUAL;
686     //                                                                                  }
687     //                                                                          }
688     //                                                                          break;
689     //                                                                  }
690     //                                                          }
691     //
692     //                                                          break;
693     //                                                  case '>' :
694     //                                                          token = TokenNameGREATER;
695     //
696     //                                                          if (str.length() > chIndx) {
697     //                                                                  if (str.charAt(chIndx) == '=') {
698     //                                                                          chIndx++;
699     //                                                                          token = TokenNameGREATER_EQUAL;
700     //                                                                          break;
701     //                                                                  }
702     //                                                                  if (str.charAt(chIndx) == '>') {
703     //                                                                          chIndx++;
704     //                                                                          token = TokenNameRIGHT_SHIFT;
705     //                                                                          if (str.length() > chIndx) {
706     //                                                                                  if (str.charAt(chIndx) == '=') {
707     //                                                                                          chIndx++;
708     //                                                                                          token =
709     //                                                                                                  TokenNameRIGHT_SHIFT_EQUAL;
710     //                                                                                          break;
711     //                                                                                  }
712     //                                                                          }
713     //                                                                          break;
714     //                                                                  }
715     //                                                          }
716     //
717     //                                                          break;
718     //                                                  case '<' :
719     //                                                          token = TokenNameLESS;
720     //
721     //                                                          if (str.length() > chIndx) {
722     //                                                                  if (str.charAt(chIndx) == '=') {
723     //                                                                          chIndx++;
724     //                                                                          token = TokenNameLESS_EQUAL;
725     //
726     //                                                                          break;
727     //                                                                  }
728     //                                                                  if (str.charAt(chIndx) == '<') {
729     //                                                                          chIndx++;
730     //                                                                          token = TokenNameLEFT_SHIFT;
731     //                                                                          if (str.charAt(chIndx) == '<') {
732     //                                                                                  // heredoc
733     //                                                                                  int startRow = rowCount;
734     //                                                                                  if (str.length() > chIndx) {
735     //
736     //                                                                                          ch = str.charAt(++chIndx);
737     //                                                                                          if ((ch >= 'a' && ch <= 'z')
738     //                                                                                                  || (ch >= 'A' && ch <= 'Z')
739     //                                                                                                  || (ch == '_')) {
740     //                                                                                                  chIndx++;
741     //                                                                                                  getIdentifier();
742     //                                                                                                  token =
743     //                                                                                                          TokenNameStringConstant;
744     //                                                                                                  while (str.length()
745     //                                                                                                          > chIndx) {
746     //                                                                                                          ch =
747     //                                                                                                                  str.charAt(
748     //                                                                                                                          chIndx++);
749     //                                                                                                          if (ch == '\n') {
750     //                                                                                                                  if (str.length()
751     //                                                                                                                          >= chIndx
752     //                                                                                                                                  + identifier
753     //                                                                                                                                          .length()) {
754     //                                                                                                                          if (str
755     //                                                                                                                                  .substring(
756     //                                                                                                                                          chIndx,
757     //                                                                                                                                          chIndx
758     //                                                                                                                                                  + identifier
759     //                                                                                                                                                          .length())
760     //                                                                                                                                  .equals(identifier)) {
761     //                                                                                                                                  chIndx
762     //                                                                                                                                          += identifier
763     //                                                                                                                                                  .length();
764     //                                                                                                                                  return;
765     //                                                                                                                          }
766     //                                                                                                                  }
767     //                                                                                                          }
768     //                                                                                                  }
769     //                                                                                          }
770     //                                                                                  }
771     //                                                                                  throwSyntaxError(
772     //                                                                                          "Open heredoc syntax after operator '<<<'.",
773     //                                                                                          startRow);
774     //                                                                          } else if (str.charAt(chIndx) == '=') {
775     //                                                                                  chIndx++;
776     //                                                                                  token = TokenNameLEFT_SHIFT_EQUAL;
777     //                                                                                  break;
778     //                                                                          }
779     //                                                                          break;
780     //                                                                  }
781     //                                                          }
782     //
783     //                                                          break;
784     //
785     //                                                  case '|' :
786     //                                                          token = TokenNameOR;
787     //
788     //                                                          if (str.length() > chIndx) {
789     //                                                                  if (str.charAt(chIndx) == '|') {
790     //                                                                          chIndx++;
791     //                                                                          token = TokenNameOR_OR;
792     //                                                                          break;
793     //                                                                  }
794     //                                                                  if (str.charAt(chIndx) == '=') {
795     //                                                                          chIndx++;
796     //                                                                          token = TokenNameOR_EQUAL;
797     //                                                                          break;
798     //                                                                  }
799     //                                                          }
800     //
801     //                                                          break;
802     //                                                  case '&' :
803     //                                                          token = TokenNameAND;
804     //                                                          if (str.length() > chIndx) {
805     //                                                                  if (str.charAt(chIndx) == '&') {
806     //                                                                          chIndx++;
807     //                                                                          token = TokenNameAND_AND;
808     //                                                                          break;
809     //                                                                  }
810     //                                                                  if (str.charAt(chIndx) == '=') {
811     //                                                                          chIndx++;
812     //                                                                          token = TokenNameAND_EQUAL;
813     //                                                                          break;
814     //                                                                  }
815     //                                                                  break;
816     //                                                          }
817     //
818     //                                                          break;
819     //                                                  case ':' :
820     //                                                          token = TokenNameCOLON;
821     //                                                          if (str.length() > chIndx) {
822     //                                                                  if (str.charAt(chIndx) == ':') {
823     //                                                                          chIndx++;
824     //                                                                          token = TokenNameCOLON_COLON;
825     //                                                                  }
826     //                                                          }
827     //                                                          break;
828     //                                                          //              case '#' :
829     //                                                          //                token = TokenNameHASH;
830     //                                                          //
831     //                                                          //                break;
832     //                                                          //          case '@' :
833     //                                                          //            token = TokenNameAT;
834     //                                                          //
835     //                                                          //            break;
836     //                                                  default :
837     //                                                          throwSyntaxError(
838     //                                                                  "unexpected character: '" + ch + "'");
839     //                                          }
840     //
841     //                                          if (token == TokenNameERROR) {
842     //                                                  throwSyntaxError("token not found");
843     //                                          }
844     //
845     //                                          return;
846     //                                  }
847     //                          }
848     //                  }
849     //          } catch (StringIndexOutOfBoundsException e) {
850     //                  // catched from charAt
851     //          }
852     //
853     //          chIndx = str.length() + 1;
854     //          ch = ' ';
855     //          token = TokenNameEOF;
856     //          phpEnd = true;
857     //          //PHPString temp;
858     //          //    if (phpList != null) {
859     //          //      if (currentPHPString < phpList.size()) {
860     //          //        token = TokenNameUNDEFINED;
861     //          //        temp = (PHPString) phpList.get(currentPHPString++);
862     //          //        this.str = temp.getPHPString();
863     //          //        this.token = TokenNameEOF;
864     //          //        this.chIndx = 0;
865     //          //        this.rowCount = temp.getLineNumber();
866     //          //        this.columnCount = 0;
867     //          //        getNextToken();
868     //          //        phpEnd = true;
869     //          //      } else {
870     //          //        token = TokenNameUNDEFINED;
871     //          //        return;
872     //          //      }
873     //          //    }
874   }
875
876   //    /**
877   //     * Get an identifier.
878   //     */
879   //    private void getIdentifier() {
880   //            //  StringBuffer ident = new StringBuffer();
881   //            int startPosition = chIndx - 1;
882   //            //    ident.append(ch);
883   //            if (ch == '$') {
884   //                    getChar();
885   //                    // attention recursive call:
886   //                    getIdentifier();
887   //                    token = TokenNameVariable;
888   //                    return;
889   //            } else {
890   //                    token = TokenNameIdentifier;
891   //            }
892   //
893   //            getChar();
894   //
895   //            //this will read the buffer until the next character is a forbidden character for identifier
896   //            while ((ch >= 'a' && ch <= 'z')
897   //                    || (ch >= 'A' && ch <= 'Z')
898   //                    || (ch >= '0' && ch <= '9')
899   //                    || (ch == '_')) {
900   //                    //    ident.append(ch);
901   //                    getChar();
902   //            }
903   //            int endPosition = chIndx--;
904   //            int length = (--endPosition) - startPosition;
905   //
906   //            identifier = str.substring(startPosition, endPosition);
907   //            // System.out.println(identifier);
908   //
909   //            // determine if this identitfer is a keyword
910   //            // @todo improve this in future version
911   //            Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
912   //            if (i != null) {
913   //                    token = i.intValue();
914   //            }
915   //    }
916
917   /**
918    * Get a number.
919    * if it's a <code>double</code> the number will be stored in <code>doubleNumber</code> and the token will have the
920    * value {@link Parser#TokenNameDOUBLE_NUMBER}<br />
921    * if it's a <code>double</code> the number will be stored in <code>longNumber</code> and the token will have the
922    * value {@link Parser#TokenNameINT_NUMBER}
923    */
924 //  private void getNumber() {
925 //    StringBuffer inum = new StringBuffer();
926 //    char dFlag = ' ';
927 //    int numFormat = 10;
928 //
929 //    // save first digit
930 //    char firstCh = ch;
931 //    inum.append(ch);
932 //
933 //    getChar();
934 //    // determine number conversions:
935 //    if (firstCh == '0') {
936 //      switch (ch) {
937 //        case 'b' :
938 //          numFormat = 2;
939 //          getChar();
940 //          break;
941 //        case 'B' :
942 //          numFormat = 2;
943 //          getChar();
944 //          break;
945 //        case 'o' :
946 //          numFormat = 8;
947 //          getChar();
948 //          break;
949 //        case 'O' :
950 //          numFormat = 8;
951 //          getChar();
952 //          break;
953 //        case 'x' :
954 //          numFormat = 16;
955 //          getChar();
956 //          break;
957 //        case 'X' :
958 //          numFormat = 16;
959 //          getChar();
960 //          break;
961 //      }
962 //    }
963 //
964 //    if (numFormat == 16) {
965 //      while ((ch >= '0' && ch <= '9')
966 //        || (ch >= 'a' && ch <= 'f')
967 //        || (ch >= 'A' && ch <= 'F')) {
968 //        inum.append(ch);
969 //        getChar();
970 //      }
971 //    } else {
972 //      while ((ch >= '0' && ch <= '9')
973 //        || (ch == '.')
974 //        || (ch == 'E')
975 //        || (ch == 'e')) {
976 //        if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
977 //          if (ch == '.' && dFlag != ' ') {
978 //            break;
979 //          }
980 //          if ((dFlag == 'E') || (dFlag == 'e')) {
981 //            break;
982 //          }
983 //          dFlag = ch;
984 //          inum.append(ch);
985 //          getChar();
986 //          if ((ch == '-') || (ch == '+')) {
987 //            inum.append(ch);
988 //            getChar();
989 //          }
990 //        } else {
991 //          inum.append(ch);
992 //          getChar();
993 //        }
994 //      }
995 //    }
996 //    chIndx--;
997 //
998 //    try {
999 //      if (dFlag != ' ') {
1000 //        doubleNumber = new Double(inum.toString());
1001 //        token = TokenNameDoubleLiteral;
1002 //        return;
1003 //      } else {
1004 //        longNumber = Long.valueOf(inum.toString(), numFormat);
1005 //        token = TokenNameIntegerLiteral;
1006 //        return;
1007 //      }
1008 //
1009 //    } catch (Throwable e) {
1010 //      throwSyntaxError("Number format error: " + inum.toString());
1011 //    }
1012 //  }
1013 //
1014 //  /**
1015 //   * Get a String.
1016 //   * @param openChar the opening char ('\'', '"', '`')
1017 //   * @param typeString the type of string {@link #TokenNameSTRING_CONSTANT},{@link #TokenNameINTERPOLATED_STRING}
1018 //   * @param errorMsg the error message in case of parse error in the string
1019 //   */
1020 //  private void getString(
1021 //    final char openChar,
1022 //    final int typeString,
1023 //    final String errorMsg) {
1024 //    StringBuffer sBuffer = new StringBuffer();
1025 //    boolean openString = true;
1026 //    int startRow = rowCount;
1027 //    while (str.length() > chIndx) {
1028 //      ch = str.charAt(chIndx++);
1029 //      if (ch == '\\') {
1030 //        sBuffer.append(ch);
1031 //        if (str.length() > chIndx) {
1032 //          ch = str.charAt(chIndx++);
1033 //          sBuffer.append(ch);
1034 //        }
1035 //      } else if (ch == openChar) {
1036 //        openString = false;
1037 //        break;
1038 //      } else if (ch == '\n') {
1039 //        rowCount++;
1040 //        columnCount = chIndx;
1041 //      } else {
1042 //        sBuffer.append(ch);
1043 //      }
1044 //    }
1045 //    if (openString) {
1046 //      if (typeString == TokenNameStringConstant) {
1047 //        throwSyntaxError(errorMsg, startRow);
1048 //      } else {
1049 //        throwSyntaxError(errorMsg);
1050 //      }
1051 //    }
1052 //    token = typeString;
1053 //    stringValue = sBuffer.toString();
1054 //  }
1055
1056   //    public void htmlParserTester(String input) {
1057   //            int lineNumber = 1;
1058   //            int startLineNumber = 1;
1059   //            int startIndex = 0;
1060   //            char ch;
1061   //            char ch2;
1062   //            boolean phpMode = false;
1063   //            boolean phpFound = false;
1064   //
1065   //            phpList = new ArrayList();
1066   //            currentPHPString = 0;
1067   //
1068   //            try {
1069   //                    int i = 0;
1070   //                    while (i < input.length()) {
1071   //                            ch = input.charAt(i++);
1072   //                            if (ch == '\n') {
1073   //                                    lineNumber++;
1074   //                            }
1075   //                            if ((!phpMode) && ch == '<') {
1076   //                                    ch2 = input.charAt(i++);
1077   //                                    if (ch2 == '?') {
1078   //                                            ch2 = input.charAt(i++);
1079   //                                            if (Character.isWhitespace(ch2)) {
1080   //                                                    // php start
1081   //                                                    phpMode = true;
1082   //                                                    phpFound = true;
1083   //                                                    startIndex = i;
1084   //                                                    startLineNumber = lineNumber;
1085   //                                                    continue;
1086   //                                            } else if (ch2 == 'p') {
1087   //                                                    ch2 = input.charAt(i++);
1088   //                                                    if (ch2 == 'h') {
1089   //                                                            ch2 = input.charAt(i++);
1090   //                                                            if (ch2 == 'p') {
1091   //                                                                    phpMode = true;
1092   //                                                                    phpFound = true;
1093   //                                                                    startIndex = i;
1094   //                                                                    startLineNumber = lineNumber;
1095   //                                                                    continue;
1096   //                                                            }
1097   //                                                            i--;
1098   //                                                    }
1099   //                                                    i--;
1100   //                                            } else if (ch2 == 'P') {
1101   //                                                    ch2 = input.charAt(i++);
1102   //                                                    if (ch2 == 'H') {
1103   //                                                            ch2 = input.charAt(i++);
1104   //                                                            if (ch2 == 'P') {
1105   //                                                                    phpMode = true;
1106   //                                                                    phpFound = true;
1107   //                                                                    startIndex = i;
1108   //                                                                    startLineNumber = lineNumber;
1109   //                                                                    continue;
1110   //                                                            }
1111   //                                                            i--;
1112   //                                                    }
1113   //                                                    i--;
1114   //                                            }
1115   //                                            i--;
1116   //                                    }
1117   //                                    i--;
1118   //                            }
1119   //
1120   //                            if (phpMode) {
1121   //                                    if (ch == '/' && i < input.length()) {
1122   //                                            ch2 = input.charAt(i++);
1123   //                                            if (ch2 == '/') {
1124   //                                                    while (i < input.length()) {
1125   //                                                            ch = input.charAt(i++);
1126   //                                                            if (ch == '?' && i < input.length()) {
1127   //                                                                    ch2 = input.charAt(i++);
1128   //                                                                    if (ch2 == '>') {
1129   //                                                                            // php end
1130   //                                                                            phpMode = false;
1131   //                                                                            phpList.add(
1132   //                                                                                    new PHPString(
1133   //                                                                                            input.substring(
1134   //                                                                                                    startIndex,
1135   //                                                                                                    i - 2),
1136   //                                                                                            startLineNumber));
1137   //                                                                            continue;
1138   //                                                                    }
1139   //                                                                    i--;
1140   //                                                            } else if (ch == '\n') {
1141   //                                                                    lineNumber++;
1142   //                                                                    break;
1143   //                                                            }
1144   //                                                    }
1145   //                                                    continue;
1146   //                                            } else if (ch2 == '*') {
1147   //                                                    // multi-line comment
1148   //                                                    while (i < input.length()) {
1149   //                                                            ch = input.charAt(i++);
1150   //                                                            if (ch == '\n') {
1151   //                                                                    lineNumber++;
1152   //                                                            } else if (ch == '*' && i < input.length()) {
1153   //                                                                    ch2 = input.charAt(i++);
1154   //                                                                    if (ch2 == '/') {
1155   //                                                                            break;
1156   //                                                                    }
1157   //                                                                    i--;
1158   //                                                            }
1159   //                                                    }
1160   //                                                    continue;
1161   //                                            } else {
1162   //                                                    i--;
1163   //                                            }
1164   //                                    } else if (ch == '#') {
1165   //                                            while (i < input.length()) {
1166   //                                                    ch = input.charAt(i++);
1167   //                                                    if (ch == '?' && i < input.length()) {
1168   //                                                            ch2 = input.charAt(i++);
1169   //                                                            if (ch2 == '>') {
1170   //                                                                    // php end
1171   //                                                                    phpMode = false;
1172   //                                                                    phpList.add(
1173   //                                                                            new PHPString(
1174   //                                                                                    input.substring(startIndex, i - 2),
1175   //                                                                                    startLineNumber));
1176   //                                                                    continue;
1177   //                                                            }
1178   //                                                            i--;
1179   //                                                    } else if (ch == '\n') {
1180   //                                                            lineNumber++;
1181   //                                                            break;
1182   //                                                    }
1183   //                                            }
1184   //                                            continue;
1185   //                                    } else if (ch == '"') {
1186   //                                            ch = ' ';
1187   //                                            while (i < input.length()) {
1188   //                                                    ch = input.charAt(i++);
1189   //                                                    if (ch == '\n') {
1190   //                                                            lineNumber++;
1191   //                                                    } else if (
1192   //                                                            ch == '\\' && i < input.length()) { // escape
1193   //                                                            i++;
1194   //                                                    } else if (ch == '"') {
1195   //                                                            break;
1196   //                                                    }
1197   //                                            }
1198   //                                            continue;
1199   //                                    } else if (ch == '\'') {
1200   //                                            ch = ' ';
1201   //                                            while (i < input.length()) {
1202   //                                                    ch = input.charAt(i++);
1203   //                                                    if (ch == '\n') {
1204   //                                                            lineNumber++;
1205   //                                                    } else if (
1206   //                                                            ch == '\\' && i < input.length()) { // escape
1207   //                                                            i++;
1208   //                                                    } else if (ch == '\'') {
1209   //                                                            break;
1210   //                                                    }
1211   //                                            }
1212   //                                            continue;
1213   //                                    }
1214   //
1215   //                                    if (ch == '?' && i < input.length()) {
1216   //                                            ch2 = input.charAt(i++);
1217   //                                            if (ch2 == '>') {
1218   //                                                    // php end
1219   //                                                    phpMode = false;
1220   //                                                    phpList.add(
1221   //                                                            new PHPString(
1222   //                                                                    input.substring(startIndex, i - 2),
1223   //                                                                    startLineNumber));
1224   //                                                    continue;
1225   //                                            }
1226   //                                            i--;
1227   //                                    }
1228   //                            }
1229   //                    }
1230   //
1231   //                    if (!phpFound) {
1232   //                            setMarker(
1233   //                                    "No PHP source code found.",
1234   //                                    lineNumber,
1235   //                                    PHPParser.INFO);
1236   //                    } else {
1237   //                            if (phpMode) {
1238   //                                    setMarker(
1239   //                                            "Open PHP tag at end of file.",
1240   //                                            lineNumber,
1241   //                                            PHPParser.INFO);
1242   //                                    phpList.add(
1243   //                                            new PHPString(
1244   //                                                    input.substring(startIndex, i - 2),
1245   //                                                    startLineNumber));
1246   //                            }
1247   //                            //        for (int j=0;j<phpList.size();j++) {
1248   //                            //          String temp = ((PHPString)phpList.get(j)).getPHPString();
1249   //                            //          int startIndx = temp.length()-10;
1250   //                            //          if (startIndx<0) {
1251   //                            //            startIndx = 0;
1252   //                            //          }
1253   //                            //          System.out.println(temp.substring(startIndx)+"?>");
1254   //                            //        }
1255   //                            phpParserTester(null, 1);
1256   //                            //        PHPString temp;
1257   //                            //        for(int j=0;j<phpList.size();j++) {
1258   //                            //          temp = (PHPString) phpList.get(j);
1259   //                            //          parser.start(temp.getPHPString(), temp.getLineNumber());
1260   //                            //        }
1261   //                    }
1262   //            } catch (CoreException e) {
1263   //            }
1264   //    }
1265
1266   public void phpParserTester(String s, int rowCount) throws CoreException {
1267     this.str = s;
1268     if (s == null) {
1269       if (phpList.size() != 0) {
1270         this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
1271       }
1272     }
1273     this.token = TokenNameEOF;
1274 //    this.chIndx = 0;
1275 //    this.rowCount = rowCount;
1276 //    this.columnCount = 0;
1277     this.phpEnd = false;
1278     this.phpMode = true;
1279     scanner.setSource(s.toCharArray());
1280     scanner.setPHPMode(true);
1281     getNextToken();
1282     do {
1283       try {
1284         if (token != TokenNameEOF && token != TokenNameERROR) {
1285           statementList();
1286         }
1287         if (token != TokenNameEOF && token != TokenNameERROR) {
1288           if (token == TokenNameRPAREN) {
1289             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1290           }
1291           if (token == TokenNameRBRACE) {
1292             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1293           }
1294           if (token == TokenNameRBRACKET) {
1295             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1296           }
1297
1298           if (token == TokenNameLPAREN) {
1299             throwSyntaxError("Read character '('; end-of-file not reached.");
1300           }
1301           if (token == TokenNameLBRACE) {
1302             throwSyntaxError("Read character '{';  end-of-file not reached.");
1303           }
1304           if (token == TokenNameLBRACKET) {
1305             throwSyntaxError("Read character '[';  end-of-file not reached.");
1306           }
1307
1308           throwSyntaxError("End-of-file not reached.");
1309         }
1310         return;
1311       } catch (SyntaxError err) {
1312         if (s != null) {
1313           throw err;
1314         } else {
1315           //   setMarker(err.getMessage(), err.getLine(), ERROR);
1316           setMarker(
1317             err.getMessage(),
1318             scanner.getCurrentTokenStartPosition(),
1319             scanner.getCurrentTokenEndPosition(),
1320             ERROR);
1321         }
1322         // if an error occured,
1323         // try to find keywords 'class' or 'function'
1324         // to parse the rest of the string
1325         while (token != TokenNameEOF && token != TokenNameERROR) {
1326           if (token == TokenNameclass || token == TokenNamefunction) {
1327             break;
1328           }
1329           getNextToken();
1330         }
1331         if (token == TokenNameEOF || token == TokenNameERROR) {
1332           return;
1333         }
1334       }
1335     }
1336     while (true);
1337   }
1338
1339   /**
1340    * Parses a string with php tags
1341    * i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt; &lt;/body&gt;'
1342    */
1343   public void parse(String s) throws CoreException {
1344     this.str = s;
1345     this.token = TokenNameEOF;
1346 //    this.chIndx = 0;
1347 //    this.rowCount = 1;
1348 //    this.columnCount = 0;
1349     this.phpEnd = false;
1350     this.phpMode = false;
1351     /* scanner initialization */
1352     scanner.setSource(s.toCharArray());
1353     scanner.setPHPMode(false);
1354     getNextToken();
1355     do {
1356       try {
1357         if (token != TokenNameEOF && token != TokenNameERROR) {
1358           statementList();
1359         }
1360         if (token != TokenNameEOF && token != TokenNameERROR) {
1361           if (token == TokenNameRPAREN) {
1362             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1363           }
1364           if (token == TokenNameRBRACE) {
1365             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1366           }
1367           if (token == TokenNameRBRACKET) {
1368             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1369           }
1370
1371           if (token == TokenNameLPAREN) {
1372             throwSyntaxError("Read character '('; end-of-file not reached.");
1373           }
1374           if (token == TokenNameLBRACE) {
1375             throwSyntaxError("Read character '{';  end-of-file not reached.");
1376           }
1377           if (token == TokenNameLBRACKET) {
1378             throwSyntaxError("Read character '[';  end-of-file not reached.");
1379           }
1380
1381           throwSyntaxError("End-of-file not reached.");
1382         }
1383         return;
1384       } catch (SyntaxError sytaxErr1) {
1385         // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
1386         setMarker(
1387           sytaxErr1.getMessage(),
1388           scanner.getCurrentTokenStartPosition(),
1389           scanner.getCurrentTokenEndPosition(),
1390           ERROR);
1391         try {
1392           // if an error occured,
1393           // try to find keywords 'class' or 'function'
1394           // to parse the rest of the string
1395           while (token != TokenNameEOF && token != TokenNameERROR) {
1396             if (token == TokenNameclass || token == TokenNamefunction) {
1397               break;
1398             }
1399             getNextToken();
1400           }
1401           if (token == TokenNameEOF || token == TokenNameERROR) {
1402             return;
1403           }
1404         } catch (SyntaxError sytaxErr2) {
1405           //    setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
1406           setMarker(
1407             sytaxErr2.getMessage(),
1408             scanner.getCurrentTokenStartPosition(),
1409             scanner.getCurrentTokenEndPosition(),
1410             ERROR);
1411           return;
1412         }
1413       }
1414     }
1415     while (true);
1416   }
1417
1418   public PHPOutlineInfo parseInfo(Object parent, String s) {
1419     PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
1420     //    Stack stack = new Stack();
1421     //    stack.push(outlineInfo.getDeclarations());
1422
1423     this.str = s;
1424     this.token = TokenNameEOF;
1425 //    this.chIndx = 0;
1426 //    this.rowCount = 1;
1427 //    this.columnCount = 0;
1428     this.phpEnd = false;
1429     this.phpMode = false;
1430     scanner.setSource(s.toCharArray());
1431     scanner.setPHPMode(false);
1432
1433     try {
1434       getNextToken();
1435       parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
1436     } catch (CoreException e) {
1437     }
1438     return outlineInfo;
1439   }
1440
1441   private void parseDeclarations(
1442     PHPOutlineInfo outlineInfo,
1443     PHPSegmentWithChildren current,
1444     boolean goBack) {
1445     char[] ident;
1446     //   PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
1447     PHPSegmentWithChildren temp;
1448     int counter = 0;
1449     
1450     IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
1451     try {
1452       while (token != TokenNameEOF && token != TokenNameERROR) {
1453         if (token == TokenNameVariable) {
1454           ident = scanner.getCurrentIdentifierSource();
1455           outlineInfo.addVariable(new String(ident));
1456           getNextToken();
1457         } else if (token == TokenNamevar) {
1458           getNextToken();
1459           if (token == TokenNameVariable
1460             && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
1461             ident = scanner.getCurrentIdentifierSource();
1462             String variableName = new String(ident);
1463             outlineInfo.addVariable(variableName);
1464             getNextToken();
1465             if (token != TokenNameSEMICOLON) {
1466               
1467               getNextToken();
1468               ident = scanner.getCurrentTokenSource();
1469               if (token > TokenNameKEYWORD) {
1470                 current.add(new PHPVarDeclaration(current, variableName,
1471                 //                      chIndx - ident.length,
1472                 scanner.getCurrentTokenStartPosition(), new String(ident)));
1473               } else {
1474                 switch (token) {
1475                   case TokenNameVariable :
1476                     current.add(new PHPVarDeclaration(current, variableName,
1477                     //                      chIndx - ident.length,
1478                     scanner.getCurrentTokenStartPosition(), new String(ident)));
1479                     break;
1480                   case TokenNameIdentifier :
1481                     current.add(new PHPVarDeclaration(current, variableName,
1482                     //                    chIndx - ident.length,
1483                     scanner.getCurrentTokenStartPosition(), new String(ident)));
1484                     break;
1485                   case TokenNameDoubleLiteral :
1486                     current
1487                       .add(new PHPVarDeclaration(
1488                         current,
1489                         variableName + doubleNumber,
1490                     //   chIndx - ident.length,
1491                     scanner.getCurrentTokenStartPosition(), new String(ident)));
1492                     break;
1493                   case TokenNameIntegerLiteral :
1494                     current.add(new PHPVarDeclaration(current, variableName,
1495                     //                 chIndx - ident.length,
1496                     scanner.getCurrentTokenStartPosition(), new String(ident)));
1497                     break;
1498                   case TokenNameStringInterpolated :
1499                   case TokenNameStringLiteral :
1500                     current.add(new PHPVarDeclaration(current, variableName,
1501                     //              chIndx - ident.length,
1502                     scanner.getCurrentTokenStartPosition(), new String(ident)));
1503                     break;
1504                   case TokenNameStringConstant :
1505                     current.add(new PHPVarDeclaration(current, variableName,
1506                     //   chIndx - ident.length,
1507                     scanner.getCurrentTokenStartPosition(), new String(ident)));
1508                     break;
1509                   default :
1510                     current.add(new PHPVarDeclaration(current, variableName,
1511                     //               chIndx - ident.length
1512                     scanner.getCurrentTokenStartPosition()));
1513                     break;
1514                 }
1515               }
1516
1517             } else {
1518               ident = scanner.getCurrentIdentifierSource();
1519
1520               current.add(new PHPVarDeclaration(current, variableName,
1521               //          chIndx - ident.length
1522               scanner.getCurrentTokenStartPosition()));
1523             }
1524           }
1525         } else if (token == TokenNamefunction) {
1526           getNextToken();
1527           if (token == TokenNameAND) {
1528             getNextToken();
1529           }
1530           if (token == TokenNameIdentifier
1531             && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
1532             ident = scanner.getCurrentIdentifierSource();
1533             outlineInfo.addVariable(new String(ident));
1534             temp = new PHPFunctionDeclaration(current, new String(ident),
1535               // chIndx - ident.length
1536   scanner.getCurrentTokenStartPosition());
1537             current.add(temp);
1538             getNextToken();
1539             parseDeclarations(outlineInfo, temp, true);
1540           }
1541         } else if (token == TokenNameclass) {
1542           getNextToken();
1543           if (token == TokenNameIdentifier
1544             && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
1545             ident = scanner.getCurrentIdentifierSource();
1546             outlineInfo.addVariable(new String(ident));
1547             temp = new PHPClassDeclaration(current, new String(ident),
1548               //      chIndx - ident.len
1549   scanner.getCurrentTokenStartPosition());
1550             current.add(temp);
1551             //        stack.push(temp);
1552             getNextToken();
1553
1554             //skip tokens for classname, extends and others until we have the opening '{'
1555             while (token != TokenNameLBRACE
1556               && token != TokenNameEOF
1557               && token != TokenNameERROR) {
1558               getNextToken();
1559             }
1560             parseDeclarations(outlineInfo, temp, true);
1561             //        stack.pop();
1562           }
1563         } else if (token == TokenNameLBRACE) {
1564           getNextToken();
1565           counter++;
1566         } else if (token == TokenNameRBRACE) {
1567           getNextToken();
1568           --counter;
1569           if (counter == 0 && goBack) {
1570             return;
1571           }
1572         } else if (
1573           token == TokenNamerequire
1574             || token == TokenNamerequire_once
1575             || token == TokenNameinclude
1576             || token == TokenNameinclude_once) {
1577           ident =   scanner.getCurrentTokenSource(); 
1578          
1579           getNextToken();
1580           int startPosition = scanner.getCurrentTokenStartPosition();
1581           expression();
1582           char[] expr =   scanner.getCurrentTokenSource(startPosition); 
1583           outlineInfo.addVariable(new String(ident));
1584           current.add(new PHPReqIncDeclaration(current, new String(ident),
1585           //    chIndx - ident.length,
1586           startPosition, new String(expr)));
1587           getNextToken();
1588         } else {
1589           getNextToken();
1590         }
1591       }
1592     } catch (CoreException e) {
1593     } catch (SyntaxError sytaxErr) {
1594       try {
1595         //  setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
1596         setMarker(
1597           sytaxErr.getMessage(),
1598           scanner.getCurrentTokenStartPosition(),
1599           scanner.getCurrentTokenEndPosition(),
1600           ERROR);
1601       } catch (CoreException e) {
1602       }
1603     }
1604   }
1605
1606   private void statementList() throws CoreException {
1607     do {
1608       statement();
1609       if ((token == TokenNameRBRACE)
1610         || (token == TokenNamecase)
1611         || (token == TokenNamedefault)
1612         || (token == TokenNameelseif)
1613         || (token == TokenNameendif)
1614         || (token == TokenNameendfor)
1615         || (token == TokenNameendforeach)
1616         || (token == TokenNameendwhile)
1617         || (token == TokenNameendswitch)
1618         || (token == TokenNameEOF)
1619         || (token == TokenNameERROR)) {
1620         return;
1621       }
1622     } while (true);
1623   }
1624
1625   private void compoundStatement() throws CoreException {
1626     // '{' [statement-list] '}'
1627     if (token == TokenNameLBRACE) {
1628       getNextToken();
1629     } else {
1630       throwSyntaxError("'{' expected in compound-statement.");
1631     }
1632     if (token != TokenNameRBRACE) {
1633       statementList();
1634     }
1635     if (token == TokenNameRBRACE) {
1636       getNextToken();
1637     } else {
1638       throwSyntaxError("'}' expected in compound-statement.");
1639     }
1640   }
1641
1642   private void statement() throws CoreException {
1643     //   if (token > TokenNameKEYWORD && token != TokenNamelist && token != TokenNamenew) {
1644     //  char[] ident = scanner.getCurrentIdentifierSource();
1645     //  String keyword = new String(ident);
1646     if (token == TokenNameinclude || token == TokenNameinclude_once) {
1647       getNextToken();
1648       expression();
1649       if (token == TokenNameSEMICOLON) {
1650         getNextToken();
1651       } else {
1652         if (token != TokenNameStopPHP) {
1653           throwSyntaxError("';' character after 'include' or 'include_once' expected.");
1654         }
1655         getNextToken();
1656       }
1657       return;
1658     } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
1659       getNextToken();
1660       //constant();
1661       expression();
1662       if (token == TokenNameSEMICOLON) {
1663         getNextToken();
1664       } else {
1665         if (token != TokenNameStopPHP) {
1666           throwSyntaxError("';' character after 'require' or 'require_once' expected.");
1667         }
1668         getNextToken();
1669       }
1670       return;
1671     } else if (token == TokenNameif) {
1672       getNextToken();
1673       if (token == TokenNameLPAREN) {
1674         getNextToken();
1675       } else {
1676         throwSyntaxError("'(' expected after 'if' keyword.");
1677       }
1678       expression();
1679       if (token == TokenNameRPAREN) {
1680         getNextToken();
1681       } else {
1682         throwSyntaxError("')' expected after 'if' condition.");
1683       }
1684       ifStatement();
1685       return;
1686
1687     } else if (token == TokenNameswitch) {
1688       getNextToken();
1689       if (token == TokenNameLPAREN) {
1690         getNextToken();
1691       } else {
1692         throwSyntaxError("'(' expected after 'switch' keyword.");
1693       }
1694       expression();
1695       if (token == TokenNameRPAREN) {
1696         getNextToken();
1697       } else {
1698         throwSyntaxError("')' expected after 'switch' condition.");
1699       }
1700       switchStatement();
1701       return;
1702     } else if (token == TokenNamefor) {
1703       getNextToken();
1704       if (token == TokenNameLPAREN) {
1705         getNextToken();
1706       } else {
1707         throwSyntaxError("'(' expected after 'for' keyword.");
1708       }
1709       if (token == TokenNameSEMICOLON) {
1710         getNextToken();
1711       } else {
1712         expressionList();
1713         if (token == TokenNameSEMICOLON) {
1714           getNextToken();
1715         } else {
1716           throwSyntaxError("';' expected after 'for'.");
1717         }
1718       }
1719       if (token == TokenNameSEMICOLON) {
1720         getNextToken();
1721       } else {
1722         expressionList();
1723         if (token == TokenNameSEMICOLON) {
1724           getNextToken();
1725         } else {
1726           throwSyntaxError("';' expected after 'for'.");
1727         }
1728       }
1729       if (token == TokenNameRPAREN) {
1730         getNextToken();
1731       } else {
1732         expressionList();
1733         if (token == TokenNameRPAREN) {
1734           getNextToken();
1735         } else {
1736           throwSyntaxError("')' expected after 'for'.");
1737         }
1738       }
1739       forStatement();
1740       return;
1741     } else if (token == TokenNamewhile) {
1742       getNextToken();
1743       if (token == TokenNameLPAREN) {
1744         getNextToken();
1745       } else {
1746         throwSyntaxError("'(' expected after 'while' keyword.");
1747       }
1748       expression();
1749       if (token == TokenNameRPAREN) {
1750         getNextToken();
1751       } else {
1752         throwSyntaxError("')' expected after 'while' condition.");
1753       }
1754       whileStatement();
1755       return;
1756     } else if (token == TokenNamedo) {
1757       getNextToken();
1758       if (token == TokenNameLBRACE) {
1759         getNextToken();
1760       } else {
1761         throwSyntaxError("'{' expected after 'do' keyword.");
1762       }
1763       if (token != TokenNameRBRACE) {
1764         statementList();
1765       }
1766       if (token == TokenNameRBRACE) {
1767         getNextToken();
1768       } else {
1769         throwSyntaxError("'}' expected after 'do' keyword.");
1770       }
1771       if (token == TokenNamewhile) {
1772         getNextToken();
1773         if (token == TokenNameLPAREN) {
1774           getNextToken();
1775         } else {
1776           throwSyntaxError("'(' expected after 'while' keyword.");
1777         }
1778         expression();
1779         if (token == TokenNameRPAREN) {
1780           getNextToken();
1781         } else {
1782           throwSyntaxError("')' expected after 'while' condition.");
1783         }
1784       } else {
1785         throwSyntaxError("'while' expected after 'do' keyword.");
1786       }
1787       if (token == TokenNameSEMICOLON) {
1788         getNextToken();
1789       } else {
1790         if (token != TokenNameStopPHP) {
1791           throwSyntaxError("';' expected after do-while statement.");
1792         }
1793         getNextToken();
1794       }
1795       return;
1796     } else if (token == TokenNameforeach) {
1797       getNextToken();
1798       if (token == TokenNameLPAREN) {
1799         getNextToken();
1800       } else {
1801         throwSyntaxError("'(' expected after 'foreach' keyword.");
1802       }
1803       expression();
1804       if (token == TokenNameas) {
1805         getNextToken();
1806       } else {
1807         throwSyntaxError("'as' expected after 'foreach' exxpression.");
1808       }
1809       variable();
1810       if (token == TokenNameEQUAL_GREATER) {
1811         getNextToken();
1812         variable();
1813       }
1814       if (token == TokenNameRPAREN) {
1815         getNextToken();
1816       } else {
1817         throwSyntaxError("')' expected after 'foreach' expression.");
1818       }
1819       foreachStatement();
1820       return;
1821
1822     } else if (
1823       token == TokenNamecontinue
1824         || token == TokenNamebreak
1825         || token == TokenNamereturn) {
1826       getNextToken();
1827       if (token != TokenNameSEMICOLON) {
1828         expression();
1829       }
1830       if (token == TokenNameSEMICOLON) {
1831         getNextToken();
1832       } else {
1833         if (token != TokenNameStopPHP) {
1834           throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1835         }
1836         getNextToken();
1837       }
1838       return;
1839
1840     } else if (token == TokenNameecho) {
1841       getNextToken();
1842       expressionList();
1843       if (token == TokenNameSEMICOLON) {
1844         getNextToken();
1845       } else {
1846         if (token != TokenNameStopPHP) {
1847           throwSyntaxError("';' expected after 'echo' statement.");
1848         }
1849         getNextToken();
1850       }
1851       return;
1852       //    } else if (token == TokenNameprint) {
1853       //      getNextToken();
1854       //      expression();
1855       //      if (token == TokenNameSEMICOLON) {
1856       //        getNextToken();
1857       //      } else {
1858       //        if (token != TokenNameStopPHP) {
1859       //          throwSyntaxError("';' expected after 'print' statement.");
1860       //        }
1861       //        getNextToken();
1862       //      }
1863       //      return;
1864
1865     } else if (token == TokenNameglobal || token == TokenNamestatic) {
1866       getNextToken();
1867       variableList();
1868       if (token == TokenNameSEMICOLON) {
1869         getNextToken();
1870       } else {
1871         if (token != TokenNameStopPHP) {
1872           throwSyntaxError("';' expected after 'global' or 'static' statement.");
1873         }
1874         getNextToken();
1875       }
1876       return;
1877
1878       //      } else if (token == TokenNameunset) {
1879       //        getNextToken();
1880       //        if (token == TokenNameARGOPEN) {
1881       //          getNextToken();
1882       //        } else {
1883       //          throwSyntaxError("'(' expected after 'unset' keyword.");
1884       //        }
1885       //        variableList();
1886       //        if (token == TokenNameARGCLOSE) {
1887       //          getNextToken();
1888       //        } else {
1889       //          throwSyntaxError("')' expected after 'unset' statement.");
1890       //        }
1891       //        if (token == TokenNameSEMICOLON) {
1892       //          getNextToken();
1893       //        } else {
1894       //          if (token != TokenNameStopPHP) {
1895       //            throwSyntaxError("';' expected after 'unset' statement.");
1896       //          }
1897       //          getNextToken();
1898       //        }
1899       //        return;
1900
1901       //      } else if (token == TokenNameexit || token == TokenNamedie) {
1902       //        getNextToken();
1903       //        if (token != TokenNameSEMICOLON) {
1904       //          exitStatus();
1905       //        }
1906       //        if (token == TokenNameSEMICOLON) {
1907       //          getNextToken();
1908       //        } else {
1909       //          if (token != TokenNameStopPHP) {
1910       //            throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1911       //          }
1912       //          getNextToken();
1913       //        }
1914       //        return;
1915
1916     } else if (token == TokenNamedefine) {
1917       getNextToken();
1918       if (token == TokenNameLPAREN) {
1919         getNextToken();
1920       } else {
1921         throwSyntaxError("'(' expected after 'define' keyword.");
1922       }
1923       expression();
1924       if (token == TokenNameCOMMA) {
1925         getNextToken();
1926       } else {
1927         throwSyntaxError("',' expected after first 'define' constant.");
1928       }
1929       expression();
1930       if (token == TokenNameCOMMA) {
1931         getNextToken();
1932         expression();
1933       }
1934       if (token == TokenNameRPAREN) {
1935         getNextToken();
1936       } else {
1937         throwSyntaxError("')' expected after 'define' statement.");
1938       }
1939       if (token == TokenNameSEMICOLON) {
1940         getNextToken();
1941       } else {
1942         if (token != TokenNameStopPHP) {
1943           throwSyntaxError("';' expected after 'define' statement.");
1944         }
1945         getNextToken();
1946       }
1947       return;
1948     } else if (token == TokenNamefunction) {
1949       getNextToken();
1950       functionDefinition();
1951       return;
1952     } else if (token == TokenNameclass) {
1953       getNextToken();
1954       classDeclarator();
1955       classBody();
1956       return;
1957       //      } else {
1958       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
1959     } else if (token == TokenNameLBRACE) {
1960       // compoundStatement
1961       getNextToken();
1962       if (token != TokenNameRBRACE) {
1963         statementList();
1964       }
1965       if (token == TokenNameRBRACE) {
1966         getNextToken();
1967         return;
1968       } else {
1969         throwSyntaxError("'}' expected.");
1970       }
1971     } else {
1972       if (token != TokenNameSEMICOLON) {
1973         expression();
1974       }
1975       if (token == TokenNameSEMICOLON) {
1976         getNextToken();
1977         return;
1978       } else {
1979         if (token != TokenNameStopPHP && token != TokenNameEOF) {
1980           throwSyntaxError(
1981             "';' expected after expression (Found token: "
1982               + scanner.toStringAction(token)
1983               + ")");
1984         }
1985         getNextToken();
1986       }
1987     }
1988   }
1989
1990   private void classDeclarator() throws CoreException {
1991     //identifier
1992     //identifier 'extends' identifier
1993     if (token == TokenNameIdentifier) {
1994       getNextToken();
1995       if (token == TokenNameextends) {
1996         getNextToken();
1997         if (token == TokenNameIdentifier) {
1998           getNextToken();
1999         } else {
2000           throwSyntaxError("Class name expected after keyword 'extends'.");
2001         }
2002       }
2003     } else {
2004       throwSyntaxError("Class name expected after keyword 'class'.");
2005     }
2006   }
2007
2008   private void classBody() throws CoreException {
2009     //'{' [class-element-list] '}'
2010     if (token == TokenNameLBRACE) {
2011       getNextToken();
2012       if (token != TokenNameRBRACE) {
2013         classElementList();
2014       }
2015       if (token == TokenNameRBRACE) {
2016         getNextToken();
2017       } else {
2018         throwSyntaxError("'}' expected at end of class body.");
2019       }
2020     } else {
2021       throwSyntaxError("'{' expected at start of class body.");
2022     }
2023   }
2024
2025   private void classElementList() throws CoreException {
2026     do {
2027       classElement();
2028     } while (token == TokenNamefunction || token == TokenNamevar);
2029   }
2030
2031   private void classElement() throws CoreException {
2032     //class-property
2033     //function-definition
2034     if (token == TokenNamefunction) {
2035       getNextToken();
2036       functionDefinition();
2037     } else if (token == TokenNamevar) {
2038       getNextToken();
2039       classProperty();
2040     } else {
2041       throwSyntaxError("'function' or 'var' expected.");
2042     }
2043   }
2044
2045   private void classProperty() throws CoreException {
2046     //'var' variable ';'
2047     //'var' variable '=' constant ';'
2048     do {
2049       if (token == TokenNameVariable) {
2050         getNextToken();
2051         if (token == TokenNameEQUAL) {
2052           getNextToken();
2053           constant();
2054         }
2055       } else {
2056         throwSyntaxError("Variable expected after keyword 'var'.");
2057       }
2058       if (token != TokenNameCOMMA) {
2059         break;
2060       }
2061       getNextToken();
2062     } while (true);
2063     if (token == TokenNameSEMICOLON) {
2064       getNextToken();
2065     } else {
2066       throwSyntaxError("';' expected after variable declaration.");
2067     }
2068   }
2069
2070   private void functionDefinition() throws CoreException {
2071     functionDeclarator();
2072     compoundStatement();
2073   }
2074
2075   private void functionDeclarator() throws CoreException {
2076     //identifier '(' [parameter-list] ')'
2077     if (token == TokenNameAND) {
2078       getNextToken();
2079     }
2080     if (token == TokenNameIdentifier) {
2081       getNextToken();
2082       if (token == TokenNameLPAREN) {
2083         getNextToken();
2084       } else {
2085         throwSyntaxError("'(' expected in function declaration.");
2086       }
2087       if (token != TokenNameRPAREN) {
2088         parameterList();
2089       }
2090       if (token != TokenNameRPAREN) {
2091         throwSyntaxError("')' expected in function declaration.");
2092       } else {
2093         getNextToken();
2094       }
2095     }
2096   }
2097   //
2098   private void parameterList() throws CoreException {
2099     //parameter-declaration
2100     //parameter-list ',' parameter-declaration
2101     do {
2102       parameterDeclaration();
2103       if (token != TokenNameCOMMA) {
2104         break;
2105       }
2106       getNextToken();
2107     } while (true);
2108   }
2109
2110   private void parameterDeclaration() throws CoreException {
2111     //variable
2112     //variable-reference
2113     if (token == TokenNameAND) {
2114       getNextToken();
2115       if (token == TokenNameVariable) {
2116         getNextToken();
2117       } else {
2118         throwSyntaxError("Variable expected after reference operator '&'.");
2119       }
2120     }
2121     //variable '=' constant
2122     if (token == TokenNameVariable) {
2123       getNextToken();
2124       if (token == TokenNameEQUAL) {
2125         getNextToken();
2126         constant();
2127       }
2128       return;
2129     }
2130   }
2131
2132   private void labeledStatementList() throws CoreException {
2133     if (token != TokenNamecase && token != TokenNamedefault) {
2134       throwSyntaxError("'case' or 'default' expected.");
2135     }
2136     do {
2137       if (token == TokenNamecase) {
2138         getNextToken();
2139         constant();
2140         if (token == TokenNameCOLON) {
2141           getNextToken();
2142           if (token == TokenNamecase
2143             || token == TokenNamedefault) { // empty case statement ?
2144             continue;
2145           }
2146           statementList();
2147         } else if (token == TokenNameSEMICOLON) {
2148           //          setMarker(
2149           //            "':' expected after 'case' keyword (Found token: "
2150           //              + scanner.toStringAction(token)
2151           //              + ")",
2152           //            rowCount,
2153           //            PHPParser.INFO);
2154           setMarker(
2155             "':' expected after 'case' keyword (Found token: "
2156               + scanner.toStringAction(token)
2157               + ")",
2158             scanner.getCurrentTokenStartPosition(),
2159             scanner.getCurrentTokenEndPosition(),
2160             INFO);
2161           getNextToken();
2162           if (token == TokenNamecase) { // empty case statement ?
2163             continue;
2164           }
2165           statementList();
2166         } else {
2167           throwSyntaxError(
2168             "':' character after 'case' constant expected (Found token: "
2169               + scanner.toStringAction(token)
2170               + ")");
2171         }
2172       } else { // TokenNamedefault
2173         getNextToken();
2174         if (token == TokenNameCOLON) {
2175           getNextToken();
2176           statementList();
2177         } else {
2178           throwSyntaxError("':' character after 'default' expected.");
2179         }
2180       }
2181     } while (token == TokenNamecase || token == TokenNamedefault);
2182   }
2183
2184   //  public void labeledStatement() {
2185   //    if (token == TokenNamecase) {
2186   //      getNextToken();
2187   //      constant();
2188   //      if (token == TokenNameDDOT) {
2189   //        getNextToken();
2190   //        statement();
2191   //      } else {
2192   //        throwSyntaxError("':' character after 'case' constant expected.");
2193   //      }
2194   //      return;
2195   //    } else if (token == TokenNamedefault) {
2196   //      getNextToken();
2197   //      if (token == TokenNameDDOT) {
2198   //        getNextToken();
2199   //        statement();
2200   //      } else {
2201   //        throwSyntaxError("':' character after 'default' expected.");
2202   //      }
2203   //      return;
2204   //    }
2205   //  }
2206
2207   //  public void expressionStatement() {
2208   //  }
2209
2210   //  private void inclusionStatement() {
2211   //  }
2212
2213   //  public void compoundStatement() {
2214   //  }
2215
2216   //  public void selectionStatement() {
2217   //  }
2218   //
2219   //  public void iterationStatement() {
2220   //  }
2221   //
2222   //  public void jumpStatement() {
2223   //  }
2224   //
2225   //  public void outputStatement() {
2226   //  }
2227   //
2228   //  public void scopeStatement() {
2229   //  }
2230   //
2231   //  public void flowStatement() {
2232   //  }
2233   //
2234   //  public void definitionStatement() {
2235   //  }
2236
2237   private void ifStatement() throws CoreException {
2238     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
2239     if (token == TokenNameCOLON) {
2240       getNextToken();
2241       statementList();
2242       switch (token) {
2243         case TokenNameelse :
2244           getNextToken();
2245           if (token == TokenNameCOLON) {
2246             getNextToken();
2247             statementList();
2248           } else {
2249             if (token == TokenNameif) { //'else if'
2250               getNextToken();
2251               elseifStatementList();
2252             } else {
2253               throwSyntaxError("':' expected after 'else'.");
2254             }
2255           }
2256           break;
2257         case TokenNameelseif :
2258           getNextToken();
2259           elseifStatementList();
2260           break;
2261       }
2262
2263       if (token != TokenNameendif) {
2264         throwSyntaxError("'endif' expected.");
2265       }
2266       getNextToken();
2267       if (token != TokenNameSEMICOLON) {
2268         throwSyntaxError("';' expected after if-statement.");
2269       }
2270       getNextToken();
2271     } else {
2272       // statement [else-statement]
2273       statement();
2274       if (token == TokenNameelseif) {
2275         getNextToken();
2276         if (token == TokenNameLPAREN) {
2277           getNextToken();
2278         } else {
2279           throwSyntaxError("'(' expected after 'elseif' keyword.");
2280         }
2281         expression();
2282         if (token == TokenNameRPAREN) {
2283           getNextToken();
2284         } else {
2285           throwSyntaxError("')' expected after 'elseif' condition.");
2286         }
2287         ifStatement();
2288       } else if (token == TokenNameelse) {
2289         getNextToken();
2290         statement();
2291       }
2292     }
2293   }
2294
2295   private void elseifStatementList() throws CoreException {
2296     do {
2297       elseifStatement();
2298       switch (token) {
2299         case TokenNameelse :
2300           getNextToken();
2301           if (token == TokenNameCOLON) {
2302             getNextToken();
2303             statementList();
2304             return;
2305           } else {
2306             if (token == TokenNameif) { //'else if'
2307               getNextToken();
2308             } else {
2309               throwSyntaxError("':' expected after 'else'.");
2310             }
2311           }
2312           break;
2313         case TokenNameelseif :
2314           getNextToken();
2315           break;
2316         default :
2317           return;
2318       }
2319     } while (true);
2320   }
2321
2322   private void elseifStatement() throws CoreException {
2323     if (token == TokenNameLPAREN) {
2324       getNextToken();
2325       expression();
2326       if (token != TokenNameLPAREN) {
2327         throwSyntaxError("')' expected in else-if-statement.");
2328       }
2329       getNextToken();
2330       if (token != TokenNameCOLON) {
2331         throwSyntaxError("':' expected in else-if-statement.");
2332       }
2333       getNextToken();
2334       statementList();
2335     }
2336   }
2337
2338   private void switchStatement() throws CoreException {
2339     if (token == TokenNameCOLON) {
2340       // ':' [labeled-statement-list] 'endswitch' ';'
2341       getNextToken();
2342       labeledStatementList();
2343       if (token != TokenNameendswitch) {
2344         throwSyntaxError("'endswitch' expected.");
2345       }
2346       getNextToken();
2347       if (token != TokenNameSEMICOLON) {
2348         throwSyntaxError("';' expected after switch-statement.");
2349       }
2350       getNextToken();
2351     } else {
2352       // '{' [labeled-statement-list] '}'
2353       if (token != TokenNameLBRACE) {
2354         throwSyntaxError("'{' expected in switch statement.");
2355       }
2356       getNextToken();
2357       if (token != TokenNameRBRACE) {
2358         labeledStatementList();
2359       }
2360       if (token != TokenNameRBRACE) {
2361         throwSyntaxError("'}' expected in switch statement.");
2362       }
2363       getNextToken();
2364
2365     }
2366   }
2367
2368   private void forStatement() throws CoreException {
2369     if (token == TokenNameCOLON) {
2370       getNextToken();
2371       statementList();
2372       if (token != TokenNameendfor) {
2373         throwSyntaxError("'endfor' expected.");
2374       }
2375       getNextToken();
2376       if (token != TokenNameSEMICOLON) {
2377         throwSyntaxError("';' expected after for-statement.");
2378       }
2379       getNextToken();
2380     } else {
2381       statement();
2382     }
2383   }
2384
2385   private void whileStatement() throws CoreException {
2386     // ':' statement-list 'endwhile' ';'
2387     if (token == TokenNameCOLON) {
2388       getNextToken();
2389       statementList();
2390       if (token != TokenNameendwhile) {
2391         throwSyntaxError("'endwhile' expected.");
2392       }
2393       getNextToken();
2394       if (token != TokenNameSEMICOLON) {
2395         throwSyntaxError("';' expected after while-statement.");
2396       }
2397       getNextToken();
2398     } else {
2399       statement();
2400     }
2401   }
2402
2403   private void foreachStatement() throws CoreException {
2404     if (token == TokenNameCOLON) {
2405       getNextToken();
2406       statementList();
2407       if (token != TokenNameendforeach) {
2408         throwSyntaxError("'endforeach' expected.");
2409       }
2410       getNextToken();
2411       if (token != TokenNameSEMICOLON) {
2412         throwSyntaxError("';' expected after foreach-statement.");
2413       }
2414       getNextToken();
2415     } else {
2416       statement();
2417     }
2418   }
2419
2420   private void exitStatus() throws CoreException {
2421     if (token == TokenNameLPAREN) {
2422       getNextToken();
2423     } else {
2424       throwSyntaxError("'(' expected in 'exit-status'.");
2425     }
2426     if (token != TokenNameRPAREN) {
2427       expression();
2428     }
2429     if (token == TokenNameRPAREN) {
2430       getNextToken();
2431     } else {
2432       throwSyntaxError("')' expected after 'exit-status'.");
2433     }
2434   }
2435
2436   private void expressionList() throws CoreException {
2437     do {
2438       expression();
2439       if (token == TokenNameCOMMA) {
2440         getNextToken();
2441       } else {
2442         break;
2443       }
2444     } while (true);
2445   }
2446
2447   private void expression() throws CoreException {
2448     //todo: find a better way to get the expression
2449 //    expression = new StringBuffer();
2450 //    for (int i = chIndx; i < str.length(); i++) {
2451 //      if (str.charAt(i) == ';') {
2452 //        break;
2453 //      }
2454 //      expression.append(str.charAt(i));
2455 //    }
2456     
2457     //    if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
2458     //      getNextToken();
2459     //    } else {
2460     logicalinclusiveorExpression();
2461     //      while (token != TokenNameSEMICOLON) {
2462     //        getNextToken();
2463     //      //      }
2464     //    }
2465   }
2466
2467   private void postfixExpression() throws CoreException {
2468     //  String ident;
2469     char[] ident;
2470     boolean castFlag = false;
2471     switch (token) {
2472       case TokenNamenew :
2473         getNextToken();
2474         expression();
2475         break;
2476       case TokenNamenull :
2477         getNextToken();
2478         break;
2479       case TokenNamefalse :
2480         getNextToken();
2481         break;
2482       case TokenNametrue :
2483         getNextToken();
2484         break;
2485       case TokenNameStringConstant :
2486         getNextToken();
2487         break;
2488       case TokenNameHEREDOC :
2489       case TokenNameStringInterpolated :
2490       case TokenNameStringLiteral :
2491         getNextToken();
2492         break;
2493       case TokenNameLPAREN :
2494         getNextToken();
2495         if (token == TokenNameIdentifier) {
2496           // check if identifier is a type:
2497           //    ident = identifier;
2498           ident = scanner.getCurrentIdentifierSource();
2499           String str = new String(ident).toLowerCase();
2500           for (int i = 0; i < PHP_TYPES.length; i++) {
2501             if (PHP_TYPES[i].equals(str)) {
2502               castFlag = true;
2503               break;
2504             }
2505           }
2506           if (castFlag) {
2507             getNextToken();
2508             if (token != TokenNameRPAREN) {
2509               throwSyntaxError(") expected after cast-type '" + str + "'.");
2510             }
2511             getNextToken();
2512             expression();
2513             break;
2514           }
2515         }
2516         if (!castFlag) {
2517           expression();
2518         }
2519         if (token != TokenNameRPAREN) {
2520           throwSyntaxError(") expected in postfix-expression.");
2521         }
2522         getNextToken();
2523         break;
2524       case TokenNameDoubleLiteral :
2525         getNextToken();
2526         break;
2527       case TokenNameIntegerLiteral :
2528         getNextToken();
2529         break;
2530       case TokenNameDOLLAR_LBRACE :
2531         getNextToken();
2532         expression();
2533         if (token != TokenNameRBRACE) {
2534           throwSyntaxError("'}' expected after indirect variable token '${'.");
2535         }
2536         getNextToken();
2537         break;
2538       case TokenNameVariable :
2539         ident = scanner.getCurrentIdentifierSource();
2540         getNextToken();
2541         if (token == TokenNameLBRACE) {
2542           getNextToken();
2543           expression();
2544           if (token != TokenNameRBRACE) {
2545             throwSyntaxError(
2546               "'}' expected after variable '"
2547                 + new String(ident)
2548                 + "' in variable-expression.");
2549           }
2550           getNextToken();
2551         } else if (token == TokenNameLPAREN) {
2552           getNextToken();
2553           if (token != TokenNameRPAREN) {
2554             expressionList();
2555             if (token != TokenNameRPAREN) {
2556               throwSyntaxError(
2557                 "')' expected after variable '"
2558                   + new String(ident)
2559                   + "' in postfix-expression.");
2560             }
2561           }
2562           getNextToken();
2563         }
2564         break;
2565       case TokenNameIdentifier :
2566         ident = scanner.getCurrentIdentifierSource();
2567         getNextToken();
2568         if (token == TokenNameLPAREN) {
2569           getNextToken();
2570           if (token != TokenNameRPAREN) {
2571             expressionList();
2572             if (token != TokenNameRPAREN) {
2573               throwSyntaxError(
2574                 "')' expected after identifier '"
2575                   + new String(ident)
2576                   + "' in postfix-expression."
2577                   + "(Found token: "
2578                   + scanner.toStringAction(token)
2579                   + ")");
2580             }
2581           }
2582           getNextToken();
2583         }
2584         break;
2585       case TokenNameprint :
2586         getNextToken();
2587         expression();
2588         //        if (token == TokenNameSEMICOLON) {
2589         //          getNextToken();
2590         //        } else {
2591         //          if (token != TokenNameStopPHP) {
2592         //            throwSyntaxError("';' expected after 'print' statement.");
2593         //          }
2594         //          getNextToken();
2595         //        }
2596         break;
2597       case TokenNamelist :
2598         getNextToken();
2599         if (token == TokenNameLPAREN) {
2600           getNextToken();
2601           if (token == TokenNameCOMMA) {
2602             getNextToken();
2603           }
2604           expressionList();
2605           if (token != TokenNameRPAREN) {
2606             throwSyntaxError("')' expected after 'list' keyword.");
2607           }
2608           getNextToken();
2609           //          if (token == TokenNameSET) {
2610           //            getNextToken();
2611           //            logicalinclusiveorExpression();
2612           //          }
2613         } else {
2614           throwSyntaxError("'(' expected after 'list' keyword.");
2615         }
2616         break;
2617         //      case TokenNameexit :
2618         //        getNextToken();
2619         //        if (token != TokenNameSEMICOLON) {
2620         //          exitStatus();
2621         //        }
2622         //        if (token == TokenNameSEMICOLON) {
2623         //          getNextToken();
2624         //        } else {
2625         //          if (token != TokenNameStopPHP) {
2626         //            throwSyntaxError("';' expected after 'exit' expression.");
2627         //          }
2628         //          getNextToken();
2629         //        }
2630         //        break;
2631         //      case TokenNamedie :
2632         //        getNextToken();
2633         //        if (token != TokenNameSEMICOLON) {
2634         //          exitStatus();
2635         //        }
2636         //        if (token == TokenNameSEMICOLON) {
2637         //          getNextToken();
2638         //        } else {
2639         //          if (token != TokenNameStopPHP) {
2640         //            throwSyntaxError("';' expected after 'die' expression.");
2641         //          }
2642         //        }
2643         //        break;
2644
2645         //      case TokenNamearray :
2646         //        getNextToken();
2647         //        if (token == TokenNameARGOPEN) {
2648         //          getNextToken();
2649         //          if (token == TokenNameCOMMA) {
2650         //            getNextToken();
2651         //          }
2652         //          expressionList();
2653         //          if (token != TokenNameARGCLOSE) {
2654         //            throwSyntaxError("')' expected after 'list' keyword.");
2655         //          }
2656         //          getNextToken();
2657         //          if (token == TokenNameSET) {
2658         //            getNextToken();
2659         //            logicalinclusiveorExpression();
2660         //          }
2661         //        } else {
2662         //          throwSyntaxError("'(' expected after 'list' keyword.");
2663         //        }
2664         //        break;
2665     }
2666     boolean while_flag = true;
2667     do {
2668       switch (token) {
2669         case TokenNameLBRACKET :
2670           getNextToken();
2671           expression();
2672           if (token != TokenNameRBRACKET) {
2673             throwSyntaxError("] expected in postfix-expression.");
2674           }
2675           getNextToken();
2676           break;
2677         case TokenNameCOLON_COLON : // ::
2678         case TokenNameMINUS_GREATER : // ->
2679           getNextToken();
2680           if (token > TokenNameKEYWORD) {
2681             ident = scanner.getCurrentIdentifierSource();
2682             //            setMarker(
2683             //              "Avoid using keyword '"
2684             //                + new String(ident)
2685             //                + "' as variable name.",
2686             //              rowCount,
2687             //              PHPParser.INFO);
2688             setMarker(
2689               "Avoid using keyword '"
2690                 + new String(ident)
2691                 + "' as variable name.",
2692               scanner.getCurrentTokenStartPosition(),
2693               scanner.getCurrentTokenEndPosition(),
2694               INFO);
2695           }
2696           switch (token) {
2697             case TokenNameVariable :
2698               ident = scanner.getCurrentIdentifierSource();
2699               getNextToken();
2700               //              if (token == TokenNameARGOPEN) {
2701               //                getNextToken();
2702               //                expressionList();
2703               //                if (token != TokenNameARGCLOSE) {
2704               //                  throwSyntaxError(") expected after variable '" + ident + "'.");
2705               //                }
2706               //                getNextToken();
2707               //              }
2708               break;
2709             case TokenNameIdentifier :
2710               //ident = scanner.getCurrentIdentifierSource();
2711               getNextToken();
2712               break;
2713             case TokenNameLBRACE :
2714               getNextToken();
2715               expression();
2716               if (token != TokenNameRBRACE) {
2717                 throwSyntaxError("} expected in postfix-expression.");
2718               }
2719               getNextToken();
2720               break;
2721             default :
2722               throwSyntaxError("Syntax error after '->' token.");
2723           } while (
2724             token == TokenNameLBRACKET
2725               || token == TokenNameLPAREN
2726               || token == TokenNameLBRACE) {
2727               if (token == TokenNameLBRACKET) {
2728                 getNextToken();
2729                 expressionList();
2730                 if (token != TokenNameRBRACKET) {
2731                   throwSyntaxError("] expected after '->'.");
2732                 }
2733                 getNextToken();
2734               }
2735               if (token == TokenNameLPAREN) {
2736                 getNextToken();
2737                 expressionList();
2738                 if (token != TokenNameRPAREN) {
2739                   throwSyntaxError(") expected after '->'.");
2740                 }
2741                 getNextToken();
2742               }
2743               if (token == TokenNameLBRACE) {
2744                 getNextToken();
2745                 expression();
2746                 if (token != TokenNameRBRACE) {
2747                   throwSyntaxError("} expected after '->'.");
2748                 }
2749                 getNextToken();
2750               }
2751             }
2752           break;
2753         case TokenNamePLUS_PLUS :
2754           getNextToken();
2755           break;
2756         case TokenNameMINUS_MINUS :
2757           getNextToken();
2758           break;
2759         default :
2760           while_flag = false;
2761       }
2762
2763     }
2764     while (while_flag);
2765   }
2766
2767   private void unaryExpression() throws CoreException {
2768     switch (token) {
2769       case TokenNamePLUS_PLUS :
2770         getNextToken();
2771         unaryExpression();
2772         break;
2773       case TokenNameMINUS_MINUS :
2774         getNextToken();
2775         unaryExpression();
2776         break;
2777         // '@' '&' '*' '+' '-' '~' '!'
2778       case TokenNameAT :
2779         getNextToken();
2780         castExpression();
2781         break;
2782       case TokenNameAND :
2783         getNextToken();
2784         castExpression();
2785         break;
2786       case TokenNameMULTIPLY :
2787         getNextToken();
2788         castExpression();
2789         break;
2790       case TokenNamePLUS :
2791         getNextToken();
2792         castExpression();
2793         break;
2794       case TokenNameMINUS :
2795         getNextToken();
2796         castExpression();
2797         break;
2798       case TokenNameTWIDDLE :
2799         getNextToken();
2800         castExpression();
2801         break;
2802       case TokenNameNOT :
2803         getNextToken();
2804         castExpression();
2805         break;
2806       default :
2807         postfixExpression();
2808     }
2809   }
2810
2811   private void castExpression() throws CoreException {
2812     //    if (token == TokenNameARGOPEN) {
2813     //      getNextToken();
2814     //      typeName();
2815     //      if (token != TokenNameARGCLOSE) {
2816     //        throwSyntaxError(") expected after cast-expression.");
2817     //      }
2818     //      getNextToken();
2819     //    }
2820     unaryExpression();
2821   }
2822
2823   private void typeName() throws CoreException {
2824     //'string' 'unset' 'array' 'object'
2825     //'bool' 'boolean'
2826     //'real' 'double' 'float'
2827     //'int' 'integer'
2828     String identifier = "";
2829     if (token == TokenNameIdentifier) {
2830       char[] ident = scanner.getCurrentIdentifierSource();
2831       identifier = new String(ident);
2832       String str = identifier.toLowerCase();
2833       getNextToken();
2834       for (int i = 0; i < PHP_TYPES.length; i++) {
2835         if (PHP_TYPES[i].equals(str)) {
2836           return;
2837         }
2838       }
2839     }
2840     throwSyntaxError(
2841       "Expected type cast '( <type-name> )'; Got '" + identifier + "'.");
2842   }
2843
2844   private void assignExpression() throws CoreException {
2845     castExpression();
2846     if (token == TokenNameEQUAL) { // =
2847       getNextToken();
2848       logicalinclusiveorExpression();
2849     } else if (token == TokenNameDOT_EQUAL) { // .=
2850       getNextToken();
2851       logicalinclusiveorExpression();
2852     } else if (token == TokenNameEQUAL_GREATER) { // =>
2853       getNextToken();
2854       logicalinclusiveorExpression();
2855     } else if (token == TokenNamePLUS_EQUAL) { // +=
2856       getNextToken();
2857       logicalinclusiveorExpression();
2858     } else if (token == TokenNameMINUS_EQUAL) { // -=
2859       getNextToken();
2860       logicalinclusiveorExpression();
2861     } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2862       getNextToken();
2863       logicalinclusiveorExpression();
2864     } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2865       getNextToken();
2866       logicalinclusiveorExpression();
2867     } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2868       getNextToken();
2869       logicalinclusiveorExpression();
2870     } else if (token == TokenNameAND_EQUAL) { // &=
2871       getNextToken();
2872       logicalinclusiveorExpression();
2873     } else if (token == TokenNameOR_EQUAL) { // |=
2874       getNextToken();
2875       logicalinclusiveorExpression();
2876     } else if (token == TokenNameXOR_EQUAL) { // ^=
2877       getNextToken();
2878       logicalinclusiveorExpression();
2879     } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2880       getNextToken();
2881       logicalinclusiveorExpression();
2882     } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2883       getNextToken();
2884       logicalinclusiveorExpression();
2885     } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2886       getNextToken();
2887       logicalinclusiveorExpression();
2888     }
2889   }
2890
2891   private void multiplicativeExpression() throws CoreException {
2892     do {
2893       assignExpression();
2894       if (token != TokenNameMULTIPLY
2895         && token != TokenNameDIVIDE
2896         && token != TokenNameREMAINDER) {
2897         return;
2898       }
2899       getNextToken();
2900     } while (true);
2901   }
2902
2903   private void concatenationExpression() throws CoreException {
2904     do {
2905       multiplicativeExpression();
2906       if (token != TokenNameDOT) {
2907         return;
2908       }
2909       getNextToken();
2910     } while (true);
2911   }
2912
2913   private void additiveExpression() throws CoreException {
2914     do {
2915       concatenationExpression();
2916       if (token != TokenNamePLUS && token != TokenNameMINUS) {
2917         return;
2918       }
2919       getNextToken();
2920     } while (true);
2921   }
2922
2923   private void shiftExpression() throws CoreException {
2924     do {
2925       additiveExpression();
2926       if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2927         return;
2928       }
2929       getNextToken();
2930     } while (true);
2931   }
2932
2933   private void relationalExpression() throws CoreException {
2934     do {
2935       shiftExpression();
2936       if (token != TokenNameLESS
2937         && token != TokenNameGREATER
2938         && token != TokenNameLESS_EQUAL
2939         && token != TokenNameGREATER_EQUAL) {
2940         return;
2941       }
2942       getNextToken();
2943     } while (true);
2944   }
2945
2946   private void identicalExpression() throws CoreException {
2947     do {
2948       relationalExpression();
2949       if (token != TokenNameEQUAL_EQUAL_EQUAL
2950         && token != TokenNameNOT_EQUAL_EQUAL) {
2951         return;
2952       }
2953       getNextToken();
2954     } while (true);
2955   }
2956
2957   private void equalityExpression() throws CoreException {
2958     do {
2959       identicalExpression();
2960       if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2961         return;
2962       }
2963       getNextToken();
2964     } while (true);
2965   }
2966
2967   private void ternaryExpression() throws CoreException {
2968     equalityExpression();
2969     if (token == TokenNameQUESTION) {
2970       getNextToken();
2971       expression();
2972       if (token == TokenNameCOLON) {
2973         getNextToken();
2974         expression();
2975       } else {
2976         throwSyntaxError("':' expected in ternary operator '? :'.");
2977       }
2978     }
2979   }
2980
2981   private void andExpression() throws CoreException {
2982     do {
2983       ternaryExpression();
2984       if (token != TokenNameAND) {
2985         return;
2986       }
2987       getNextToken();
2988     } while (true);
2989   }
2990
2991   private void exclusiveorExpression() throws CoreException {
2992     do {
2993       andExpression();
2994       if (token != TokenNameXOR) {
2995         return;
2996       }
2997       getNextToken();
2998     } while (true);
2999   }
3000
3001   private void inclusiveorExpression() throws CoreException {
3002     do {
3003       exclusiveorExpression();
3004       if (token != TokenNameOR) {
3005         return;
3006       }
3007       getNextToken();
3008     } while (true);
3009   }
3010
3011   private void booleanandExpression() throws CoreException {
3012     do {
3013       inclusiveorExpression();
3014       if (token != TokenNameAND_AND) {
3015         return;
3016       }
3017       getNextToken();
3018     } while (true);
3019   }
3020
3021   private void booleanorExpression() throws CoreException {
3022     do {
3023       booleanandExpression();
3024       if (token != TokenNameOR_OR) {
3025         return;
3026       }
3027       getNextToken();
3028     } while (true);
3029   }
3030
3031   private void logicalandExpression() throws CoreException {
3032     do {
3033       booleanorExpression();
3034       if (token != TokenNameAND) {
3035         return;
3036       }
3037       getNextToken();
3038     } while (true);
3039   }
3040
3041   private void logicalexclusiveorExpression() throws CoreException {
3042     do {
3043       logicalandExpression();
3044       if (token != TokenNameXOR) {
3045         return;
3046       }
3047       getNextToken();
3048     } while (true);
3049   }
3050
3051   private void logicalinclusiveorExpression() throws CoreException {
3052     do {
3053       logicalexclusiveorExpression();
3054       if (token != TokenNameOR) {
3055         return;
3056       }
3057       getNextToken();
3058     } while (true);
3059   }
3060
3061   //  public void assignmentExpression() {
3062   //    if (token == TokenNameVARIABLE) {
3063   //      getNextToken();
3064   //      if (token == TokenNameSET) {
3065   //        getNextToken();
3066   //        logicalinclusiveorExpression();
3067   //      }
3068   //    } else {
3069   //      logicalinclusiveorExpression();
3070   //    }
3071   //  }
3072
3073   private void variableList() throws CoreException {
3074     do {
3075       variable();
3076       if (token == TokenNameCOMMA) {
3077         getNextToken();
3078       } else {
3079         break;
3080       }
3081     } while (true);
3082   }
3083
3084   private void variable() throws CoreException {
3085     if (token == TokenNameDOLLAR_LBRACE) {
3086       getNextToken();
3087       expression();
3088       ;
3089       if (token != TokenNameRBRACE) {
3090         throwSyntaxError("'}' expected after indirect variable token '${'.");
3091       }
3092       getNextToken();
3093     } else {
3094       if (token == TokenNameVariable) {
3095         getNextToken();
3096         if (token == TokenNameLBRACKET) {
3097           getNextToken();
3098           expression();
3099           if (token != TokenNameRBRACKET) {
3100             throwSyntaxError("']' expected in variable-list.");
3101           }
3102           getNextToken();
3103         } else if (token == TokenNameEQUAL) {
3104           getNextToken();
3105           constant();
3106         }
3107       } else {
3108         throwSyntaxError("$-variable expected in variable-list.");
3109       }
3110     }
3111   }
3112
3113   /**
3114    * It will look for a value (after a '=' for example)
3115    * @throws CoreException
3116    */
3117   private void constant() throws CoreException {
3118     //   String ident;
3119     switch (token) {
3120       case TokenNamePLUS :
3121         getNextToken();
3122         switch (token) {
3123           case TokenNameDoubleLiteral :
3124             getNextToken();
3125             break;
3126           case TokenNameIntegerLiteral :
3127             getNextToken();
3128             break;
3129           default :
3130             throwSyntaxError("Constant expected after '+' presign.");
3131         }
3132         break;
3133       case TokenNameMINUS :
3134         getNextToken();
3135         switch (token) {
3136           case TokenNameDoubleLiteral :
3137             getNextToken();
3138             break;
3139           case TokenNameIntegerLiteral :
3140             getNextToken();
3141             break;
3142           default :
3143             throwSyntaxError("Constant expected after '-' presign.");
3144         }
3145         break;
3146       case TokenNamenull :
3147         getNextToken();
3148         break;
3149       case TokenNamefalse :
3150         getNextToken();
3151         break;
3152       case TokenNametrue :
3153         getNextToken();
3154         break;
3155       case TokenNameIdentifier :
3156         //   ident = identifier;
3157         char[] ident = scanner.getCurrentIdentifierSource();
3158         getNextToken();
3159         if (token == TokenNameLPAREN) {
3160           getNextToken();
3161           if (token != TokenNameRPAREN) {
3162             expressionList();
3163             if (token != TokenNameRPAREN) {
3164               throwSyntaxError(
3165                 "')' expected after identifier '"
3166                   + new String(ident)
3167                   + "' in postfix-expression.");
3168             }
3169           }
3170           getNextToken();
3171         }
3172         break;
3173       case TokenNameStringLiteral :
3174         getNextToken();
3175         break;
3176       case TokenNameStringConstant :
3177         getNextToken();
3178         break;
3179       case TokenNameStringInterpolated :
3180         getNextToken();
3181         break;
3182       case TokenNameDoubleLiteral :
3183         getNextToken();
3184         break;
3185       case TokenNameIntegerLiteral :
3186         getNextToken();
3187         break;
3188       default :
3189         throwSyntaxError("Constant expected.");
3190     }
3191   }
3192
3193   /**
3194    * Call the php parse command ( php -l -f &lt;filename&gt; )
3195    * and create markers according to the external parser output
3196    */
3197   public static void phpExternalParse(IFile file) {
3198     //IFile file = (IFile) resource;
3199     IPath path = file.getFullPath();
3200     IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
3201     String filename = file.getLocation().toString();
3202
3203     String[] arguments = { filename };
3204     MessageFormat form =
3205       new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF));
3206     String command = form.format(arguments);
3207
3208     String parserResult =
3209       PHPStartApacheAction.getParserOutput(command, "External parser: ");
3210
3211     try {
3212       // parse the buffer to find the errors and warnings
3213       createMarkers(parserResult, file);
3214     } catch (CoreException e) {
3215     }
3216   }
3217
3218   /**
3219    * Create markers according to the external parser output
3220    */
3221   private static void createMarkers(String output, IFile file)
3222     throws CoreException {
3223     // delete all markers
3224     file.deleteMarkers(IMarker.PROBLEM, false, 0);
3225
3226     int indx = 0;
3227     int brIndx = 0;
3228     boolean flag = true;
3229     while ((brIndx = output.indexOf("<br />", indx)) != -1) {
3230       // newer php error output (tested with 4.2.3)
3231       scanLine(output, file, indx, brIndx);
3232       indx = brIndx + 6;
3233       flag = false;
3234     }
3235     if (flag) {
3236       while ((brIndx = output.indexOf("<br>", indx)) != -1) {
3237         // older php error output (tested with 4.2.3)
3238         scanLine(output, file, indx, brIndx);
3239         indx = brIndx + 4;
3240       }
3241     }
3242   }
3243
3244   private static void scanLine(String output, IFile file, int indx, int brIndx)
3245     throws CoreException {
3246     String current;
3247     String outLineNumberString;
3248     StringBuffer lineNumberBuffer = new StringBuffer(10);
3249     char ch;
3250     current = output.substring(indx, brIndx);
3251
3252     if (current.indexOf(PARSE_WARNING_STRING) != -1
3253       || current.indexOf(PARSE_ERROR_STRING) != -1) {
3254       int onLine = current.indexOf("on line <b>");
3255       if (onLine != -1) {
3256         lineNumberBuffer.delete(0, lineNumberBuffer.length());
3257         for (int i = onLine; i < current.length(); i++) {
3258           ch = current.charAt(i);
3259           if ('0' <= ch && '9' >= ch) {
3260             lineNumberBuffer.append(ch);
3261           }
3262         }
3263
3264         int lineNumber = Integer.parseInt(lineNumberBuffer.toString());
3265
3266         Hashtable attributes = new Hashtable();
3267
3268         current = current.replaceAll("\n", "");
3269         current = current.replaceAll("<b>", "");
3270         current = current.replaceAll("</b>", "");
3271         MarkerUtilities.setMessage(attributes, current);
3272
3273         if (current.indexOf(PARSE_ERROR_STRING) != -1)
3274           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
3275         else if (current.indexOf(PARSE_WARNING_STRING) != -1)
3276           attributes.put(
3277             IMarker.SEVERITY,
3278             new Integer(IMarker.SEVERITY_WARNING));
3279         else
3280           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
3281         MarkerUtilities.setLineNumber(attributes, lineNumber);
3282         MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
3283       }
3284     }
3285   }
3286 }