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