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