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 == TokenNamefinal) {
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     }
1439   }
1440   private void interface_extends_list() {
1441     //  /* empty */
1442     //  | T_EXTENDS interface_list
1443     if (token == TokenNameextends) {
1444       getNextToken();
1445       interface_list();
1446     }
1447   }
1448   private void implements_list() {
1449     //  /* empty */
1450     //  | T_IMPLEMENTS interface_list
1451     if (token == TokenNameimplements) {
1452       getNextToken();
1453       interface_list();
1454     }
1455   }
1456   private void interface_list() {
1457     //  interface_list:
1458     //  fully_qualified_class_name
1459     //| interface_list ',' fully_qualified_class_name
1460     do {
1461       if (token == TokenNameIdentifier) {
1462         getNextToken();
1463       } else {
1464         throwSyntaxError("Interface name expected after keyword 'implements'.");
1465       }
1466       if (token != TokenNameCOMMA) {
1467         return;
1468       }
1469       getNextToken();
1470     } while (true);
1471   }
1472   //  private void classBody(TypeDeclaration typeDecl) {
1473   //    //'{' [class-element-list] '}'
1474   //    if (token == TokenNameLBRACE) {
1475   //      getNextToken();
1476   //      if (token != TokenNameRBRACE) {
1477   //        class_statement_list();
1478   //      }
1479   //      if (token == TokenNameRBRACE) {
1480   //        typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1481   //        getNextToken();
1482   //      } else {
1483   //        throwSyntaxError("'}' expected at end of class body.");
1484   //      }
1485   //    } else {
1486   //      throwSyntaxError("'{' expected at start of class body.");
1487   //    }
1488   //  }
1489   private void class_statement_list() {
1490     do {
1491       class_statement();
1492     } while (token == TokenNamefunction || token == TokenNamevar);
1493   }
1494   private void class_statement() {
1495     //    class_statement:
1496     //          variable_modifiers class_variable_declaration ';'
1497     //  | class_constant_declaration ';'
1498     //  | method_modifiers T_FUNCTION is_reference T_STRING
1499     //    '(' parameter_list ')' method_body
1500     initializeModifiers();
1501     if (token == TokenNamevar) {
1502       checkAndSetModifiers(AccPublic);
1503       reportSyntaxError(
1504           "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected' modifier for field declarations.",
1505           scanner.getCurrentTokenStartPosition(), scanner
1506               .getCurrentTokenEndPosition());
1507       getNextToken();
1508       classProperty();
1509     } else {
1510       boolean hasModifiers = member_modifiers();
1511       if (token == TokenNamefunction) {
1512         if (!hasModifiers) {
1513           checkAndSetModifiers(AccPublic);
1514         }
1515         MethodDeclaration methodDecl = new MethodDeclaration(
1516             this.compilationUnit.compilationResult);
1517         methodDecl.declarationSourceStart = scanner
1518             .getCurrentTokenStartPosition();
1519         methodDecl.modifiers = this.modifiers;
1520         getNextToken();
1521         functionDefinition(methodDecl);
1522       } else {
1523         if (!hasModifiers) {
1524           throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1525         }
1526         classProperty();
1527       }
1528     }
1529     //    if (token == TokenNamefunction) {
1530     //      MethodDeclaration methodDecl = new MethodDeclaration(
1531     //          this.compilationUnit.compilationResult);
1532     //      methodDecl.declarationSourceStart = scanner
1533     //          .getCurrentTokenStartPosition();
1534     //      getNextToken();
1535     //      functionDefinition(methodDecl);
1536     //    } else if (token == TokenNamevar) {
1537     //      getNextToken();
1538     //      classProperty();
1539     //    } else {
1540     //      throwSyntaxError("'function' or 'var' expected.");
1541     //    }
1542   }
1543   //  private void variable_modifiers() {
1544   //    // variable_modifiers:
1545   //    // non_empty_member_modifiers
1546   //    //| T_VAR
1547   //    initializeModifiers();
1548   //    if (token == TokenNamevar) {
1549   //      checkAndSetModifiers(AccPublic);
1550   //      reportSyntaxError(
1551   //          "Keyword 'var' is deprecated. Please use 'public' 'private' or 'protected'
1552   // modifier for field declarations.",
1553   //          scanner.getCurrentTokenStartPosition(), scanner
1554   //              .getCurrentTokenEndPosition());
1555   //      getNextToken();
1556   //    } else {
1557   //      if (!member_modifiers()) {
1558   //        throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1559   // field declarations.");
1560   //      }
1561   //    }
1562   //  }
1563   //  private void method_modifiers() {
1564   //    //method_modifiers:
1565   //    // /* empty */
1566   //    //| non_empty_member_modifiers
1567   //    initializeModifiers();
1568   //    if (!member_modifiers()) {
1569   //      checkAndSetModifiers(AccPublic);
1570   //    }
1571   //  }
1572   private boolean member_modifiers() {
1573     //  T_PUBLIC
1574     //| T_PROTECTED
1575     //| T_PRIVATE
1576     //| T_STATIC
1577     //| T_ABSTRACT
1578     //| T_FINAL
1579     boolean foundToken = false;
1580     while (true) {
1581       if (token == TokenNamepublic) {
1582         checkAndSetModifiers(AccPublic);
1583         getNextToken();
1584         foundToken = true;
1585       } else if (token == TokenNameprotected) {
1586         checkAndSetModifiers(AccProtected);
1587         getNextToken();
1588         foundToken = true;
1589       } else if (token == TokenNameprivate) {
1590         checkAndSetModifiers(AccPrivate);
1591         getNextToken();
1592         foundToken = true;
1593       } else if (token == TokenNamestatic) {
1594         checkAndSetModifiers(AccStatic);
1595         getNextToken();
1596         foundToken = true;
1597       } else if (token == TokenNameabstract) {
1598         checkAndSetModifiers(AccAbstract);
1599         getNextToken();
1600         foundToken = true;
1601       } else if (token == TokenNamefinal) {
1602         checkAndSetModifiers(AccFinal);
1603         getNextToken();
1604         foundToken = true;
1605       } else {
1606         break;
1607       }
1608     }
1609     return foundToken;
1610   }
1611   private void classProperty() {
1612     //'var' variable ';'
1613     //'var' variable '=' constant ';'
1614     do {
1615       if (token == TokenNameVariable) {
1616         getNextToken();
1617         if (token == TokenNameEQUAL) {
1618           getNextToken();
1619           constant();
1620         }
1621       } else {
1622         if (token == TokenNamethis) {
1623           throwSyntaxError("Reserved word '$this' not allowed after keyword 'var'.");
1624         }
1625         throwSyntaxError("Variable expected after keyword 'var'.");
1626       }
1627       if (token != TokenNameCOMMA) {
1628         break;
1629       }
1630       getNextToken();
1631     } while (true);
1632     if (token == TokenNameSEMICOLON) {
1633       getNextToken();
1634     } else {
1635       throwSyntaxError("';' expected after variable declaration.");
1636     }
1637   }
1638   private void functionDefinition(MethodDeclaration methodDecl) {
1639     if (astPtr == 0) {
1640       compilationUnit.types.add(methodDecl);
1641     } else {
1642       AstNode node = astStack[astPtr];
1643       if (node instanceof TypeDeclaration) {
1644         TypeDeclaration typeDecl = ((TypeDeclaration) node);
1645         if (typeDecl.methods == null) {
1646           typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
1647         } else {
1648           AbstractMethodDeclaration[] newMethods;
1649           System
1650               .arraycopy(
1651                   typeDecl.methods,
1652                   0,
1653                   newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
1654                   1, typeDecl.methods.length);
1655           newMethods[0] = methodDecl;
1656           typeDecl.methods = newMethods;
1657         }
1658       }
1659     }
1660     functionDeclarator(methodDecl);
1661     functionBody(methodDecl);
1662   }
1663   private void functionDeclarator(MethodDeclaration methodDecl) {
1664     //identifier '(' [parameter-list] ')'
1665     if (token == TokenNameAND) {
1666       getNextToken();
1667     }
1668     if (token == TokenNameIdentifier) {
1669       methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1670       methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1671       methodDecl.selector = scanner.getCurrentIdentifierSource();
1672       getNextToken();
1673       if (token == TokenNameLPAREN) {
1674         getNextToken();
1675       } else {
1676         throwSyntaxError("'(' expected in function declaration.");
1677       }
1678       if (token != TokenNameRPAREN) {
1679         parameterList();
1680       }
1681       if (token != TokenNameRPAREN) {
1682         throwSyntaxError("')' expected in function declaration.");
1683       } else {
1684         methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1685         getNextToken();
1686       }
1687     } else {
1688       if (token > TokenNameKEYWORD) {
1689         throwSyntaxError("Don't use keyword for function declaration [" + token
1690             + "].");
1691       }
1692       throwSyntaxError("Function name expected after keyword 'function'.");
1693     }
1694   }
1695   //
1696   private void parameterList() {
1697     //parameter-declaration
1698     //parameter-list ',' parameter-declaration
1699     do {
1700       parameterDeclaration();
1701       if (token != TokenNameCOMMA) {
1702         break;
1703       }
1704       getNextToken();
1705     } while (true);
1706   }
1707   private void parameterDeclaration() {
1708     //variable
1709     //variable-reference
1710     if (token == TokenNameAND) {
1711       getNextToken();
1712       if (isVariable()) {
1713         getNextToken();
1714       } else {
1715         throwSyntaxError("Variable expected after reference operator '&'.");
1716       }
1717     }
1718     //variable '=' constant
1719     if (token == TokenNameVariable) {
1720       getNextToken();
1721       if (token == TokenNameEQUAL) {
1722         getNextToken();
1723         constant();
1724       }
1725       return;
1726     }
1727     if (token == TokenNamethis) {
1728       throwSyntaxError("Reserved word '$this' not allowed in parameter declaration.");
1729     }
1730   }
1731   private void labeledStatementList() {
1732     if (token != TokenNamecase && token != TokenNamedefault) {
1733       throwSyntaxError("'case' or 'default' expected.");
1734     }
1735     do {
1736       if (token == TokenNamecase) {
1737         getNextToken();
1738         expr(); //constant();
1739         if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1740           getNextToken();
1741           if (token == TokenNamecase || token == TokenNamedefault) { // empty
1742             // case
1743             // statement
1744             // ?
1745             continue;
1746           }
1747           statementList();
1748         }
1749         //        else if (token == TokenNameSEMICOLON) {
1750         //          setMarker(
1751         //            "':' expected after 'case' keyword (Found token: " +
1752         // scanner.toStringAction(token) + ")",
1753         //            scanner.getCurrentTokenStartPosition(),
1754         //            scanner.getCurrentTokenEndPosition(),
1755         //            INFO);
1756         //          getNextToken();
1757         //          if (token == TokenNamecase) { // empty case statement ?
1758         //            continue;
1759         //          }
1760         //          statementList();
1761         //        }
1762         else {
1763           throwSyntaxError("':' character after 'case' constant expected (Found token: "
1764               + scanner.toStringAction(token) + ")");
1765         }
1766       } else { // TokenNamedefault
1767         getNextToken();
1768         if (token == TokenNameCOLON) {
1769           getNextToken();
1770           statementList();
1771         } else {
1772           throwSyntaxError("':' character after 'default' expected.");
1773         }
1774       }
1775     } while (token == TokenNamecase || token == TokenNamedefault);
1776   }
1777   //  public void labeledStatement() {
1778   //    if (token == TokenNamecase) {
1779   //      getNextToken();
1780   //      constant();
1781   //      if (token == TokenNameDDOT) {
1782   //        getNextToken();
1783   //        statement();
1784   //      } else {
1785   //        throwSyntaxError("':' character after 'case' constant expected.");
1786   //      }
1787   //      return;
1788   //    } else if (token == TokenNamedefault) {
1789   //      getNextToken();
1790   //      if (token == TokenNameDDOT) {
1791   //        getNextToken();
1792   //        statement();
1793   //      } else {
1794   //        throwSyntaxError("':' character after 'default' expected.");
1795   //      }
1796   //      return;
1797   //    }
1798   //  }
1799   //  public void expressionStatement() {
1800   //  }
1801   //  private void inclusionStatement() {
1802   //  }
1803   //  public void compoundStatement() {
1804   //  }
1805   //  public void selectionStatement() {
1806   //  }
1807   //
1808   //  public void iterationStatement() {
1809   //  }
1810   //
1811   //  public void jumpStatement() {
1812   //  }
1813   //
1814   //  public void outputStatement() {
1815   //  }
1816   //
1817   //  public void scopeStatement() {
1818   //  }
1819   //
1820   //  public void flowStatement() {
1821   //  }
1822   //
1823   //  public void definitionStatement() {
1824   //  }
1825   private void ifStatement() {
1826     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1827     if (token == TokenNameCOLON) {
1828       getNextToken();
1829       if (token != TokenNameendif) {
1830         statementList();
1831         switch (token) {
1832           case TokenNameelse :
1833             getNextToken();
1834             if (token == TokenNameCOLON) {
1835               getNextToken();
1836               if (token != TokenNameendif) {
1837                 statementList();
1838               }
1839             } else {
1840               if (token == TokenNameif) { //'else if'
1841                 getNextToken();
1842                 elseifStatementList();
1843               } else {
1844                 throwSyntaxError("':' expected after 'else'.");
1845               }
1846             }
1847             break;
1848           case TokenNameelseif :
1849             getNextToken();
1850             elseifStatementList();
1851             break;
1852         }
1853       }
1854       if (token != TokenNameendif) {
1855         throwSyntaxError("'endif' expected.");
1856       }
1857       getNextToken();
1858       if (token != TokenNameSEMICOLON) {
1859         throwSyntaxError("';' expected after if-statement.");
1860       }
1861       getNextToken();
1862     } else {
1863       // statement [else-statement]
1864       statement(TokenNameEOF);
1865       if (token == TokenNameelseif) {
1866         getNextToken();
1867         if (token == TokenNameLPAREN) {
1868           getNextToken();
1869         } else {
1870           throwSyntaxError("'(' expected after 'elseif' keyword.");
1871         }
1872         expr();
1873         if (token == TokenNameRPAREN) {
1874           getNextToken();
1875         } else {
1876           throwSyntaxError("')' expected after 'elseif' condition.");
1877         }
1878         ifStatement();
1879       } else if (token == TokenNameelse) {
1880         getNextToken();
1881         statement(TokenNameEOF);
1882       }
1883     }
1884   }
1885   private void elseifStatementList() {
1886     do {
1887       elseifStatement();
1888       switch (token) {
1889         case TokenNameelse :
1890           getNextToken();
1891           if (token == TokenNameCOLON) {
1892             getNextToken();
1893             if (token != TokenNameendif) {
1894               statementList();
1895             }
1896             return;
1897           } else {
1898             if (token == TokenNameif) { //'else if'
1899               getNextToken();
1900             } else {
1901               throwSyntaxError("':' expected after 'else'.");
1902             }
1903           }
1904           break;
1905         case TokenNameelseif :
1906           getNextToken();
1907           break;
1908         default :
1909           return;
1910       }
1911     } while (true);
1912   }
1913   private void elseifStatement() {
1914     if (token == TokenNameLPAREN) {
1915       getNextToken();
1916       expr();
1917       if (token != TokenNameRPAREN) {
1918         throwSyntaxError("')' expected in else-if-statement.");
1919       }
1920       getNextToken();
1921       if (token != TokenNameCOLON) {
1922         throwSyntaxError("':' expected in else-if-statement.");
1923       }
1924       getNextToken();
1925       if (token != TokenNameendif) {
1926         statementList();
1927       }
1928     }
1929   }
1930   private void switchStatement() {
1931     if (token == TokenNameCOLON) {
1932       // ':' [labeled-statement-list] 'endswitch' ';'
1933       getNextToken();
1934       labeledStatementList();
1935       if (token != TokenNameendswitch) {
1936         throwSyntaxError("'endswitch' expected.");
1937       }
1938       getNextToken();
1939       if (token != TokenNameSEMICOLON) {
1940         throwSyntaxError("';' expected after switch-statement.");
1941       }
1942       getNextToken();
1943     } else {
1944       // '{' [labeled-statement-list] '}'
1945       if (token != TokenNameLBRACE) {
1946         throwSyntaxError("'{' expected in switch statement.");
1947       }
1948       getNextToken();
1949       if (token != TokenNameRBRACE) {
1950         labeledStatementList();
1951       }
1952       if (token != TokenNameRBRACE) {
1953         throwSyntaxError("'}' expected in switch statement.");
1954       }
1955       getNextToken();
1956     }
1957   }
1958   private void forStatement() {
1959     if (token == TokenNameCOLON) {
1960       getNextToken();
1961       statementList();
1962       if (token != TokenNameendfor) {
1963         throwSyntaxError("'endfor' expected.");
1964       }
1965       getNextToken();
1966       if (token != TokenNameSEMICOLON) {
1967         throwSyntaxError("';' expected after for-statement.");
1968       }
1969       getNextToken();
1970     } else {
1971       statement(TokenNameEOF);
1972     }
1973   }
1974   private void whileStatement() {
1975     // ':' statement-list 'endwhile' ';'
1976     if (token == TokenNameCOLON) {
1977       getNextToken();
1978       statementList();
1979       if (token != TokenNameendwhile) {
1980         throwSyntaxError("'endwhile' expected.");
1981       }
1982       getNextToken();
1983       if (token != TokenNameSEMICOLON) {
1984         throwSyntaxError("';' expected after while-statement.");
1985       }
1986       getNextToken();
1987     } else {
1988       statement(TokenNameEOF);
1989     }
1990   }
1991   private void foreachStatement() {
1992     if (token == TokenNameCOLON) {
1993       getNextToken();
1994       statementList();
1995       if (token != TokenNameendforeach) {
1996         throwSyntaxError("'endforeach' expected.");
1997       }
1998       getNextToken();
1999       if (token != TokenNameSEMICOLON) {
2000         throwSyntaxError("';' expected after foreach-statement.");
2001       }
2002       getNextToken();
2003     } else {
2004       statement(TokenNameEOF);
2005     }
2006   }
2007   //  private void exitStatus() {
2008   //    if (token == TokenNameLPAREN) {
2009   //      getNextToken();
2010   //    } else {
2011   //      throwSyntaxError("'(' expected in 'exit-status'.");
2012   //    }
2013   //    if (token != TokenNameRPAREN) {
2014   //      expression();
2015   //    }
2016   //    if (token == TokenNameRPAREN) {
2017   //      getNextToken();
2018   //    } else {
2019   //      throwSyntaxError("')' expected after 'exit-status'.");
2020   //    }
2021   //  }
2022   private void expressionList() {
2023     do {
2024       expr();
2025       if (token == TokenNameCOMMA) {
2026         getNextToken();
2027       } else {
2028         break;
2029       }
2030     } while (true);
2031   }
2032   private void expr() {
2033     //todo: find a better way to get the expression
2034     //    expression = new StringBuffer();
2035     //    for (int i = chIndx; i < str.length(); i++) {
2036     //      if (str.charAt(i) == ';') {
2037     //        break;
2038     //      }
2039     //      expression.append(str.charAt(i));
2040     //    }
2041     //    if (token == TokenNameSTRING_CONSTANT || token ==
2042     // TokenNameINTERPOLATED_STRING) {
2043     //      getNextToken();
2044     //    } else {
2045     logicalinclusiveorExpression();
2046     //      while (token != TokenNameSEMICOLON) {
2047     //        getNextToken();
2048     //      // }
2049     //    }
2050   }
2051   private void expr_without_variable() {
2052     //  String ident;
2053     char[] ident;
2054     boolean castFlag = false;
2055     boolean arrayFlag = false;
2056     switch (token) {
2057       case TokenNameisset :
2058       case TokenNameempty :
2059       case TokenNameeval :
2060       case TokenNameinclude :
2061       case TokenNameinclude_once :
2062       case TokenNamerequire :
2063       case TokenNamerequire_once :
2064         internal_functions_in_yacc();
2065         break;
2066       case TokenNamenew :
2067         getNextToken();
2068         expr();
2069         break;
2070       case TokenNamenull :
2071         getNextToken();
2072         break;
2073       case TokenNamefalse :
2074         getNextToken();
2075         break;
2076       case TokenNametrue :
2077         getNextToken();
2078         break;
2079       case TokenNameStringConstant :
2080         getNextToken();
2081         break;
2082       case TokenNameHEREDOC :
2083       case TokenNameStringInterpolated :
2084       case TokenNameStringLiteral :
2085         getNextToken();
2086         break;
2087       case TokenNameLPAREN :
2088         getNextToken();
2089         if (token == TokenNameIdentifier) {
2090           // check if identifier is a type:
2091           //    ident = identifier;
2092           ident = scanner.getCurrentIdentifierSource();
2093           String str = new String(ident).toLowerCase();
2094           for (int i = 0; i < PHP_TYPES.length; i++) {
2095             if (PHP_TYPES[i].equals(str)) {
2096               castFlag = true;
2097               if (PHP_TYPES[i].equals("array")) {
2098                 arrayFlag = true;
2099               }
2100               break;
2101             }
2102           }
2103         }
2104         if (castFlag) {
2105           getNextToken();
2106           if (arrayFlag && token == TokenNameLPAREN) {
2107             getNextToken();
2108             if (token == TokenNameRPAREN) {
2109               getNextToken();
2110             } else {
2111               expr();
2112               if (token != TokenNameRPAREN) {
2113                 throwSyntaxError(") expected after 'array('.");
2114               }
2115             }
2116           }
2117           if (token != TokenNameRPAREN) {
2118             throwSyntaxError(") expected after cast-type '" + str + "'.");
2119           }
2120           getNextToken();
2121           expr();
2122           break;
2123         } else {
2124           expr();
2125         }
2126         if (token != TokenNameRPAREN) {
2127           throwSyntaxError(") expected in postfix-expression.");
2128         }
2129         getNextToken();
2130         break;
2131       case TokenNameDoubleLiteral :
2132         getNextToken();
2133         break;
2134       case TokenNameIntegerLiteral :
2135         getNextToken();
2136         break;
2137       case TokenNameDOLLAR_LBRACE :
2138         getNextToken();
2139         expr();
2140         if (token != TokenNameRBRACE) {
2141           throwSyntaxError("'}' expected after indirect variable token '${'.");
2142         }
2143         getNextToken();
2144         break;
2145       case TokenNameVariable :
2146       case TokenNamethis :
2147         ident = scanner.getCurrentIdentifierSource();
2148         getNextToken();
2149         if (token == TokenNameLBRACE) {
2150           getNextToken();
2151           expr();
2152           if (token != TokenNameRBRACE) {
2153             throwSyntaxError("'}' expected after variable '"
2154                 + new String(ident) + "' in variable-expression.");
2155           }
2156           getNextToken();
2157         } else if (token == TokenNameLPAREN) {
2158           getNextToken();
2159           if (token != TokenNameRPAREN) {
2160             expressionList();
2161             if (token != TokenNameRPAREN) {
2162               throwSyntaxError("')' expected after variable '"
2163                   + new String(ident) + "' in postfix-expression.");
2164             }
2165           }
2166           getNextToken();
2167         }
2168         break;
2169       case TokenNameIdentifier :
2170         ident = scanner.getCurrentIdentifierSource();
2171         getNextToken();
2172         if (token == TokenNameLPAREN) {
2173           getNextToken();
2174           if (token != TokenNameRPAREN) {
2175             expressionList();
2176             if (token != TokenNameRPAREN) {
2177               throwSyntaxError("')' expected after identifier '"
2178                   + new String(ident) + "' in postfix-expression."
2179                   + "(Found token: " + scanner.toStringAction(token) + ")");
2180             }
2181           }
2182           getNextToken();
2183         }
2184         break;
2185       case TokenNameprint :
2186         getNextToken();
2187         expr();
2188         break;
2189       case TokenNameexit :
2190         getNextToken();
2191         exit_expr();
2192         break;
2193       case TokenNamelist :
2194         getNextToken();
2195         if (token == TokenNameLPAREN) {
2196           getNextToken();
2197           if (token == TokenNameCOMMA) {
2198             getNextToken();
2199           }
2200           expressionList();
2201           if (token != TokenNameRPAREN) {
2202             throwSyntaxError("')' expected after 'list' keyword.");
2203           }
2204           getNextToken();
2205           //          if (token == TokenNameSET) {
2206           //            getNextToken();
2207           //            logicalinclusiveorExpression();
2208           //          }
2209         } else {
2210           throwSyntaxError("'(' expected after 'list' keyword.");
2211         }
2212         break;
2213     //      case TokenNameexit :
2214     //        getNextToken();
2215     //        if (token != TokenNameSEMICOLON) {
2216     //          exitStatus();
2217     //        }
2218     //        if (token == TokenNameSEMICOLON) {
2219     //          getNextToken();
2220     //        } else {
2221     //          if (token != TokenNameStopPHP) {
2222     //            throwSyntaxError("';' expected after 'exit' expression.");
2223     //          }
2224     //          getNextToken();
2225     //        }
2226     //        break;
2227     //      case TokenNamedie :
2228     //        getNextToken();
2229     //        if (token != TokenNameSEMICOLON) {
2230     //          exitStatus();
2231     //        }
2232     //        if (token == TokenNameSEMICOLON) {
2233     //          getNextToken();
2234     //        } else {
2235     //          if (token != TokenNameStopPHP) {
2236     //            throwSyntaxError("';' expected after 'die' expression.");
2237     //          }
2238     //        }
2239     //        break;
2240     //      case TokenNamearray :
2241     //        getNextToken();
2242     //        if (token == TokenNameARGOPEN) {
2243     //          getNextToken();
2244     //          if (token == TokenNameCOMMA) {
2245     //            getNextToken();
2246     //          }
2247     //          expressionList();
2248     //          if (token != TokenNameARGCLOSE) {
2249     //            throwSyntaxError("')' expected after 'list' keyword.");
2250     //          }
2251     //          getNextToken();
2252     //          if (token == TokenNameSET) {
2253     //            getNextToken();
2254     //            logicalinclusiveorExpression();
2255     //          }
2256     //        } else {
2257     //          throwSyntaxError("'(' expected after 'list' keyword.");
2258     //        }
2259     //        break;
2260     }
2261     boolean while_flag = true;
2262     do {
2263       switch (token) {
2264         case TokenNameLBRACKET :
2265           getNextToken();
2266           expr();
2267           if (token != TokenNameRBRACKET) {
2268             throwSyntaxError("] expected in postfix-expression.");
2269           }
2270           getNextToken();
2271           break;
2272         case TokenNameCOLON_COLON :
2273         // ::
2274         case TokenNameMINUS_GREATER :
2275           // ->
2276           getNextToken();
2277           if (token > TokenNameKEYWORD) {
2278             ident = scanner.getCurrentIdentifierSource();
2279             //            setMarker(
2280             //              "Avoid using keyword '"
2281             //                + new String(ident)
2282             //                + "' as variable name.",
2283             //              rowCount,
2284             //              PHPParser.INFO);
2285             //            setMarker(
2286             //              "Avoid using keyword '" + new String(ident) + "' as
2287             // variable name.",
2288             //              scanner.getCurrentTokenStartPosition(),
2289             //              scanner.getCurrentTokenEndPosition(),
2290             //              INFO);
2291           }
2292           switch (token) {
2293             case TokenNameVariable :
2294               ident = scanner.getCurrentIdentifierSource();
2295               getNextToken();
2296               //              if (token == TokenNameARGOPEN) {
2297               //                getNextToken();
2298               //                expressionList();
2299               //                if (token != TokenNameARGCLOSE) {
2300               //                  throwSyntaxError(") expected after variable '" +
2301               // ident + "'.");
2302               //                }
2303               //                getNextToken();
2304               //              }
2305               break;
2306             case TokenNameIdentifier :
2307               //ident = scanner.getCurrentIdentifierSource();
2308               getNextToken();
2309               break;
2310             case TokenNameLBRACE :
2311               getNextToken();
2312               expr();
2313               if (token != TokenNameRBRACE) {
2314                 throwSyntaxError("} expected in postfix-expression.");
2315               }
2316               getNextToken();
2317               break;
2318             default :
2319               throwSyntaxError("Syntax error after '->' token.");
2320           }
2321           while (token == TokenNameLBRACKET || token == TokenNameLPAREN
2322               || token == TokenNameLBRACE) {
2323             if (token == TokenNameLBRACKET) {
2324               getNextToken();
2325               expressionList();
2326               if (token != TokenNameRBRACKET) {
2327                 throwSyntaxError("] expected after '->'.");
2328               }
2329               getNextToken();
2330             } else if (token == TokenNameLPAREN) {
2331               getNextToken();
2332               expressionList();
2333               if (token != TokenNameRPAREN) {
2334                 throwSyntaxError(") expected after '->'.");
2335               }
2336               getNextToken();
2337             } else if (token == TokenNameLBRACE) {
2338               getNextToken();
2339               expr();
2340               if (token != TokenNameRBRACE) {
2341                 throwSyntaxError("} expected after '->'.");
2342               }
2343               getNextToken();
2344             }
2345           }
2346           break;
2347         case TokenNamePLUS_PLUS :
2348           getNextToken();
2349           break;
2350         case TokenNameMINUS_MINUS :
2351           getNextToken();
2352           break;
2353         default :
2354           while_flag = false;
2355       }
2356     } while (while_flag);
2357   }
2358   private void unaryExpression() {
2359     switch (token) {
2360       case TokenNamePLUS_PLUS :
2361         getNextToken();
2362         unaryExpression();
2363         break;
2364       case TokenNameMINUS_MINUS :
2365         getNextToken();
2366         unaryExpression();
2367         break;
2368       // '@' '&' '*' '+' '-' '~' '!'
2369       case TokenNameAT :
2370         getNextToken();
2371         if (token == TokenNameinclude || token == TokenNameinclude_once
2372             || token == TokenNamerequire || token == TokenNamerequire_once) {
2373           statement(TokenNameAT);
2374         } else {
2375           expr_without_variable(); //  castExpression();
2376         }
2377         break;
2378       case TokenNameAND :
2379         getNextToken();
2380         castExpression();
2381         break;
2382       case TokenNameMULTIPLY :
2383         getNextToken();
2384         castExpression();
2385         break;
2386       case TokenNamePLUS :
2387         getNextToken();
2388         castExpression();
2389         break;
2390       case TokenNameMINUS :
2391         getNextToken();
2392         castExpression();
2393         break;
2394       case TokenNameTWIDDLE :
2395         getNextToken();
2396         castExpression();
2397         break;
2398       case TokenNameNOT :
2399         getNextToken();
2400         castExpression();
2401         break;
2402       default :
2403         expr_without_variable();
2404     }
2405   }
2406   private void castExpression() {
2407     //    if (token == TokenNameARGOPEN) {
2408     //      getNextToken();
2409     //      typeName();
2410     //      if (token != TokenNameARGCLOSE) {
2411     //        throwSyntaxError(") expected after cast-expression.");
2412     //      }
2413     //      getNextToken();
2414     //    }
2415     unaryExpression();
2416   }
2417   private void assignExpression() {
2418     castExpression();
2419     if (token == TokenNameEQUAL) { // =
2420       getNextToken();
2421       logicalinclusiveorExpression();
2422     } else if (token == TokenNameDOT_EQUAL) { // .=
2423       getNextToken();
2424       logicalinclusiveorExpression();
2425     } else if (token == TokenNameEQUAL_GREATER) { // =>
2426       getNextToken();
2427       logicalinclusiveorExpression();
2428     } else if (token == TokenNamePLUS_EQUAL) { // +=
2429       getNextToken();
2430       logicalinclusiveorExpression();
2431     } else if (token == TokenNameMINUS_EQUAL) { // -=
2432       getNextToken();
2433       logicalinclusiveorExpression();
2434     } else if (token == TokenNameMULTIPLY_EQUAL) { // *=
2435       getNextToken();
2436       logicalinclusiveorExpression();
2437     } else if (token == TokenNameDIVIDE_EQUAL) { // *=
2438       getNextToken();
2439       logicalinclusiveorExpression();
2440     } else if (token == TokenNameREMAINDER_EQUAL) { // %=
2441       getNextToken();
2442       logicalinclusiveorExpression();
2443     } else if (token == TokenNameAND_EQUAL) { // &=
2444       getNextToken();
2445       logicalinclusiveorExpression();
2446     } else if (token == TokenNameOR_EQUAL) { // |=
2447       getNextToken();
2448       logicalinclusiveorExpression();
2449     } else if (token == TokenNameXOR_EQUAL) { // ^=
2450       getNextToken();
2451       logicalinclusiveorExpression();
2452     } else if (token == TokenNameLEFT_SHIFT_EQUAL) { // <<=
2453       getNextToken();
2454       logicalinclusiveorExpression();
2455     } else if (token == TokenNameRIGHT_SHIFT_EQUAL) { // >>=
2456       getNextToken();
2457       logicalinclusiveorExpression();
2458     } else if (token == TokenNameTWIDDLE_EQUAL) { // ~=
2459       getNextToken();
2460       logicalinclusiveorExpression();
2461     }
2462   }
2463   private void multiplicativeExpression() {
2464     do {
2465       assignExpression();
2466       if (token != TokenNameMULTIPLY && token != TokenNameDIVIDE
2467           && token != TokenNameREMAINDER) {
2468         return;
2469       }
2470       getNextToken();
2471     } while (true);
2472   }
2473   private void concatenationExpression() {
2474     do {
2475       multiplicativeExpression();
2476       if (token != TokenNameDOT) {
2477         return;
2478       }
2479       getNextToken();
2480     } while (true);
2481   }
2482   private void additiveExpression() {
2483     do {
2484       concatenationExpression();
2485       if (token != TokenNamePLUS && token != TokenNameMINUS) {
2486         return;
2487       }
2488       getNextToken();
2489     } while (true);
2490   }
2491   private void shiftExpression() {
2492     do {
2493       additiveExpression();
2494       if (token != TokenNameLEFT_SHIFT && token != TokenNameRIGHT_SHIFT) {
2495         return;
2496       }
2497       getNextToken();
2498     } while (true);
2499   }
2500   private void relationalExpression() {
2501     do {
2502       shiftExpression();
2503       if (token != TokenNameLESS && token != TokenNameGREATER
2504           && token != TokenNameLESS_EQUAL && token != TokenNameGREATER_EQUAL) {
2505         return;
2506       }
2507       getNextToken();
2508     } while (true);
2509   }
2510   private void identicalExpression() {
2511     do {
2512       relationalExpression();
2513       if (token != TokenNameEQUAL_EQUAL_EQUAL
2514           && token != TokenNameNOT_EQUAL_EQUAL) {
2515         return;
2516       }
2517       getNextToken();
2518     } while (true);
2519   }
2520   private void equalityExpression() {
2521     do {
2522       identicalExpression();
2523       if (token != TokenNameEQUAL_EQUAL && token != TokenNameNOT_EQUAL) {
2524         return;
2525       }
2526       getNextToken();
2527     } while (true);
2528   }
2529   private void ternaryExpression() {
2530     equalityExpression();
2531     if (token == TokenNameQUESTION) {
2532       getNextToken();
2533       expr();
2534       if (token == TokenNameCOLON) {
2535         getNextToken();
2536         expr();
2537       } else {
2538         throwSyntaxError("':' expected in ternary operator '? :'.");
2539       }
2540     }
2541   }
2542   private void andExpression() {
2543     do {
2544       ternaryExpression();
2545       if (token != TokenNameAND) {
2546         return;
2547       }
2548       getNextToken();
2549     } while (true);
2550   }
2551   private void exclusiveorExpression() {
2552     do {
2553       andExpression();
2554       if (token != TokenNameXOR) {
2555         return;
2556       }
2557       getNextToken();
2558     } while (true);
2559   }
2560   private void inclusiveorExpression() {
2561     do {
2562       exclusiveorExpression();
2563       if (token != TokenNameOR) {
2564         return;
2565       }
2566       getNextToken();
2567     } while (true);
2568   }
2569   private void booleanandExpression() {
2570     do {
2571       inclusiveorExpression();
2572       if (token != TokenNameAND_AND) {
2573         return;
2574       }
2575       getNextToken();
2576     } while (true);
2577   }
2578   private void booleanorExpression() {
2579     do {
2580       booleanandExpression();
2581       if (token != TokenNameOR_OR) {
2582         return;
2583       }
2584       getNextToken();
2585     } while (true);
2586   }
2587   private void logicalandExpression() {
2588     do {
2589       booleanorExpression();
2590       if (token != TokenNameAND) {
2591         return;
2592       }
2593       getNextToken();
2594     } while (true);
2595   }
2596   private void logicalexclusiveorExpression() {
2597     do {
2598       logicalandExpression();
2599       if (token != TokenNameXOR) {
2600         return;
2601       }
2602       getNextToken();
2603     } while (true);
2604   }
2605   private void logicalinclusiveorExpression() {
2606     do {
2607       logicalexclusiveorExpression();
2608       if (token != TokenNameOR) {
2609         return;
2610       }
2611       getNextToken();
2612     } while (true);
2613   }
2614   //  public void assignmentExpression() {
2615   //    if (token == TokenNameVARIABLE) {
2616   //      getNextToken();
2617   //      if (token == TokenNameSET) {
2618   //        getNextToken();
2619   //        logicalinclusiveorExpression();
2620   //      }
2621   //    } else {
2622   //      logicalinclusiveorExpression();
2623   //    }
2624   //  }
2625   private void variableList() {
2626     do {
2627       variable();
2628       if (token == TokenNameCOMMA) {
2629         getNextToken();
2630       } else {
2631         break;
2632       }
2633     } while (true);
2634   }
2635   private void variable() {
2636     if (token == TokenNameDOLLAR_LBRACE) {
2637       getNextToken();
2638       expr();
2639       ;
2640       if (token != TokenNameRBRACE) {
2641         throwSyntaxError("'}' expected after indirect variable token '${'.");
2642       }
2643       getNextToken();
2644     } else {
2645       if (token == TokenNameVariable) {
2646         getNextToken();
2647         if (token == TokenNameLBRACKET) {
2648           getNextToken();
2649           expr();
2650           if (token != TokenNameRBRACKET) {
2651             throwSyntaxError("']' expected in variable-list.");
2652           }
2653           getNextToken();
2654         } else if (token == TokenNameEQUAL) {
2655           getNextToken();
2656           constant();
2657         }
2658       } else {
2659         throwSyntaxError("$-variable expected in variable-list.");
2660       }
2661     }
2662   }
2663   private void exit_expr() {
2664     //  /* empty */
2665     //  | '(' ')'
2666     //  | '(' expr ')'
2667     if (token != TokenNameLPAREN) {
2668       return;
2669     }
2670     getNextToken();
2671     if (token == TokenNameRPAREN) {
2672       getNextToken();
2673       return;
2674     }
2675     expr();
2676     if (token != TokenNameRPAREN) {
2677       throwSyntaxError("')' expected after keyword 'exit'");
2678     }
2679     getNextToken();
2680   }
2681   private void internal_functions_in_yacc() {
2682     switch (token) {
2683       case TokenNameisset :
2684         //      T_ISSET '(' isset_variables ')'
2685         getNextToken();
2686         if (token != TokenNameLPAREN) {
2687           throwSyntaxError("'(' expected after keyword 'isset'");
2688         }
2689         getNextToken();
2690         isset_variables();
2691         if (token != TokenNameRPAREN) {
2692           throwSyntaxError("')' expected after keyword 'isset'");
2693         }
2694         getNextToken();
2695         break;
2696       case TokenNameempty :
2697         //      T_EMPTY '(' variable ')'
2698         getNextToken();
2699         if (token != TokenNameLPAREN) {
2700           throwSyntaxError("'(' expected after keyword 'empty'");
2701         }
2702         getNextToken();
2703         variable();
2704         if (token != TokenNameRPAREN) {
2705           throwSyntaxError("')' expected after keyword 'empty'");
2706         }
2707         getNextToken();
2708         break;
2709       case TokenNameinclude :
2710         //T_INCLUDE expr
2711         getNextToken();
2712         expr();
2713         break;
2714       case TokenNameinclude_once :
2715         //      T_INCLUDE_ONCE expr
2716         getNextToken();
2717         expr();
2718         break;
2719       case TokenNameeval :
2720         //      T_EVAL '(' expr ')'
2721         getNextToken();
2722         if (token != TokenNameLPAREN) {
2723           throwSyntaxError("'(' expected after keyword 'eval'");
2724         }
2725         getNextToken();
2726         expr();
2727         if (token != TokenNameRPAREN) {
2728           throwSyntaxError("')' expected after keyword 'eval'");
2729         }
2730         getNextToken();
2731         break;
2732       case TokenNamerequire :
2733         //T_REQUIRE expr
2734         getNextToken();
2735         expr();
2736         break;
2737       case TokenNamerequire_once :
2738         //      T_REQUIRE_ONCE expr
2739         getNextToken();
2740         expr();
2741         break;
2742     }
2743   }
2744   private void isset_variables() {
2745     //  variable
2746     //  | isset_variables ','
2747     if (token == TokenNameRPAREN) {
2748       throwSyntaxError("Variable expected after keyword 'isset'");
2749     }
2750     while (true) {
2751       variable();
2752       if (token == TokenNameCOMMA) {
2753         getNextToken();
2754       } else {
2755         break;
2756       }
2757     }
2758   }
2759   /**
2760    * It will look for a value (after a '=' for example) @
2761    */
2762   private void constant() {
2763     //   String ident;
2764     switch (token) {
2765       case TokenNamePLUS :
2766         getNextToken();
2767         switch (token) {
2768           case TokenNameDoubleLiteral :
2769             getNextToken();
2770             break;
2771           case TokenNameIntegerLiteral :
2772             getNextToken();
2773             break;
2774           default :
2775             throwSyntaxError("Constant expected after '+' presign.");
2776         }
2777         break;
2778       case TokenNameMINUS :
2779         getNextToken();
2780         switch (token) {
2781           case TokenNameDoubleLiteral :
2782             getNextToken();
2783             break;
2784           case TokenNameIntegerLiteral :
2785             getNextToken();
2786             break;
2787           default :
2788             throwSyntaxError("Constant expected after '-' presign.");
2789         }
2790         break;
2791       case TokenNamenull :
2792         getNextToken();
2793         break;
2794       case TokenNamefalse :
2795         getNextToken();
2796         break;
2797       case TokenNametrue :
2798         getNextToken();
2799         break;
2800       case TokenNameIdentifier :
2801         //   ident = identifier;
2802         char[] ident = scanner.getCurrentIdentifierSource();
2803         getNextToken();
2804         if (token == TokenNameLPAREN) {
2805           getNextToken();
2806           if (token != TokenNameRPAREN) {
2807             expressionList();
2808             if (token != TokenNameRPAREN) {
2809               throwSyntaxError("')' expected after identifier '"
2810                   + new String(ident) + "' in postfix-expression.");
2811             }
2812           }
2813           getNextToken();
2814         }
2815         break;
2816       case TokenNameStringLiteral :
2817         getNextToken();
2818         break;
2819       case TokenNameStringConstant :
2820         getNextToken();
2821         break;
2822       case TokenNameStringInterpolated :
2823         getNextToken();
2824         break;
2825       case TokenNameDoubleLiteral :
2826         getNextToken();
2827         break;
2828       case TokenNameIntegerLiteral :
2829         getNextToken();
2830         break;
2831       default :
2832         throwSyntaxError("Constant expected.");
2833     }
2834   }
2835   public void reportSyntaxError() { //int act, int currentKind, int
2836     // stateStackTop) {
2837     /* remember current scanner position */
2838     int startPos = scanner.startPosition;
2839     int currentPos = scanner.currentPosition;
2840     //          String[] expectings;
2841     //          String tokenName = name[symbol_index[currentKind]];
2842     //fetch all "accurate" possible terminals that could recover the error
2843     //          int start, end = start = asi(stack[stateStackTop]);
2844     //          while (asr[end] != 0)
2845     //                  end++;
2846     //          int length = end - start;
2847     //          expectings = new String[length];
2848     //          if (length != 0) {
2849     //                  char[] indexes = new char[length];
2850     //                  System.arraycopy(asr, start, indexes, 0, length);
2851     //                  for (int i = 0; i < length; i++) {
2852     //                          expectings[i] = name[symbol_index[indexes[i]]];
2853     //                  }
2854     //          }
2855     //if the pb is an EOF, try to tell the user that they are some
2856     //          if (tokenName.equals(UNEXPECTED_EOF)) {
2857     //                  if (!this.checkAndReportBracketAnomalies(problemReporter())) {
2858     //                          char[] tokenSource;
2859     //                          try {
2860     //                                  tokenSource = this.scanner.getCurrentTokenSource();
2861     //                          } catch (Exception e) {
2862     //                                  tokenSource = new char[] {};
2863     //                          }
2864     //                          problemReporter().parseError(
2865     //                                  this.scanner.startPosition,
2866     //                                  this.scanner.currentPosition - 1,
2867     //                                  tokenSource,
2868     //                                  tokenName,
2869     //                                  expectings);
2870     //                  }
2871     //          } else { //the next test is HEAVILY grammar DEPENDENT.
2872     //                  if ((length == 14)
2873     //                          && (expectings[0] == "=") //$NON-NLS-1$
2874     //                          && (expectings[1] == "*=") //$NON-NLS-1$
2875     //                          && (expressionPtr > -1)) {
2876     //                                  switch(currentKind) {
2877     //                                          case TokenNameSEMICOLON:
2878     //                                          case TokenNamePLUS:
2879     //                                          case TokenNameMINUS:
2880     //                                          case TokenNameDIVIDE:
2881     //                                          case TokenNameREMAINDER:
2882     //                                          case TokenNameMULTIPLY:
2883     //                                          case TokenNameLEFT_SHIFT:
2884     //                                          case TokenNameRIGHT_SHIFT:
2885     //// case TokenNameUNSIGNED_RIGHT_SHIFT:
2886     //                                          case TokenNameLESS:
2887     //                                          case TokenNameGREATER:
2888     //                                          case TokenNameLESS_EQUAL:
2889     //                                          case TokenNameGREATER_EQUAL:
2890     //                                          case TokenNameEQUAL_EQUAL:
2891     //                                          case TokenNameNOT_EQUAL:
2892     //                                          case TokenNameXOR:
2893     //                                          case TokenNameAND:
2894     //                                          case TokenNameOR:
2895     //                                          case TokenNameOR_OR:
2896     //                                          case TokenNameAND_AND:
2897     //                                                  // the ; is not the expected token ==> it ends a statement when an
2898     // expression is not ended
2899     //                                                  problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
2900     //                                                  break;
2901     //                                          case TokenNameRBRACE :
2902     //                                                  problemReporter().missingSemiColon(expressionStack[expressionPtr]);
2903     //                                                  break;
2904     //                                          default:
2905     //                                                  char[] tokenSource;
2906     //                                                  try {
2907     //                                                          tokenSource = this.scanner.getCurrentTokenSource();
2908     //                                                  } catch (Exception e) {
2909     //                                                          tokenSource = new char[] {};
2910     //                                                  }
2911     //                                                  problemReporter().parseError(
2912     //                                                          this.scanner.startPosition,
2913     //                                                          this.scanner.currentPosition - 1,
2914     //                                                          tokenSource,
2915     //                                                          tokenName,
2916     //                                                          expectings);
2917     //                                                  this.checkAndReportBracketAnomalies(problemReporter());
2918     //                                  }
2919     //                  } else {
2920     char[] tokenSource;
2921     try {
2922       tokenSource = this.scanner.getCurrentTokenSource();
2923     } catch (Exception e) {
2924       tokenSource = new char[]{};
2925     }
2926     //                          problemReporter().parseError(
2927     //                                  this.scanner.startPosition,
2928     //                                  this.scanner.currentPosition - 1,
2929     //                                  tokenSource,
2930     //                                  tokenName,
2931     //                                  expectings);
2932     this.checkAndReportBracketAnomalies(problemReporter());
2933     //                  }
2934     //          }
2935     /* reset scanner where it was */
2936     scanner.startPosition = startPos;
2937     scanner.currentPosition = currentPos;
2938   }
2939   public static final int RoundBracket = 0;
2940   public static final int SquareBracket = 1;
2941   public static final int CurlyBracket = 2;
2942   public static final int BracketKinds = 3;
2943   protected int[] nestedMethod; //the ptr is nestedType
2944   protected int nestedType, dimensions;
2945   //ast stack
2946   final static int AstStackIncrement = 100;
2947   protected int astPtr;
2948   protected AstNode[] astStack = new AstNode[AstStackIncrement];
2949   protected int astLengthPtr;
2950   protected int[] astLengthStack;
2951   AstNode[] noAstNodes = new AstNode[AstStackIncrement];
2952   public CompilationUnitDeclaration compilationUnit; /*
2953                                                       * the result from parse()
2954                                                       */
2955   protected ReferenceContext referenceContext;
2956   protected ProblemReporter problemReporter;
2957   //  protected CompilationResult compilationResult;
2958   /**
2959    * Returns this parser's problem reporter initialized with its reference
2960    * context. Also it is assumed that a problem is going to be reported, so
2961    * initializes the compilation result's line positions.
2962    */
2963   public ProblemReporter problemReporter() {
2964     if (scanner.recordLineSeparator) {
2965       compilationUnit.compilationResult.lineSeparatorPositions = scanner
2966           .getLineEnds();
2967     }
2968     problemReporter.referenceContext = referenceContext;
2969     return problemReporter;
2970   }
2971   /*
2972    * Reconsider the entire source looking for inconsistencies in {} () []
2973    */
2974   public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
2975     scanner.wasAcr = false;
2976     boolean anomaliesDetected = false;
2977     try {
2978       char[] source = scanner.source;
2979       int[] leftCount = {0, 0, 0};
2980       int[] rightCount = {0, 0, 0};
2981       int[] depths = {0, 0, 0};
2982       int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
2983       int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
2984       int[][] rightPositions = new int[][]{new int[10], new int[10],
2985           new int[10]};
2986       int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
2987       scanner.currentPosition = scanner.initialPosition; //starting
2988       // point
2989       // (first-zero-based
2990       // char)
2991       while (scanner.currentPosition < scanner.eofPosition) { //loop for
2992         // jumping
2993         // over
2994         // comments
2995         try {
2996           // ---------Consume white space and handles
2997           // startPosition---------
2998           boolean isWhiteSpace;
2999           do {
3000             scanner.startPosition = scanner.currentPosition;
3001             //                                          if (((scanner.currentCharacter =
3002             // source[scanner.currentPosition++]) == '\\') &&
3003             // (source[scanner.currentPosition] == 'u')) {
3004             //                                                  isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3005             //                                          } else {
3006             if (scanner.recordLineSeparator
3007                 && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3008               if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3009                 // only record line positions we have not
3010                 // recorded yet
3011                 scanner.pushLineSeparator();
3012               }
3013             }
3014             isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3015             //                                          }
3016           } while (isWhiteSpace
3017               && (scanner.currentPosition < scanner.eofPosition));
3018           // -------consume token until } is found---------
3019           switch (scanner.currentCharacter) {
3020             case '{' :
3021               {
3022                 int index = leftCount[CurlyBracket]++;
3023                 if (index == leftPositions[CurlyBracket].length) {
3024                   System.arraycopy(leftPositions[CurlyBracket], 0,
3025                       (leftPositions[CurlyBracket] = new int[index * 2]), 0,
3026                       index);
3027                   System
3028                       .arraycopy(leftDepths[CurlyBracket], 0,
3029                           (leftDepths[CurlyBracket] = new int[index * 2]), 0,
3030                           index);
3031                 }
3032                 leftPositions[CurlyBracket][index] = scanner.startPosition;
3033                 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3034               }
3035               break;
3036             case '}' :
3037               {
3038                 int index = rightCount[CurlyBracket]++;
3039                 if (index == rightPositions[CurlyBracket].length) {
3040                   System.arraycopy(rightPositions[CurlyBracket], 0,
3041                       (rightPositions[CurlyBracket] = new int[index * 2]), 0,
3042                       index);
3043                   System.arraycopy(rightDepths[CurlyBracket], 0,
3044                       (rightDepths[CurlyBracket] = new int[index * 2]), 0,
3045                       index);
3046                 }
3047                 rightPositions[CurlyBracket][index] = scanner.startPosition;
3048                 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3049               }
3050               break;
3051             case '(' :
3052               {
3053                 int index = leftCount[RoundBracket]++;
3054                 if (index == leftPositions[RoundBracket].length) {
3055                   System.arraycopy(leftPositions[RoundBracket], 0,
3056                       (leftPositions[RoundBracket] = new int[index * 2]), 0,
3057                       index);
3058                   System
3059                       .arraycopy(leftDepths[RoundBracket], 0,
3060                           (leftDepths[RoundBracket] = new int[index * 2]), 0,
3061                           index);
3062                 }
3063                 leftPositions[RoundBracket][index] = scanner.startPosition;
3064                 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3065               }
3066               break;
3067             case ')' :
3068               {
3069                 int index = rightCount[RoundBracket]++;
3070                 if (index == rightPositions[RoundBracket].length) {
3071                   System.arraycopy(rightPositions[RoundBracket], 0,
3072                       (rightPositions[RoundBracket] = new int[index * 2]), 0,
3073                       index);
3074                   System.arraycopy(rightDepths[RoundBracket], 0,
3075                       (rightDepths[RoundBracket] = new int[index * 2]), 0,
3076                       index);
3077                 }
3078                 rightPositions[RoundBracket][index] = scanner.startPosition;
3079                 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3080               }
3081               break;
3082             case '[' :
3083               {
3084                 int index = leftCount[SquareBracket]++;
3085                 if (index == leftPositions[SquareBracket].length) {
3086                   System.arraycopy(leftPositions[SquareBracket], 0,
3087                       (leftPositions[SquareBracket] = new int[index * 2]), 0,
3088                       index);
3089                   System.arraycopy(leftDepths[SquareBracket], 0,
3090                       (leftDepths[SquareBracket] = new int[index * 2]), 0,
3091                       index);
3092                 }
3093                 leftPositions[SquareBracket][index] = scanner.startPosition;
3094                 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3095               }
3096               break;
3097             case ']' :
3098               {
3099                 int index = rightCount[SquareBracket]++;
3100                 if (index == rightPositions[SquareBracket].length) {
3101                   System.arraycopy(rightPositions[SquareBracket], 0,
3102                       (rightPositions[SquareBracket] = new int[index * 2]), 0,
3103                       index);
3104                   System.arraycopy(rightDepths[SquareBracket], 0,
3105                       (rightDepths[SquareBracket] = new int[index * 2]), 0,
3106                       index);
3107                 }
3108                 rightPositions[SquareBracket][index] = scanner.startPosition;
3109                 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3110               }
3111               break;
3112             case '\'' :
3113               {
3114                 if (scanner.getNextChar('\\')) {
3115                   scanner.scanEscapeCharacter();
3116                 } else { // consume next character
3117                   scanner.unicodeAsBackSlash = false;
3118                   //                                                                    if (((scanner.currentCharacter =
3119                   // source[scanner.currentPosition++]) ==
3120                   // '\\') &&
3121                   // (source[scanner.currentPosition] ==
3122                   // 'u')) {
3123                   //                                                                            scanner.getNextUnicodeChar();
3124                   //                                                                    } else {
3125                   if (scanner.withoutUnicodePtr != 0) {
3126                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3127                   }
3128                   //                                                                    }
3129                 }
3130                 scanner.getNextChar('\'');
3131                 break;
3132               }
3133             case '"' :
3134               // consume next character
3135               scanner.unicodeAsBackSlash = false;
3136               //                                                        if (((scanner.currentCharacter =
3137               // source[scanner.currentPosition++]) == '\\') &&
3138               // (source[scanner.currentPosition] == 'u')) {
3139               //                                                                scanner.getNextUnicodeChar();
3140               //                                                        } else {
3141               if (scanner.withoutUnicodePtr != 0) {
3142                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3143               }
3144               //                                                        }
3145               while (scanner.currentCharacter != '"') {
3146                 if (scanner.currentCharacter == '\r') {
3147                   if (source[scanner.currentPosition] == '\n')
3148                     scanner.currentPosition++;
3149                   break; // the string cannot go further that
3150                   // the line
3151                 }
3152                 if (scanner.currentCharacter == '\n') {
3153                   break; // the string cannot go further that
3154                   // the line
3155                 }
3156                 if (scanner.currentCharacter == '\\') {
3157                   scanner.scanEscapeCharacter();
3158                 }
3159                 // consume next character
3160                 scanner.unicodeAsBackSlash = false;
3161                 //                                                              if (((scanner.currentCharacter =
3162                 // source[scanner.currentPosition++]) == '\\')
3163                 // && (source[scanner.currentPosition] == 'u'))
3164                 // {
3165                 //                                                                      scanner.getNextUnicodeChar();
3166                 //                                                              } else {
3167                 if (scanner.withoutUnicodePtr != 0) {
3168                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3169                 }
3170                 //                                                              }
3171               }
3172               break;
3173             case '/' :
3174               {
3175                 int test;
3176                 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3177                   // comment
3178                   //get the next char
3179                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3180                       && (source[scanner.currentPosition] == 'u')) {
3181                     //-------------unicode traitement
3182                     // ------------
3183                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3184                     scanner.currentPosition++;
3185                     while (source[scanner.currentPosition] == 'u') {
3186                       scanner.currentPosition++;
3187                     }
3188                     if ((c1 = Character
3189                         .getNumericValue(source[scanner.currentPosition++])) > 15
3190                         || c1 < 0
3191                         || (c2 = Character
3192                             .getNumericValue(source[scanner.currentPosition++])) > 15
3193                         || c2 < 0
3194                         || (c3 = Character
3195                             .getNumericValue(source[scanner.currentPosition++])) > 15
3196                         || c3 < 0
3197                         || (c4 = Character
3198                             .getNumericValue(source[scanner.currentPosition++])) > 15
3199                         || c4 < 0) { //error don't
3200                       // care of the
3201                       // value
3202                       scanner.currentCharacter = 'A';
3203                     } //something different from \n and \r
3204                     else {
3205                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3206                     }
3207                   }
3208                   while (scanner.currentCharacter != '\r'
3209                       && scanner.currentCharacter != '\n') {
3210                     //get the next char
3211                     scanner.startPosition = scanner.currentPosition;
3212                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3213                         && (source[scanner.currentPosition] == 'u')) {
3214                       //-------------unicode traitement
3215                       // ------------
3216                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3217                       scanner.currentPosition++;
3218                       while (source[scanner.currentPosition] == 'u') {
3219                         scanner.currentPosition++;
3220                       }
3221                       if ((c1 = Character
3222                           .getNumericValue(source[scanner.currentPosition++])) > 15
3223                           || c1 < 0
3224                           || (c2 = Character
3225                               .getNumericValue(source[scanner.currentPosition++])) > 15
3226                           || c2 < 0
3227                           || (c3 = Character
3228                               .getNumericValue(source[scanner.currentPosition++])) > 15
3229                           || c3 < 0
3230                           || (c4 = Character
3231                               .getNumericValue(source[scanner.currentPosition++])) > 15
3232                           || c4 < 0) { //error don't
3233                         // care of the
3234                         // value
3235                         scanner.currentCharacter = 'A';
3236                       } //something different from \n
3237                       // and \r
3238                       else {
3239                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3240                       }
3241                     }
3242                   }
3243                   if (scanner.recordLineSeparator
3244                       && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3245                     if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3246                       // only record line positions we
3247                       // have not recorded yet
3248                       scanner.pushLineSeparator();
3249                       if (this.scanner.taskTags != null) {
3250                         this.scanner.checkTaskTag(this.scanner
3251                             .getCurrentTokenStartPosition(), this.scanner
3252                             .getCurrentTokenEndPosition());
3253                       }
3254                     }
3255                   }
3256                   break;
3257                 }
3258                 if (test > 0) { //traditional and annotation
3259                   // comment
3260                   boolean star = false;
3261                   // consume next character
3262                   scanner.unicodeAsBackSlash = false;
3263                   //                                                                    if (((scanner.currentCharacter =
3264                   // source[scanner.currentPosition++]) ==
3265                   // '\\') &&
3266                   // (source[scanner.currentPosition] ==
3267                   // 'u')) {
3268                   //                                                                            scanner.getNextUnicodeChar();
3269                   //                                                                    } else {
3270                   if (scanner.withoutUnicodePtr != 0) {
3271                     scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3272                   }
3273                   //                                                                    }
3274                   if (scanner.currentCharacter == '*') {
3275                     star = true;
3276                   }
3277                   //get the next char
3278                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3279                       && (source[scanner.currentPosition] == 'u')) {
3280                     //-------------unicode traitement
3281                     // ------------
3282                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3283                     scanner.currentPosition++;
3284                     while (source[scanner.currentPosition] == 'u') {
3285                       scanner.currentPosition++;
3286                     }
3287                     if ((c1 = Character
3288                         .getNumericValue(source[scanner.currentPosition++])) > 15
3289                         || c1 < 0
3290                         || (c2 = Character
3291                             .getNumericValue(source[scanner.currentPosition++])) > 15
3292                         || c2 < 0
3293                         || (c3 = Character
3294                             .getNumericValue(source[scanner.currentPosition++])) > 15
3295                         || c3 < 0
3296                         || (c4 = Character
3297                             .getNumericValue(source[scanner.currentPosition++])) > 15
3298                         || c4 < 0) { //error don't
3299                       // care of the
3300                       // value
3301                       scanner.currentCharacter = 'A';
3302                     } //something different from * and /
3303                     else {
3304                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3305                     }
3306                   }
3307                   //loop until end of comment */
3308                   while ((scanner.currentCharacter != '/') || (!star)) {
3309                     star = scanner.currentCharacter == '*';
3310                     //get next char
3311                     if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3312                         && (source[scanner.currentPosition] == 'u')) {
3313                       //-------------unicode traitement
3314                       // ------------
3315                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3316                       scanner.currentPosition++;
3317                       while (source[scanner.currentPosition] == 'u') {
3318                         scanner.currentPosition++;
3319                       }
3320                       if ((c1 = Character
3321                           .getNumericValue(source[scanner.currentPosition++])) > 15
3322                           || c1 < 0
3323                           || (c2 = Character
3324                               .getNumericValue(source[scanner.currentPosition++])) > 15
3325                           || c2 < 0
3326                           || (c3 = Character
3327                               .getNumericValue(source[scanner.currentPosition++])) > 15
3328                           || c3 < 0
3329                           || (c4 = Character
3330                               .getNumericValue(source[scanner.currentPosition++])) > 15
3331                           || c4 < 0) { //error don't
3332                         // care of the
3333                         // value
3334                         scanner.currentCharacter = 'A';
3335                       } //something different from * and
3336                       // /
3337                       else {
3338                         scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3339                       }
3340                     }
3341                   }
3342                   if (this.scanner.taskTags != null) {
3343                     this.scanner.checkTaskTag(this.scanner
3344                         .getCurrentTokenStartPosition(), this.scanner
3345                         .getCurrentTokenEndPosition());
3346                   }
3347                   break;
3348                 }
3349                 break;
3350               }
3351             default :
3352               if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3353                 scanner.scanIdentifierOrKeyword(false);
3354                 break;
3355               }
3356               if (Character.isDigit(scanner.currentCharacter)) {
3357                 scanner.scanNumber(false);
3358                 break;
3359               }
3360           }
3361           //-----------------end switch while
3362           // try--------------------
3363         } catch (IndexOutOfBoundsException e) {
3364           break; // read until EOF
3365         } catch (InvalidInputException e) {
3366           return false; // no clue
3367         }
3368       }
3369       if (scanner.recordLineSeparator) {
3370         //                              compilationUnit.compilationResult.lineSeparatorPositions =
3371         // scanner.getLineEnds();
3372       }
3373       // check placement anomalies against other kinds of brackets
3374       for (int kind = 0; kind < BracketKinds; kind++) {
3375         for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3376           int start = leftPositions[kind][leftIndex]; // deepest
3377           // first
3378           // find matching closing bracket
3379           int depth = leftDepths[kind][leftIndex];
3380           int end = -1;
3381           for (int i = 0; i < rightCount[kind]; i++) {
3382             int pos = rightPositions[kind][i];
3383             // want matching bracket further in source with same
3384             // depth
3385             if ((pos > start) && (depth == rightDepths[kind][i])) {
3386               end = pos;
3387               break;
3388             }
3389           }
3390           if (end < 0) { // did not find a good closing match
3391             problemReporter.unmatchedBracket(start, referenceContext,
3392                 compilationUnit.compilationResult);
3393             return true;
3394           }
3395           // check if even number of opening/closing other brackets
3396           // in between this pair of brackets
3397           int balance = 0;
3398           for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3399             for (int i = 0; i < leftCount[otherKind]; i++) {
3400               int pos = leftPositions[otherKind][i];
3401               if ((pos > start) && (pos < end))
3402                 balance++;
3403             }
3404             for (int i = 0; i < rightCount[otherKind]; i++) {
3405               int pos = rightPositions[otherKind][i];
3406               if ((pos > start) && (pos < end))
3407                 balance--;
3408             }
3409             if (balance != 0) {
3410               problemReporter.unmatchedBracket(start, referenceContext,
3411                   compilationUnit.compilationResult); //bracket
3412               // anomaly
3413               return true;
3414             }
3415           }
3416         }
3417         // too many opening brackets ?
3418         for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3419           anomaliesDetected = true;
3420           problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind]
3421               - i - 1], referenceContext, compilationUnit.compilationResult);
3422         }
3423         // too many closing brackets ?
3424         for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3425           anomaliesDetected = true;
3426           problemReporter.unmatchedBracket(rightPositions[kind][i],
3427               referenceContext, compilationUnit.compilationResult);
3428         }
3429         if (anomaliesDetected)
3430           return true;
3431       }
3432       return anomaliesDetected;
3433     } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3434       return anomaliesDetected;
3435     } catch (NullPointerException e) { // jdk1.2.2 jit bug
3436       return anomaliesDetected;
3437     }
3438   }
3439   protected void pushOnAstLengthStack(int pos) {
3440     try {
3441       astLengthStack[++astLengthPtr] = pos;
3442     } catch (IndexOutOfBoundsException e) {
3443       int oldStackLength = astLengthStack.length;
3444       int[] oldPos = astLengthStack;
3445       astLengthStack = new int[oldStackLength + StackIncrement];
3446       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3447       astLengthStack[astLengthPtr] = pos;
3448     }
3449   }
3450   protected void pushOnAstStack(AstNode node) {
3451     /*
3452      * add a new obj on top of the ast stack
3453      */
3454     try {
3455       astStack[++astPtr] = node;
3456     } catch (IndexOutOfBoundsException e) {
3457       int oldStackLength = astStack.length;
3458       AstNode[] oldStack = astStack;
3459       astStack = new AstNode[oldStackLength + AstStackIncrement];
3460       System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3461       astPtr = oldStackLength;
3462       astStack[astPtr] = node;
3463     }
3464     try {
3465       astLengthStack[++astLengthPtr] = 1;
3466     } catch (IndexOutOfBoundsException e) {
3467       int oldStackLength = astLengthStack.length;
3468       int[] oldPos = astLengthStack;
3469       astLengthStack = new int[oldStackLength + AstStackIncrement];
3470       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3471       astLengthStack[astLengthPtr] = 1;
3472     }
3473   }
3474 }