6cb4c916baaf99d40d21a6edfa21b7e09b32e2ae
[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();
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() 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       expression();
984       if (token == TokenNameSEMICOLON) {
985         getNextToken();
986       } else {
987         if (token != TokenNameStopPHP) {
988           throwSyntaxError("';' character after 'include' or 'include_once' expected.");
989         }
990         getNextToken();
991       }
992       return;
993     } else if (token == TokenNamerequire || token == TokenNamerequire_once) {
994       getNextToken();
995       //constant();
996       expression();
997       if (token == TokenNameSEMICOLON) {
998         getNextToken();
999       } else {
1000         if (token != TokenNameStopPHP) {
1001           throwSyntaxError("';' character after 'require' or 'require_once' expected.");
1002         }
1003         getNextToken();
1004       }
1005       return;
1006     } else if (token == TokenNameif) {
1007       getNextToken();
1008       if (token == TokenNameLPAREN) {
1009         getNextToken();
1010       } else {
1011         throwSyntaxError("'(' expected after 'if' keyword.");
1012       }
1013       expression();
1014       if (token == TokenNameRPAREN) {
1015         getNextToken();
1016       } else {
1017         throwSyntaxError("')' expected after 'if' condition.");
1018       }
1019       ifStatement();
1020       return;
1021
1022     } else if (token == TokenNameswitch) {
1023       getNextToken();
1024       if (token == TokenNameLPAREN) {
1025         getNextToken();
1026       } else {
1027         throwSyntaxError("'(' expected after 'switch' keyword.");
1028       }
1029       expression();
1030       if (token == TokenNameRPAREN) {
1031         getNextToken();
1032       } else {
1033         throwSyntaxError("')' expected after 'switch' condition.");
1034       }
1035       switchStatement();
1036       return;
1037     } else if (token == TokenNamefor) {
1038       getNextToken();
1039       if (token == TokenNameLPAREN) {
1040         getNextToken();
1041       } else {
1042         throwSyntaxError("'(' expected after 'for' keyword.");
1043       }
1044       if (token == TokenNameSEMICOLON) {
1045         getNextToken();
1046       } else {
1047         expressionList();
1048         if (token == TokenNameSEMICOLON) {
1049           getNextToken();
1050         } else {
1051           throwSyntaxError("';' expected after 'for'.");
1052         }
1053       }
1054       if (token == TokenNameSEMICOLON) {
1055         getNextToken();
1056       } else {
1057         expressionList();
1058         if (token == TokenNameSEMICOLON) {
1059           getNextToken();
1060         } else {
1061           throwSyntaxError("';' expected after 'for'.");
1062         }
1063       }
1064       if (token == TokenNameRPAREN) {
1065         getNextToken();
1066       } else {
1067         expressionList();
1068         if (token == TokenNameRPAREN) {
1069           getNextToken();
1070         } else {
1071           throwSyntaxError("')' expected after 'for'.");
1072         }
1073       }
1074       forStatement();
1075       return;
1076     } else if (token == TokenNamewhile) {
1077       getNextToken();
1078       if (token == TokenNameLPAREN) {
1079         getNextToken();
1080       } else {
1081         throwSyntaxError("'(' expected after 'while' keyword.");
1082       }
1083       expression();
1084       if (token == TokenNameRPAREN) {
1085         getNextToken();
1086       } else {
1087         throwSyntaxError("')' expected after 'while' condition.");
1088       }
1089       whileStatement();
1090       return;
1091     } else if (token == TokenNamedo) {
1092       getNextToken();
1093       if (token == TokenNameLBRACE) {
1094         getNextToken();
1095       } else {
1096         throwSyntaxError("'{' expected after 'do' keyword.");
1097       }
1098       if (token != TokenNameRBRACE) {
1099         statementList();
1100       }
1101       if (token == TokenNameRBRACE) {
1102         getNextToken();
1103       } else {
1104         throwSyntaxError("'}' expected after 'do' keyword.");
1105       }
1106       if (token == TokenNamewhile) {
1107         getNextToken();
1108         if (token == TokenNameLPAREN) {
1109           getNextToken();
1110         } else {
1111           throwSyntaxError("'(' expected after 'while' keyword.");
1112         }
1113         expression();
1114         if (token == TokenNameRPAREN) {
1115           getNextToken();
1116         } else {
1117           throwSyntaxError("')' expected after 'while' condition.");
1118         }
1119       } else {
1120         throwSyntaxError("'while' expected after 'do' keyword.");
1121       }
1122       if (token == TokenNameSEMICOLON) {
1123         getNextToken();
1124       } else {
1125         if (token != TokenNameStopPHP) {
1126           throwSyntaxError("';' expected after do-while statement.");
1127         }
1128         getNextToken();
1129       }
1130       return;
1131     } else if (token == TokenNameforeach) {
1132       getNextToken();
1133       if (token == TokenNameLPAREN) {
1134         getNextToken();
1135       } else {
1136         throwSyntaxError("'(' expected after 'foreach' keyword.");
1137       }
1138       expression();
1139       if (token == TokenNameas) {
1140         getNextToken();
1141       } else {
1142         throwSyntaxError("'as' expected after 'foreach' exxpression.");
1143       }
1144       variable();
1145       if (token == TokenNameEQUAL_GREATER) {
1146         getNextToken();
1147         variable();
1148       }
1149       if (token == TokenNameRPAREN) {
1150         getNextToken();
1151       } else {
1152         throwSyntaxError("')' expected after 'foreach' expression.");
1153       }
1154       foreachStatement();
1155       return;
1156
1157     } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
1158       getNextToken();
1159       if (token != TokenNameSEMICOLON) {
1160         expression();
1161       }
1162       if (token == TokenNameSEMICOLON) {
1163         getNextToken();
1164       } else {
1165         if (token != TokenNameStopPHP) {
1166           throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1167         }
1168         getNextToken();
1169       }
1170       return;
1171
1172     } else if (token == TokenNameecho) {
1173       getNextToken();
1174       expressionList();
1175       if (token == TokenNameSEMICOLON) {
1176         getNextToken();
1177       } else {
1178         if (token != TokenNameStopPHP) {
1179           throwSyntaxError("';' expected after 'echo' statement.");
1180         }
1181         getNextToken();
1182       }
1183       return;
1184       //    } else if (token == TokenNameprint) {
1185       //      getNextToken();
1186       //      expression();
1187       //      if (token == TokenNameSEMICOLON) {
1188       //        getNextToken();
1189       //      } else {
1190       //        if (token != TokenNameStopPHP) {
1191       //          throwSyntaxError("';' expected after 'print' statement.");
1192       //        }
1193       //        getNextToken();
1194       //      }
1195       //      return;
1196
1197     } else if (token == TokenNameglobal || token == TokenNamestatic) {
1198       getNextToken();
1199       variableList();
1200       if (token == TokenNameSEMICOLON) {
1201         getNextToken();
1202       } else {
1203         if (token != TokenNameStopPHP) {
1204           throwSyntaxError("';' expected after 'global' or 'static' statement.");
1205         }
1206         getNextToken();
1207       }
1208       return;
1209
1210       //      } else if (token == TokenNameunset) {
1211       //        getNextToken();
1212       //        if (token == TokenNameARGOPEN) {
1213       //          getNextToken();
1214       //        } else {
1215       //          throwSyntaxError("'(' expected after 'unset' keyword.");
1216       //        }
1217       //        variableList();
1218       //        if (token == TokenNameARGCLOSE) {
1219       //          getNextToken();
1220       //        } else {
1221       //          throwSyntaxError("')' expected after 'unset' statement.");
1222       //        }
1223       //        if (token == TokenNameSEMICOLON) {
1224       //          getNextToken();
1225       //        } else {
1226       //          if (token != TokenNameStopPHP) {
1227       //            throwSyntaxError("';' expected after 'unset' statement.");
1228       //          }
1229       //          getNextToken();
1230       //        }
1231       //        return;
1232
1233       //      } else if (token == TokenNameexit || token == TokenNamedie) {
1234       //        getNextToken();
1235       //        if (token != TokenNameSEMICOLON) {
1236       //          exitStatus();
1237       //        }
1238       //        if (token == TokenNameSEMICOLON) {
1239       //          getNextToken();
1240       //        } else {
1241       //          if (token != TokenNameStopPHP) {
1242       //            throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1243       //          }
1244       //          getNextToken();
1245       //        }
1246       //        return;
1247
1248     } else if (token == TokenNamedefine) {
1249       getNextToken();
1250       if (token == TokenNameLPAREN) {
1251         getNextToken();
1252       } else {
1253         throwSyntaxError("'(' expected after 'define' keyword.");
1254       }
1255       expression();
1256       if (token == TokenNameCOMMA) {
1257         getNextToken();
1258       } else {
1259         throwSyntaxError("',' expected after first 'define' constant.");
1260       }
1261       expression();
1262       if (token == TokenNameCOMMA) {
1263         getNextToken();
1264         expression();
1265       }
1266       if (token == TokenNameRPAREN) {
1267         getNextToken();
1268       } else {
1269         throwSyntaxError("')' expected after 'define' statement.");
1270       }
1271       if (token == TokenNameSEMICOLON) {
1272         getNextToken();
1273       } else {
1274         if (token != TokenNameStopPHP) {
1275           throwSyntaxError("';' expected after 'define' statement.");
1276         }
1277         getNextToken();
1278       }
1279       return;
1280     } else if (token == TokenNamefunction) {
1281       getNextToken();
1282       functionDefinition();
1283       return;
1284     } else if (token == TokenNameclass) {
1285       getNextToken();
1286       classDeclarator();
1287       classBody();
1288       return;
1289       //      } else {
1290       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
1291     } else if (token == TokenNameLBRACE) {
1292       // compoundStatement
1293       getNextToken();
1294       if (token != TokenNameRBRACE) {
1295         statementList();
1296       }
1297       if (token == TokenNameRBRACE) {
1298         getNextToken();
1299         return;
1300       } else {
1301         throwSyntaxError("'}' expected.");
1302       }
1303     } else {
1304       if (token != TokenNameSEMICOLON) {
1305         expression();
1306       }
1307       if (token == TokenNameSEMICOLON) {
1308         getNextToken();
1309         return;
1310       } else {
1311         if (token != TokenNameStopPHP && token != TokenNameEOF) {
1312           throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
1313         }
1314         getNextToken();
1315       }
1316     }
1317   }
1318
1319   private void classDeclarator() throws CoreException {
1320     //identifier
1321     //identifier 'extends' identifier
1322     if (token == TokenNameIdentifier) {
1323       getNextToken();
1324       if (token == TokenNameextends) {
1325         getNextToken();
1326         if (token == TokenNameIdentifier) {
1327           getNextToken();
1328         } else {
1329           throwSyntaxError("ClassDeclaration name expected after keyword 'extends'.");
1330         }
1331       }
1332     } else {
1333       if (token > TokenNameKEYWORD) {
1334         throwSyntaxError("Don't use keyword for class declaration [" + token + "].");
1335       }
1336       throwSyntaxError("ClassDeclaration name expected after keyword 'class'.");
1337     }
1338   }
1339
1340   private void classBody() throws CoreException {
1341     //'{' [class-element-list] '}'
1342     if (token == TokenNameLBRACE) {
1343       getNextToken();
1344       if (token != TokenNameRBRACE) {
1345         classElementList();
1346       }
1347       if (token == TokenNameRBRACE) {
1348         getNextToken();
1349       } else {
1350         throwSyntaxError("'}' expected at end of class body.");
1351       }
1352     } else {
1353       throwSyntaxError("'{' expected at start of class body.");
1354     }
1355   }
1356
1357   private void classElementList() throws CoreException {
1358     do {
1359       classElement();
1360     } while (token == TokenNamefunction || token == TokenNamevar);
1361   }
1362
1363   private void classElement() throws CoreException {
1364     //class-property
1365     //function-definition
1366     if (token == TokenNamefunction) {
1367       getNextToken();
1368       functionDefinition();
1369     } else if (token == TokenNamevar) {
1370       getNextToken();
1371       classProperty();
1372     } else {
1373       throwSyntaxError("'function' or 'var' expected.");
1374     }
1375   }
1376
1377   private void classProperty() throws CoreException {
1378     //'var' variable ';'
1379     //'var' variable '=' constant ';'
1380     do {
1381       if (token == TokenNameVariable) {
1382         getNextToken();
1383         if (token == TokenNameEQUAL) {
1384           getNextToken();
1385           constant();
1386         }
1387       } else {
1388         if (token == TokenNamethis) {
1389           throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
1390         }
1391         throwSyntaxError("Variable expected after keyword 'var'.");
1392       }
1393       if (token != TokenNameCOMMA) {
1394         break;
1395       }
1396       getNextToken();
1397     } while (true);
1398     if (token == TokenNameSEMICOLON) {
1399       getNextToken();
1400     } else {
1401       throwSyntaxError("';' expected after variable declaration.");
1402     }
1403   }
1404
1405   private void functionDefinition() throws CoreException {
1406     functionDeclarator();
1407     compoundStatement();
1408   }
1409
1410   private void functionDeclarator() throws CoreException {
1411     //identifier '(' [parameter-list] ')'
1412     if (token == TokenNameAND) {
1413       getNextToken();
1414     }
1415     if (token == TokenNameIdentifier) {
1416       getNextToken();
1417       if (token == TokenNameLPAREN) {
1418         getNextToken();
1419       } else {
1420         throwSyntaxError("'(' expected in function declaration.");
1421       }
1422       if (token != TokenNameRPAREN) {
1423         parameterList();
1424       }
1425       if (token != TokenNameRPAREN) {
1426         throwSyntaxError("')' expected in function declaration.");
1427       } else {
1428         getNextToken();
1429       }
1430     } else {
1431       if (token > TokenNameKEYWORD) {
1432         throwSyntaxError("Don't use keyword for function declaration [" + token + "].");
1433       }
1434       throwSyntaxError("Function name expected after keyword 'function'.");
1435     }
1436   }
1437   //
1438   private void parameterList() throws CoreException {
1439     //parameter-declaration
1440     //parameter-list ',' parameter-declaration
1441     do {
1442       parameterDeclaration();
1443       if (token != TokenNameCOMMA) {
1444         break;
1445       }
1446       getNextToken();
1447     } while (true);
1448   }
1449
1450   private void parameterDeclaration() throws CoreException {
1451     //variable
1452     //variable-reference
1453     if (token == TokenNameAND) {
1454       getNextToken();
1455       if (isVariable()) {
1456         getNextToken();
1457       } else {
1458         throwSyntaxError("Variable expected after reference operator '&'.");
1459       }
1460     }
1461     //variable '=' constant
1462     if (token == TokenNameVariable) {
1463       getNextToken();
1464       if (token == TokenNameEQUAL) {
1465         getNextToken();
1466         constant();
1467       }
1468       return;
1469     }
1470     if (token == TokenNamethis) {
1471       throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
1472     }
1473   }
1474
1475   private void labeledStatementList() throws CoreException {
1476     if (token != TokenNamecase && token != TokenNamedefault) {
1477       throwSyntaxError("'case' or 'default' expected.");
1478     }
1479     do {
1480       if (token == TokenNamecase) {
1481         getNextToken();
1482         expression(); //constant();
1483         if (token == TokenNameCOLON) {
1484           getNextToken();
1485           if (token == TokenNamecase || token == TokenNamedefault) { // empty case statement ?
1486             continue;
1487           }
1488           statementList();
1489         } else if (token == TokenNameSEMICOLON) {
1490           //          setMarker(
1491           //            "':' expected after 'case' keyword (Found token: "
1492           //              + scanner.toStringAction(token)
1493           //              + ")",
1494           //            rowCount,
1495           //            PHPParser.INFO);
1496           setMarker(
1497             "':' expected after 'case' keyword (Found token: " + scanner.toStringAction(token) + ")",
1498             scanner.getCurrentTokenStartPosition(),
1499             scanner.getCurrentTokenEndPosition(),
1500             INFO);
1501           getNextToken();
1502           if (token == TokenNamecase) { // empty case statement ?
1503             continue;
1504           }
1505           statementList();
1506         } else {
1507           throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
1508         }
1509       } else { // TokenNamedefault
1510         getNextToken();
1511         if (token == TokenNameCOLON) {
1512           getNextToken();
1513           statementList();
1514         } else {
1515           throwSyntaxError("':' character after 'default' expected.");
1516         }
1517       }
1518     } while (token == TokenNamecase || token == TokenNamedefault);
1519   }
1520
1521   //  public void labeledStatement() {
1522   //    if (token == TokenNamecase) {
1523   //      getNextToken();
1524   //      constant();
1525   //      if (token == TokenNameDDOT) {
1526   //        getNextToken();
1527   //        statement();
1528   //      } else {
1529   //        throwSyntaxError("':' character after 'case' constant expected.");
1530   //      }
1531   //      return;
1532   //    } else if (token == TokenNamedefault) {
1533   //      getNextToken();
1534   //      if (token == TokenNameDDOT) {
1535   //        getNextToken();
1536   //        statement();
1537   //      } else {
1538   //        throwSyntaxError("':' character after 'default' expected.");
1539   //      }
1540   //      return;
1541   //    }
1542   //  }
1543
1544   //  public void expressionStatement() {
1545   //  }
1546
1547   //  private void inclusionStatement() {
1548   //  }
1549
1550   //  public void compoundStatement() {
1551   //  }
1552
1553   //  public void selectionStatement() {
1554   //  }
1555   //
1556   //  public void iterationStatement() {
1557   //  }
1558   //
1559   //  public void jumpStatement() {
1560   //  }
1561   //
1562   //  public void outputStatement() {
1563   //  }
1564   //
1565   //  public void scopeStatement() {
1566   //  }
1567   //
1568   //  public void flowStatement() {
1569   //  }
1570   //
1571   //  public void definitionStatement() {
1572   //  }
1573
1574   private void ifStatement() throws CoreException {
1575     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1576     if (token == TokenNameCOLON) {
1577       getNextToken();
1578       if (token != TokenNameendif) {
1579         statementList();
1580         switch (token) {
1581           case TokenNameelse :
1582             getNextToken();
1583             if (token == TokenNameCOLON) {
1584               getNextToken();
1585               if (token != TokenNameendif) {
1586                 statementList();
1587               }
1588             } else {
1589               if (token == TokenNameif) { //'else if'
1590                 getNextToken();
1591                 elseifStatementList();
1592               } else {
1593                 throwSyntaxError("':' expected after 'else'.");
1594               }
1595             }
1596             break;
1597           case TokenNameelseif :
1598             getNextToken();
1599             elseifStatementList();
1600             break;
1601         }
1602       }
1603
1604       if (token != TokenNameendif) {
1605         throwSyntaxError("'endif' expected.");
1606       }
1607       getNextToken();
1608       if (token != TokenNameSEMICOLON) {
1609         throwSyntaxError("';' expected after if-statement.");
1610       }
1611       getNextToken();
1612     } else {
1613       // statement [else-statement]
1614       statement();
1615       if (token == TokenNameelseif) {
1616         getNextToken();
1617         if (token == TokenNameLPAREN) {
1618           getNextToken();
1619         } else {
1620           throwSyntaxError("'(' expected after 'elseif' keyword.");
1621         }
1622         expression();
1623         if (token == TokenNameRPAREN) {
1624           getNextToken();
1625         } else {
1626           throwSyntaxError("')' expected after 'elseif' condition.");
1627         }
1628         ifStatement();
1629       } else if (token == TokenNameelse) {
1630         getNextToken();
1631         statement();
1632       }
1633     }
1634   }
1635
1636   private void elseifStatementList() throws CoreException {
1637     do {
1638       elseifStatement();
1639       switch (token) {
1640         case TokenNameelse :
1641           getNextToken();
1642           if (token == TokenNameCOLON) {
1643             getNextToken();
1644             if (token != TokenNameendif) {
1645               statementList();
1646             }
1647             return;
1648           } else {
1649             if (token == TokenNameif) { //'else if'
1650               getNextToken();
1651             } else {
1652               throwSyntaxError("':' expected after 'else'.");
1653             }
1654           }
1655           break;
1656         case TokenNameelseif :
1657           getNextToken();
1658           break;
1659         default :
1660           return;
1661       }
1662     } while (true);
1663   }
1664
1665   private void elseifStatement() throws CoreException {
1666     if (token == TokenNameLPAREN) {
1667       getNextToken();
1668       expression();
1669       if (token != TokenNameRPAREN) {
1670         throwSyntaxError("')' expected in else-if-statement.");
1671       }
1672       getNextToken();
1673       if (token != TokenNameCOLON) {
1674         throwSyntaxError("':' expected in else-if-statement.");
1675       }
1676       getNextToken();
1677       if (token != TokenNameendif) {
1678         statementList();
1679       }
1680     }
1681   }
1682
1683   private void switchStatement() throws CoreException {
1684     if (token == TokenNameCOLON) {
1685       // ':' [labeled-statement-list] 'endswitch' ';'
1686       getNextToken();
1687       labeledStatementList();
1688       if (token != TokenNameendswitch) {
1689         throwSyntaxError("'endswitch' expected.");
1690       }
1691       getNextToken();
1692       if (token != TokenNameSEMICOLON) {
1693         throwSyntaxError("';' expected after switch-statement.");
1694       }
1695       getNextToken();
1696     } else {
1697       // '{' [labeled-statement-list] '}'
1698       if (token != TokenNameLBRACE) {
1699         throwSyntaxError("'{' expected in switch statement.");
1700       }
1701       getNextToken();
1702       if (token != TokenNameRBRACE) {
1703         labeledStatementList();
1704       }
1705       if (token != TokenNameRBRACE) {
1706         throwSyntaxError("'}' expected in switch statement.");
1707       }
1708       getNextToken();
1709
1710     }
1711   }
1712
1713   private void forStatement() throws CoreException {
1714     if (token == TokenNameCOLON) {
1715       getNextToken();
1716       statementList();
1717       if (token != TokenNameendfor) {
1718         throwSyntaxError("'endfor' expected.");
1719       }
1720       getNextToken();
1721       if (token != TokenNameSEMICOLON) {
1722         throwSyntaxError("';' expected after for-statement.");
1723       }
1724       getNextToken();
1725     } else {
1726       statement();
1727     }
1728   }
1729
1730   private void whileStatement() throws CoreException {
1731     // ':' statement-list 'endwhile' ';'
1732     if (token == TokenNameCOLON) {
1733       getNextToken();
1734       statementList();
1735       if (token != TokenNameendwhile) {
1736         throwSyntaxError("'endwhile' expected.");
1737       }
1738       getNextToken();
1739       if (token != TokenNameSEMICOLON) {
1740         throwSyntaxError("';' expected after while-statement.");
1741       }
1742       getNextToken();
1743     } else {
1744       statement();
1745     }
1746   }
1747
1748   private void foreachStatement() throws CoreException {
1749     if (token == TokenNameCOLON) {
1750       getNextToken();
1751       statementList();
1752       if (token != TokenNameendforeach) {
1753         throwSyntaxError("'endforeach' expected.");
1754       }
1755       getNextToken();
1756       if (token != TokenNameSEMICOLON) {
1757         throwSyntaxError("';' expected after foreach-statement.");
1758       }
1759       getNextToken();
1760     } else {
1761       statement();
1762     }
1763   }
1764
1765   private void exitStatus() throws CoreException {
1766     if (token == TokenNameLPAREN) {
1767       getNextToken();
1768     } else {
1769       throwSyntaxError("'(' expected in 'exit-status'.");
1770     }
1771     if (token != TokenNameRPAREN) {
1772       expression();
1773     }
1774     if (token == TokenNameRPAREN) {
1775       getNextToken();
1776     } else {
1777       throwSyntaxError("')' expected after 'exit-status'.");
1778     }
1779   }
1780
1781   private void expressionList() throws CoreException {
1782     do {
1783       expression();
1784       if (token == TokenNameCOMMA) {
1785         getNextToken();
1786       } else {
1787         break;
1788       }
1789     } while (true);
1790   }
1791
1792   private void expression() throws CoreException {
1793     //todo: find a better way to get the expression
1794     //    expression = new StringBuffer();
1795     //    for (int i = chIndx; i < str.length(); i++) {
1796     //      if (str.charAt(i) == ';') {
1797     //        break;
1798     //      }
1799     //      expression.append(str.charAt(i));
1800     //    }
1801
1802     //    if (token == TokenNameSTRING_CONSTANT || token == TokenNameINTERPOLATED_STRING) {
1803     //      getNextToken();
1804     //    } else {
1805     logicalinclusiveorExpression();
1806     //      while (token != TokenNameSEMICOLON) {
1807     //        getNextToken();
1808     //      //      }
1809     //    }
1810   }
1811
1812   private void postfixExpression() throws CoreException {
1813     //  String ident;
1814     char[] ident;
1815     boolean castFlag = false;
1816     switch (token) {
1817       case TokenNamenew :
1818         getNextToken();
1819         expression();
1820         break;
1821       case TokenNamenull :
1822         getNextToken();
1823         break;
1824       case TokenNamefalse :
1825         getNextToken();
1826         break;
1827       case TokenNametrue :
1828         getNextToken();
1829         break;
1830       case TokenNameStringConstant :
1831         getNextToken();
1832         break;
1833       case TokenNameHEREDOC :
1834       case TokenNameStringInterpolated :
1835       case TokenNameStringLiteral :
1836         getNextToken();
1837         break;
1838       case TokenNameLPAREN :
1839         getNextToken();
1840         if (token == TokenNameIdentifier) {
1841           // check if identifier is a type:
1842           //    ident = identifier;
1843           ident = scanner.getCurrentIdentifierSource();
1844           String str = new String(ident).toLowerCase();
1845           for (int i = 0; i < PHP_TYPES.length; i++) {
1846             if (PHP_TYPES[i].equals(str)) {
1847               castFlag = true;
1848               break;
1849             }
1850           }
1851           if (castFlag) {
1852             getNextToken();
1853             if (token != TokenNameRPAREN) {
1854               throwSyntaxError(") expected after cast-type '" + str + "'.");
1855             }
1856             getNextToken();
1857             expression();
1858             break;
1859           }
1860         }
1861         if (!castFlag) {
1862           expression();
1863         }
1864         if (token != TokenNameRPAREN) {
1865           throwSyntaxError(") expected in postfix-expression.");
1866         }
1867         getNextToken();
1868         break;
1869       case TokenNameDoubleLiteral :
1870         getNextToken();
1871         break;
1872       case TokenNameIntegerLiteral :
1873         getNextToken();
1874         break;
1875       case TokenNameDOLLAR_LBRACE :
1876         getNextToken();
1877         expression();
1878         if (token != TokenNameRBRACE) {
1879           throwSyntaxError("'}' expected after indirect variable token '${'.");
1880         }
1881         getNextToken();
1882         break;
1883       case TokenNameVariable :
1884       case TokenNamethis :
1885         ident = scanner.getCurrentIdentifierSource();
1886         getNextToken();
1887         if (token == TokenNameLBRACE) {
1888           getNextToken();
1889           expression();
1890           if (token != TokenNameRBRACE) {
1891             throwSyntaxError("'}' expected after variable '" + new String(ident) + "' in variable-expression.");
1892           }
1893           getNextToken();
1894         } else if (token == TokenNameLPAREN) {
1895           getNextToken();
1896           if (token != TokenNameRPAREN) {
1897             expressionList();
1898             if (token != TokenNameRPAREN) {
1899               throwSyntaxError("')' expected after variable '" + new String(ident) + "' in postfix-expression.");
1900             }
1901           }
1902           getNextToken();
1903         }
1904         break;
1905       case TokenNameIdentifier :
1906         ident = scanner.getCurrentIdentifierSource();
1907         getNextToken();
1908         if (token == TokenNameLPAREN) {
1909           getNextToken();
1910           if (token != TokenNameRPAREN) {
1911             expressionList();
1912             if (token != TokenNameRPAREN) {
1913               throwSyntaxError(
1914                 "')' expected after identifier '"
1915                   + new String(ident)
1916                   + "' in postfix-expression."
1917                   + "(Found token: "
1918                   + scanner.toStringAction(token)
1919                   + ")");
1920             }
1921           }
1922           getNextToken();
1923         }
1924         break;
1925       case TokenNameprint :
1926         getNextToken();
1927         expression();
1928         //        if (token == TokenNameSEMICOLON) {
1929         //          getNextToken();
1930         //        } else {
1931         //          if (token != TokenNameStopPHP) {
1932         //            throwSyntaxError("';' expected after 'print' statement.");
1933         //          }
1934         //          getNextToken();
1935         //        }
1936         break;
1937       case TokenNamelist :
1938         getNextToken();
1939         if (token == TokenNameLPAREN) {
1940           getNextToken();
1941           if (token == TokenNameCOMMA) {
1942             getNextToken();
1943           }
1944           expressionList();
1945           if (token != TokenNameRPAREN) {
1946             throwSyntaxError("')' expected after 'list' keyword.");
1947           }
1948           getNextToken();
1949           //          if (token == TokenNameSET) {
1950           //            getNextToken();
1951           //            logicalinclusiveorExpression();
1952           //          }
1953         } else {
1954           throwSyntaxError("'(' expected after 'list' keyword.");
1955         }
1956         break;
1957         //      case TokenNameexit :
1958         //        getNextToken();
1959         //        if (token != TokenNameSEMICOLON) {
1960         //          exitStatus();
1961         //        }
1962         //        if (token == TokenNameSEMICOLON) {
1963         //          getNextToken();
1964         //        } else {
1965         //          if (token != TokenNameStopPHP) {
1966         //            throwSyntaxError("';' expected after 'exit' expression.");
1967         //          }
1968         //          getNextToken();
1969         //        }
1970         //        break;
1971         //      case TokenNamedie :
1972         //        getNextToken();
1973         //        if (token != TokenNameSEMICOLON) {
1974         //          exitStatus();
1975         //        }
1976         //        if (token == TokenNameSEMICOLON) {
1977         //          getNextToken();
1978         //        } else {
1979         //          if (token != TokenNameStopPHP) {
1980         //            throwSyntaxError("';' expected after 'die' expression.");
1981         //          }
1982         //        }
1983         //        break;
1984
1985         //      case TokenNamearray :
1986         //        getNextToken();
1987         //        if (token == TokenNameARGOPEN) {
1988         //          getNextToken();
1989         //          if (token == TokenNameCOMMA) {
1990         //            getNextToken();
1991         //          }
1992         //          expressionList();
1993         //          if (token != TokenNameARGCLOSE) {
1994         //            throwSyntaxError("')' expected after 'list' keyword.");
1995         //          }
1996         //          getNextToken();
1997         //          if (token == TokenNameSET) {
1998         //            getNextToken();
1999         //            logicalinclusiveorExpression();
2000         //          }
2001         //        } else {
2002         //          throwSyntaxError("'(' expected after 'list' keyword.");
2003         //        }
2004         //        break;
2005     }
2006     boolean while_flag = true;
2007     do {
2008       switch (token) {
2009         case TokenNameLBRACKET :
2010           getNextToken();
2011           expression();
2012           if (token != TokenNameRBRACKET) {
2013             throwSyntaxError("] expected in postfix-expression.");
2014           }
2015           getNextToken();
2016           break;
2017         case TokenNameCOLON_COLON : // ::
2018         case TokenNameMINUS_GREATER : // ->
2019           getNextToken();
2020           if (token > TokenNameKEYWORD) {
2021             ident = scanner.getCurrentIdentifierSource();
2022             //            setMarker(
2023             //              "Avoid using keyword '"
2024             //                + new String(ident)
2025             //                + "' as variable name.",
2026             //              rowCount,
2027             //              PHPParser.INFO);
2028             setMarker(
2029               "Avoid using keyword '" + new String(ident) + "' as variable name.",
2030               scanner.getCurrentTokenStartPosition(),
2031               scanner.getCurrentTokenEndPosition(),
2032               INFO);
2033           }
2034           switch (token) {
2035             case TokenNameVariable :
2036               ident = scanner.getCurrentIdentifierSource();
2037               getNextToken();
2038               //              if (token == TokenNameARGOPEN) {
2039               //                getNextToken();
2040               //                expressionList();
2041               //                if (token != TokenNameARGCLOSE) {
2042               //                  throwSyntaxError(") expected after variable '" + ident + "'.");
2043               //                }
2044               //                getNextToken();
2045               //              }
2046               break;
2047             case TokenNameIdentifier :
2048               //ident = scanner.getCurrentIdentifierSource();
2049               getNextToken();
2050               break;
2051             case TokenNameLBRACE :
2052               getNextToken();
2053               expression();
2054               if (token != TokenNameRBRACE) {
2055                 throwSyntaxError("} expected in postfix-expression.");
2056               }
2057               getNextToken();
2058               break;
2059             default :
2060               throwSyntaxError("Syntax error after '->' token.");
2061           } while (token == TokenNameLBRACKET || token == TokenNameLPAREN || token == TokenNameLBRACE) {
2062               if (token == TokenNameLBRACKET) {
2063                 getNextToken();
2064                 expressionList();
2065                 if (token != TokenNameRBRACKET) {
2066                   throwSyntaxError("] expected after '->'.");
2067                 }
2068                 getNextToken();
2069               } else if (token == TokenNameLPAREN) {
2070                 getNextToken();
2071                 expressionList();
2072                 if (token != TokenNameRPAREN) {
2073                   throwSyntaxError(") expected after '->'.");
2074                 }
2075                 getNextToken();
2076               } else if (token == TokenNameLBRACE) {
2077                 getNextToken();
2078                 expression();
2079                 if (token != TokenNameRBRACE) {
2080                   throwSyntaxError("} expected after '->'.");
2081                 }
2082                 getNextToken();
2083               }
2084             }
2085           break;
2086         case TokenNamePLUS_PLUS :
2087           getNextToken();
2088           break;
2089         case TokenNameMINUS_MINUS :
2090           getNextToken();
2091           break;
2092         default :
2093           while_flag = false;
2094       }
2095
2096     }
2097     while (while_flag);
2098   }
2099
2100   private void unaryExpression() throws CoreException {
2101     switch (token) {
2102       case TokenNamePLUS_PLUS :
2103         getNextToken();
2104         unaryExpression();
2105         break;
2106       case TokenNameMINUS_MINUS :
2107         getNextToken();
2108         unaryExpression();
2109         break;
2110         // '@' '&' '*' '+' '-' '~' '!'
2111       case TokenNameAT :
2112         getNextToken();
2113         if (token == TokenNameinclude
2114           || token == TokenNameinclude_once
2115           || token == TokenNamerequire
2116           || token == TokenNamerequire_once) {
2117           statement();
2118         } else {
2119           postfixExpression(); //  castExpression();
2120         }
2121         break;
2122       case TokenNameAND :
2123         getNextToken();
2124         castExpression();
2125         break;
2126       case TokenNameMULTIPLY :
2127         getNextToken();
2128         castExpression();
2129         break;
2130       case TokenNamePLUS :
2131         getNextToken();
2132         castExpression();
2133         break;
2134       case TokenNameMINUS :
2135         getNextToken();
2136         castExpression();
2137         break;
2138       case TokenNameTWIDDLE :
2139         getNextToken();
2140         castExpression();
2141         break;
2142       case TokenNameNOT :
2143         getNextToken();
2144         castExpression();
2145         break;
2146       default :
2147         postfixExpression();
2148     }
2149   }
2150
2151   private void castExpression() throws CoreException {
2152     //    if (token == TokenNameARGOPEN) {
2153     //      getNextToken();
2154     //      typeName();
2155     //      if (token != TokenNameARGCLOSE) {
2156     //        throwSyntaxError(") expected after cast-expression.");
2157     //      }
2158     //      getNextToken();
2159     //    }
2160     unaryExpression();
2161   }
2162
2163   private void assignExpression() throws CoreException {
2164     castExpression();
2165     if (token == TokenNameEQUAL) { // =
2166       getNextToken();
2167       logicalinclusiveorExpression();
2168     } else if (token == TokenNameDOT_EQUAL) { // .=
2169       getNextToken();
2170       logicalinclusiveorExpression();
2171     } else if (token == TokenNameEQUAL_GREATER) { // =>
2172       getNextToken();
2173       logicalinclusiveorExpression();
2174     } else if (token == TokenNamePLUS_EQUAL) { // +=
2175       getNextToken();
2176       logicalinclusiveorExpression();
2177     } else if (token == TokenNameMINUS_EQUAL) { // -=
2178       getNextToken();
2179       logicalinclusiveorExpression();
2180     } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2181       getNextToken();
2182       logicalinclusiveorExpression();
2183     } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2184       getNextToken();
2185       logicalinclusiveorExpression();
2186     } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2187       getNextToken();
2188       logicalinclusiveorExpression();
2189     } else if (token == TokenNameAND_EQUAL) { // &=
2190       getNextToken();
2191       logicalinclusiveorExpression();
2192     } else if (token == TokenNameOR_EQUAL) { // |=
2193       getNextToken();
2194       logicalinclusiveorExpression();
2195     } else if (token == TokenNameXOR_EQUAL) { // ^=
2196       getNextToken();
2197       logicalinclusiveorExpression();
2198     } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2199       getNextToken();
2200       logicalinclusiveorExpression();
2201     } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2202       getNextToken();
2203       logicalinclusiveorExpression();
2204     } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2205       getNextToken();
2206       logicalinclusiveorExpression();
2207     }
2208   }
2209
2210   private void multiplicativeExpression() throws CoreException {
2211     do {
2212       assignExpression();
2213       if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE && token != TokenNameREMAINDER) {
2214         return;
2215       }
2216       getNextToken();
2217     } while (true);
2218   }
2219
2220   private void concatenationExpression() throws CoreException {
2221     do {
2222       multiplicativeExpression();
2223       if (token != TokenNameDOT) {
2224         return;
2225       }
2226       getNextToken();
2227     } while (true);
2228   }
2229
2230   private void additiveExpression() throws CoreException {
2231     do {
2232       concatenationExpression();
2233       if (token != TokenNamePLUS && token != TokenNameMINUS) {
2234         return;
2235       }
2236       getNextToken();
2237     } while (true);
2238   }
2239
2240   private void shiftExpression() throws CoreException {
2241     do {
2242       additiveExpression();
2243       if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2244         return;
2245       }
2246       getNextToken();
2247     } while (true);
2248   }
2249
2250   private void relationalExpression() throws CoreException {
2251     do {
2252       shiftExpression();
2253       if (token != TokenNameLESS && token != TokenNameGREATER && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2254         return;
2255       }
2256       getNextToken();
2257     } while (true);
2258   }
2259
2260   private void identicalExpression() throws CoreException {
2261     do {
2262       relationalExpression();
2263       if (token != TokenNameEQUAL_EQUAL_EQUAL && token != TokenNameNOT_EQUAL_EQUAL) {
2264         return;
2265       }
2266       getNextToken();
2267     } while (true);
2268   }
2269
2270   private void equalityExpression() throws CoreException {
2271     do {
2272       identicalExpression();
2273       if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2274         return;
2275       }
2276       getNextToken();
2277     } while (true);
2278   }
2279
2280   private void ternaryExpression() throws CoreException {
2281     equalityExpression();
2282     if (token == TokenNameQUESTION) {
2283       getNextToken();
2284       expression();
2285       if (token == TokenNameCOLON) {
2286         getNextToken();
2287         expression();
2288       } else {
2289         throwSyntaxError("':' expected in ternary operator '? :'.");
2290       }
2291     }
2292   }
2293
2294   private void andExpression() throws CoreException {
2295     do {
2296       ternaryExpression();
2297       if (token != TokenNameAND) {
2298         return;
2299       }
2300       getNextToken();
2301     } while (true);
2302   }
2303
2304   private void exclusiveorExpression() throws CoreException {
2305     do {
2306       andExpression();
2307       if (token != TokenNameXOR) {
2308         return;
2309       }
2310       getNextToken();
2311     } while (true);
2312   }
2313
2314   private void inclusiveorExpression() throws CoreException {
2315     do {
2316       exclusiveorExpression();
2317       if (token != TokenNameOR) {
2318         return;
2319       }
2320       getNextToken();
2321     } while (true);
2322   }
2323
2324   private void booleanandExpression() throws CoreException {
2325     do {
2326       inclusiveorExpression();
2327       if (token != TokenNameAND_AND) {
2328         return;
2329       }
2330       getNextToken();
2331     } while (true);
2332   }
2333
2334   private void booleanorExpression() throws CoreException {
2335     do {
2336       booleanandExpression();
2337       if (token != TokenNameOR_OR) {
2338         return;
2339       }
2340       getNextToken();
2341     } while (true);
2342   }
2343
2344   private void logicalandExpression() throws CoreException {
2345     do {
2346       booleanorExpression();
2347       if (token != TokenNameAND) {
2348         return;
2349       }
2350       getNextToken();
2351     } while (true);
2352   }
2353
2354   private void logicalexclusiveorExpression() throws CoreException {
2355     do {
2356       logicalandExpression();
2357       if (token != TokenNameXOR) {
2358         return;
2359       }
2360       getNextToken();
2361     } while (true);
2362   }
2363
2364   private void logicalinclusiveorExpression() throws CoreException {
2365     do {
2366       logicalexclusiveorExpression();
2367       if (token != TokenNameOR) {
2368         return;
2369       }
2370       getNextToken();
2371     } while (true);
2372   }
2373
2374   //  public void assignmentExpression() {
2375   //    if (token == TokenNameVARIABLE) {
2376   //      getNextToken();
2377   //      if (token == TokenNameSET) {
2378   //        getNextToken();
2379   //        logicalinclusiveorExpression();
2380   //      }
2381   //    } else {
2382   //      logicalinclusiveorExpression();
2383   //    }
2384   //  }
2385
2386   private void variableList() throws CoreException {
2387     do {
2388       variable();
2389       if (token == TokenNameCOMMA) {
2390         getNextToken();
2391       } else {
2392         break;
2393       }
2394     } while (true);
2395   }
2396
2397   private void variable() throws CoreException {
2398     if (token == TokenNameDOLLAR_LBRACE) {
2399       getNextToken();
2400       expression();
2401       ;
2402       if (token != TokenNameRBRACE) {
2403         throwSyntaxError("'}' expected after indirect variable token '${'.");
2404       }
2405       getNextToken();
2406     } else {
2407       if (token == TokenNameVariable) {
2408         getNextToken();
2409         if (token == TokenNameLBRACKET) {
2410           getNextToken();
2411           expression();
2412           if (token != TokenNameRBRACKET) {
2413             throwSyntaxError("']' expected in variable-list.");
2414           }
2415           getNextToken();
2416         } else if (token == TokenNameEQUAL) {
2417           getNextToken();
2418           constant();
2419         }
2420       } else {
2421         throwSyntaxError("$-variable expected in variable-list.");
2422       }
2423     }
2424   }
2425
2426   /**
2427    * It will look for a value (after a '=' for example)
2428    * @throws CoreException
2429    */
2430   private void constant() throws CoreException {
2431     //   String ident;
2432     switch (token) {
2433       case TokenNamePLUS :
2434         getNextToken();
2435         switch (token) {
2436           case TokenNameDoubleLiteral :
2437             getNextToken();
2438             break;
2439           case TokenNameIntegerLiteral :
2440             getNextToken();
2441             break;
2442           default :
2443             throwSyntaxError("Constant expected after '+' presign.");
2444         }
2445         break;
2446       case TokenNameMINUS :
2447         getNextToken();
2448         switch (token) {
2449           case TokenNameDoubleLiteral :
2450             getNextToken();
2451             break;
2452           case TokenNameIntegerLiteral :
2453             getNextToken();
2454             break;
2455           default :
2456             throwSyntaxError("Constant expected after '-' presign.");
2457         }
2458         break;
2459       case TokenNamenull :
2460         getNextToken();
2461         break;
2462       case TokenNamefalse :
2463         getNextToken();
2464         break;
2465       case TokenNametrue :
2466         getNextToken();
2467         break;
2468       case TokenNameIdentifier :
2469         //   ident = identifier;
2470         char[] ident = scanner.getCurrentIdentifierSource();
2471         getNextToken();
2472         if (token == TokenNameLPAREN) {
2473           getNextToken();
2474           if (token != TokenNameRPAREN) {
2475             expressionList();
2476             if (token != TokenNameRPAREN) {
2477               throwSyntaxError("')' expected after identifier '" + new String(ident) + "' in postfix-expression.");
2478             }
2479           }
2480           getNextToken();
2481         }
2482         break;
2483       case TokenNameStringLiteral :
2484         getNextToken();
2485         break;
2486       case TokenNameStringConstant :
2487         getNextToken();
2488         break;
2489       case TokenNameStringInterpolated :
2490         getNextToken();
2491         break;
2492       case TokenNameDoubleLiteral :
2493         getNextToken();
2494         break;
2495       case TokenNameIntegerLiteral :
2496         getNextToken();
2497         break;
2498       default :
2499         throwSyntaxError("Constant expected.");
2500     }
2501   }
2502
2503 }