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