73d504e25863e2a9a5dadb865cbdf67ed4f0028c
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / Parser.java
1 /***********************************************************************************************************************************
2  * Copyright (c) 2002 www.phpeclipse.de All rights reserved. This program and the accompanying material are
3  * made available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
4  * http://www.eclipse.org/legal/cpl-v10.html
5  * 
6  * Contributors: www.phpeclipse.de
7  **********************************************************************************************************************************/
8 package net.sourceforge.phpdt.internal.compiler.parser;
9
10 import java.util.ArrayList;
11
12 import net.sourceforge.phpdt.core.compiler.CharOperation;
13 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
14 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
15 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
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.phpdt.internal.compiler.problem.ProblemSeverities;
21 import net.sourceforge.phpdt.internal.compiler.util.Util;
22 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
23 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.AND_AND_Expression;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.BinaryExpression;
28 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
29 import net.sourceforge.phpeclipse.internal.compiler.ast.ConditionalExpression;
30 import net.sourceforge.phpeclipse.internal.compiler.ast.EqualExpression;
31 import net.sourceforge.phpeclipse.internal.compiler.ast.Expression;
32 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
33 import net.sourceforge.phpeclipse.internal.compiler.ast.IfStatement;
34 import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
35 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
36 import net.sourceforge.phpeclipse.internal.compiler.ast.OR_OR_Expression;
37 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
38 import net.sourceforge.phpeclipse.internal.compiler.ast.Statement;
39 import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteral;
40 import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralDQ;
41 import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralSQ;
42 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
43
44 import org.eclipse.core.resources.IFile;
45 import org.eclipse.core.resources.IProject;
46 import org.eclipse.core.resources.IResource;
47
48 public class Parser //extends PHPParserSuperclass
49     implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
50   //internal data for the automat
51   protected final static int StackIncrement = 255;
52
53   protected int stateStackTop;
54
55   protected int[] stack = new int[StackIncrement];
56
57   public int firstToken; // handle for multiple parsing goals
58
59   public int lastAct; //handle for multiple parsing goals
60
61   protected RecoveredElement currentElement;
62
63   public static boolean VERBOSE_RECOVERY = false;
64
65   protected boolean diet = false; //tells the scanner to jump over some
66
67   // parts of the code/expressions like
68   // method bodies
69   //scanner token
70   public Scanner scanner;
71
72   private ArrayList phpList;
73
74   private int currentPHPString;
75
76   private boolean phpEnd;
77
78   // private static HashMap keywordMap = null;
79   private String str;
80
81   // current character
82   //  char ch;
83   // current token
84   int token;
85
86   // row counter for syntax errors:
87   //int rowCount;
88   // column counter for syntax errors:
89   //int columnCount;
90   //int chIndx;
91   //
92   //    // current identifier
93   //    String identifier;
94   Long longNumber;
95
96   Double doubleNumber;
97
98   private String stringValue;
99
100   /** Contains the current expression. */
101   // private StringBuffer expression;
102   //private boolean phpMode;
103   protected int modifiers;
104
105   protected int modifiersSourceStart;
106
107   //  protected IdentifierIndexManager indexManager;
108
109   protected Parser(ProblemReporter problemReporter) {
110     this.problemReporter = problemReporter;
111     this.options = problemReporter.options;
112     this.currentPHPString = 0;
113     //          PHPParserSuperclass.fileToParse = fileToParse;
114     this.phpList = null;
115     //    this.indexManager = null;
116     this.str = "";
117     this.token = TokenNameEOF;
118     //    this.chIndx = 0;
119     //    this.rowCount = 1;
120     //    this.columnCount = 0;
121     this.phpEnd = false;
122     //   getNextToken();
123     this.initializeScanner();
124   }
125
126   public void setFileToParse(IFile fileToParse) {
127     this.currentPHPString = 0;
128     //    PHPParserSuperclass.fileToParse = fileToParse;
129     this.phpList = null;
130     //    this.indexManager = null;
131     this.str = "";
132     this.token = TokenNameEOF;
133     this.phpEnd = false;
134     this.initializeScanner();
135   }
136
137   /**
138    * ClassDeclaration Constructor.
139    * 
140    * @param s
141    * @param sess
142    *          Description of Parameter
143    * @see
144    */
145   public Parser(IFile fileToParse) {
146     //    if (keywordMap == null) {
147     //      keywordMap = new HashMap();
148     //      for (int i = 0; i < PHP_KEYWORS.length; i++) {
149     //        keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
150     //      }
151     //    }
152     this.currentPHPString = 0;
153     //    PHPParserSuperclass.fileToParse = fileToParse;
154     this.phpList = null;
155     this.includesList = null;
156     this.str = "";
157     this.token = TokenNameEOF;
158     //    this.chIndx = 0;
159     //    this.rowCount = 1;
160     //    this.columnCount = 0;
161     this.phpEnd = false;
162     //   getNextToken();
163     this.initializeScanner();
164   }
165
166   public void initializeScanner() {
167     this.scanner = new Scanner(false /* comment */, false /* whitespace */, this.options
168         .getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /* nls */, false, false,
169         this.options.taskTags/* taskTags */, this.options.taskPriorites/* taskPriorities */);
170   }
171
172   /**
173    * Create marker for the parse error
174    */
175   //  private void setMarker(String message, int charStart, int charEnd, int
176   // errorLevel) {
177   //    setMarker(fileToParse, message, charStart, charEnd, errorLevel);
178   //  }
179   /**
180    * This method will throw the SyntaxError. It will add the good lines and columns to the Error
181    * 
182    * @param error
183    *          the error message
184    * @throws SyntaxError
185    *           the error raised
186    */
187   private void throwSyntaxError(String error) {
188     int problemStartPosition = scanner.getCurrentTokenStartPosition();
189     int problemEndPosition = scanner.getCurrentTokenEndPosition();
190     throwSyntaxError(error, problemStartPosition, problemEndPosition + 1);
191   }
192
193   /**
194    * This method will throw the SyntaxError. It will add the good lines and columns to the Error
195    * 
196    * @param error
197    *          the error message
198    * @throws SyntaxError
199    *           the error raised
200    */
201   //  private void throwSyntaxError(String error, int startRow) {
202   //    throw new SyntaxError(startRow, 0, " ", error);
203   //  }
204   private void throwSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
205     problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
206         compilationUnit.compilationResult);
207     throw new SyntaxError(1, 0, " ", error);
208   }
209
210   private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
211     problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
212         compilationUnit.compilationResult);
213   }
214
215   private void reportSyntaxWarning(String error, int problemStartPosition, int problemEndPosition) {
216     problemReporter.phpParsingWarning(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
217         compilationUnit.compilationResult);
218   }
219
220   /**
221    * gets the next token from input
222    */
223   private void getNextToken() {
224     try {
225       token = scanner.getNextToken();
226       if (Scanner.DEBUG) {
227         int currentEndPosition = scanner.getCurrentTokenEndPosition();
228         int currentStartPosition = scanner.getCurrentTokenStartPosition();
229         System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
230         System.out.println(scanner.toStringAction(token));
231       }
232     } catch (InvalidInputException e) {
233       token = TokenNameERROR;
234       String detailedMessage = e.getMessage();
235
236       if (detailedMessage == Scanner.UNTERMINATED_STRING) {
237         throwSyntaxError("Unterminated string.");
238       } else if (detailedMessage == Scanner.UNTERMINATED_COMMENT) {
239         throwSyntaxError("Unterminated commment.");
240       }
241     }
242     return;
243   }
244
245   public void init(String s) {
246     this.str = s;
247     this.token = TokenNameEOF;
248     //    this.chIndx = 0;
249     //    this.rowCount = 1;
250     //    this.columnCount = 0;
251     this.phpEnd = false;
252     //    this.phpMode = false;
253     /* scanner initialization */
254     scanner.setSource(s.toCharArray());
255     scanner.setPHPMode(false);
256   }
257
258   protected void initialize(boolean phpMode) {
259     initialize(phpMode, null);
260   }
261
262   protected void initialize(boolean phpMode, IdentifierIndexManager indexManager) {
263     compilationUnit = null;
264     referenceContext = null;
265     includesList = new ArrayList();
266     //    this.indexManager = indexManager;
267     this.str = "";
268     this.token = TokenNameEOF;
269     //    this.chIndx = 0;
270     //    this.rowCount = 1;
271     //    this.columnCount = 0;
272     this.phpEnd = false;
273     //    this.phpMode = phpMode;
274     scanner.setPHPMode(phpMode);
275   }
276
277   /**
278    * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt; &lt;/body&gt;'
279    */
280   public void parse(String s) {
281     init(s);
282     parse();
283   }
284
285   /**
286    * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt; &lt;/body&gt;'
287    */
288   protected void parse() {
289     getNextToken();
290     do {
291       try {
292         if (token != TokenNameEOF && token != TokenNameERROR) {
293           statementList();
294         }
295         if (token != TokenNameEOF) {
296           if (token == TokenNameERROR) {
297             throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
298           }
299           if (token == TokenNameRPAREN) {
300             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
301           }
302           if (token == TokenNameRBRACE) {
303             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
304           }
305           if (token == TokenNameRBRACKET) {
306             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
307           }
308           if (token == TokenNameLPAREN) {
309             throwSyntaxError("Read character '('; end-of-file not reached.");
310           }
311           if (token == TokenNameLBRACE) {
312             throwSyntaxError("Read character '{';  end-of-file not reached.");
313           }
314           if (token == TokenNameLBRACKET) {
315             throwSyntaxError("Read character '[';  end-of-file not reached.");
316           }
317           throwSyntaxError("End-of-file not reached.");
318         }
319         break;
320       } catch (SyntaxError sytaxErr1) {
321         // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(),
322         // ERROR);
323         //        setMarker(sytaxErr1.getMessage(),
324         // scanner.getCurrentTokenStartPosition(),
325         // scanner.getCurrentTokenEndPosition(), ERROR);
326         try {
327           // if an error occured,
328           // try to find keywords 'class' or 'function'
329           // to parse the rest of the string
330           while (token != TokenNameEOF && token != TokenNameERROR) {
331             if (token == TokenNameabstract || token == TokenNamefinal || token == TokenNameclass || token == TokenNamefunction) {
332               break;
333             }
334             getNextToken();
335           }
336           if (token == TokenNameEOF || token == TokenNameERROR) {
337             break;
338           }
339         } catch (SyntaxError sytaxErr2) {
340           //    setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(),
341           // ERROR);
342           //          setMarker(sytaxErr2.getMessage(),
343           // scanner.getCurrentTokenStartPosition(),
344           // scanner.getCurrentTokenEndPosition(), ERROR);
345           break;
346         }
347       }
348     } while (true);
349
350     endParse(0);
351   }
352
353   protected CompilationUnitDeclaration endParse(int act) {
354
355     this.lastAct = act;
356
357     if (currentElement != null) {
358       currentElement.topElement().updateParseTree();
359       if (VERBOSE_RECOVERY) {
360         System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
361         System.out.println("--------------------------"); //$NON-NLS-1$
362         System.out.println(compilationUnit);
363         System.out.println("----------------------------------"); //$NON-NLS-1$
364       }
365     } else {
366       if (diet & VERBOSE_RECOVERY) {
367         System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
368         System.out.println("--------------------------"); //$NON-NLS-1$
369         System.out.println(compilationUnit);
370         System.out.println("----------------------------------"); //$NON-NLS-1$
371       }
372     }
373     if (scanner.recordLineSeparator) {
374       compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
375     }
376     if (scanner.taskTags != null) {
377       for (int i = 0; i < scanner.foundTaskCount; i++) {
378         problemReporter().task(new String(scanner.foundTaskTags[i]), new String(scanner.foundTaskMessages[i]),
379             scanner.foundTaskPriorities[i] == null ? null : new String(scanner.foundTaskPriorities[i]),
380             scanner.foundTaskPositions[i][0], scanner.foundTaskPositions[i][1]);
381       }
382     }
383     compilationUnit.imports = new ImportReference[includesList.size()];
384     for (int i = 0; i < includesList.size(); i++) {
385       compilationUnit.imports[i] = (ImportReference) includesList.get(i);
386     }
387     return compilationUnit;
388   }
389
390   //  public PHPOutlineInfo parseInfo(Object parent, String s) {
391   //    PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
392   //    // Stack stack = new Stack();
393   //    // stack.push(outlineInfo.getDeclarations());
394   //    this.str = s;
395   //    this.token = TokenNameEOF;
396   //    // this.chIndx = 0;
397   //    // this.rowCount = 1;
398   //    // this.columnCount = 0;
399   //    this.phpEnd = false;
400   //    this.phpMode = false;
401   //    scanner.setSource(s.toCharArray());
402   //    scanner.setPHPMode(false);
403   //    
404   //    getNextToken();
405   //    parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
406   //    
407   //    return outlineInfo;
408   //  }
409   private boolean isVariable() {
410     return token == TokenNameVariable; //  || token == TokenNamethis;
411   }
412
413   //  private void parseDeclarations(PHPOutlineInfo outlineInfo,
414   //      OutlineableWithChildren current, boolean goBack) {
415   //    char[] ident;
416   //    // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
417   //    PHPSegmentWithChildren temp;
418   //    int counter = 0;
419   //    IPreferenceStore store =
420   // PHPeclipsePlugin.getDefault().getPreferenceStore();
421   //    try {
422   //      while (token != TokenNameEOF && token != TokenNameERROR) {
423   //        if (token == TokenNameVariable) {
424   //          ident = scanner.getCurrentIdentifierSource();
425   //          outlineInfo.addVariable(new String(ident));
426   //          getNextToken();
427   //        } else if (token == TokenNamevar) {
428   //          getNextToken();
429   //          if (token == TokenNameVariable
430   //              && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
431   //            ident = scanner.getCurrentIdentifierSource();
432   //            //substring(1) added because PHPVarDeclaration doesn't
433   //            // need the $ anymore
434   //            String variableName = new String(ident).substring(1);
435   //            outlineInfo.addVariable(variableName);
436   //            getNextToken();
437   //            if (token != TokenNameSEMICOLON) {
438   //              getNextToken();
439   //              ident = scanner.getCurrentTokenSource();
440   //              if (token > TokenNameKEYWORD) {
441   //                current.add(new PHPVarDeclaration(current, variableName,
442   //                // chIndx - ident.length,
443   //                    scanner.getCurrentTokenStartPosition(), new String(ident)));
444   //              } else {
445   //                switch (token) {
446   //                  case TokenNameVariable :
447   //                  case TokenNamethis :
448   //                    current.add(new PHPVarDeclaration(current, variableName,
449   //                    // chIndx -
450   //                        // ident.length,
451   //                        scanner.getCurrentTokenStartPosition(), new String(
452   //                            ident)));
453   //                    break;
454   //                  case TokenNameIdentifier :
455   //                    current.add(new PHPVarDeclaration(current, variableName,
456   //                    // chIndx -
457   //                        // ident.length,
458   //                        scanner.getCurrentTokenStartPosition(), new String(
459   //                            ident)));
460   //                    break;
461   //                  case TokenNameDoubleLiteral :
462   //                    current.add(new PHPVarDeclaration(current, variableName
463   //                        + doubleNumber,
464   //                    // chIndx -
465   //                        // ident.length,
466   //                        scanner.getCurrentTokenStartPosition(), new String(
467   //                            ident)));
468   //                    break;
469   //                  case TokenNameIntegerLiteral :
470   //                    current.add(new PHPVarDeclaration(current, variableName,
471   //                    // chIndx -
472   //                        // ident.length,
473   //                        scanner.getCurrentTokenStartPosition(), new String(
474   //                            ident)));
475   //                    break;
476   //                  case TokenNameStringInterpolated :
477   //                  case TokenNameStringLiteral :
478   //                    current.add(new PHPVarDeclaration(current, variableName,
479   //                    // chIndx -
480   //                        // ident.length,
481   //                        scanner.getCurrentTokenStartPosition(), new String(
482   //                            ident)));
483   //                    break;
484   //                  case TokenNameStringConstant :
485   //                    current.add(new PHPVarDeclaration(current, variableName,
486   //                    // chIndx -
487   //                        // ident.length,
488   //                        scanner.getCurrentTokenStartPosition(), new String(
489   //                            ident)));
490   //                    break;
491   //                  default :
492   //                    current.add(new PHPVarDeclaration(current, variableName,
493   //                    // chIndx -
494   //                        // ident.length
495   //                        scanner.getCurrentTokenStartPosition()));
496   //                    break;
497   //                }
498   //              }
499   //            } else {
500   //              ident = scanner.getCurrentIdentifierSource();
501   //              current.add(new PHPVarDeclaration(current, variableName,
502   //              // chIndx - ident.length
503   //                  scanner.getCurrentTokenStartPosition()));
504   //            }
505   //          }
506   //        } else if (token == TokenNamefunction) {
507   //          getNextToken();
508   //          if (token == TokenNameAND) {
509   //            getNextToken();
510   //          }
511   //          if (token == TokenNameIdentifier
512   //              && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
513   //            ident = scanner.getCurrentIdentifierSource();
514   //            outlineInfo.addVariable(new String(ident));
515   //            temp = new PHPFunctionDeclaration(current, new String(ident),
516   //            // chIndx - ident.length
517   //                scanner.getCurrentTokenStartPosition());
518   //            current.add(temp);
519   //            getNextToken();
520   //            parseDeclarations(outlineInfo, temp, true);
521   //          }
522   //        } else if (token == TokenNameclass) {
523   //          getNextToken();
524   //          if (token == TokenNameIdentifier
525   //              && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
526   //            ident = scanner.getCurrentIdentifierSource();
527   //            outlineInfo.addVariable(new String(ident));
528   //            temp = new PHPClassDeclaration(current, new String(ident),
529   //            // chIndx - ident.len
530   //                scanner.getCurrentTokenStartPosition());
531   //            current.add(temp);
532   //            // stack.push(temp);
533   //            getNextToken();
534   //            //skip tokens for classname, extends and others until
535   //            // we have the opening '{'
536   //            while (token != TokenNameLBRACE && token != TokenNameEOF
537   //                && token != TokenNameERROR) {
538   //              getNextToken();
539   //            }
540   //            parseDeclarations(outlineInfo, temp, true);
541   //            // stack.pop();
542   //          }
543   //        } else if ((token == TokenNameLBRACE)
544   //            || (token == TokenNameDOLLAR_LBRACE)) {
545   //          getNextToken();
546   //          counter++;
547   //        } else if (token == TokenNameRBRACE) {
548   //          getNextToken();
549   //          --counter;
550   //          if (counter == 0 && goBack) {
551   //            return;
552   //          }
553   //        } else if (token == TokenNamerequire || token == TokenNamerequire_once
554   //            || token == TokenNameinclude || token == TokenNameinclude_once) {
555   //          ident = scanner.getCurrentTokenSource();
556   //          getNextToken();
557   //          int startPosition = scanner.getCurrentTokenStartPosition();
558   //          expr();
559   //          char[] expr = scanner.getCurrentTokenSource(startPosition);
560   //          outlineInfo.addVariable(new String(ident));
561   //          current.add(new PHPReqIncDeclaration(current, new String(ident),
562   //          // chIndx - ident.length,
563   //              startPosition, new String(expr)));
564   //          getNextToken();
565   //        } else {
566   //          getNextToken();
567   //        }
568   //      }
569   //    } catch (SyntaxError sytaxErr) {
570   //      // try {
571   //      // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
572   //      // setMarker(sytaxErr.getMessage(),
573   //      // scanner.getCurrentTokenStartPosition(),
574   //      // scanner.getCurrentTokenEndPosition(), ERROR);
575   //      // } catch (CoreException e) {
576   //      // }
577   //    }
578   //  }
579   private void statementList() {
580     do {
581       statement(TokenNameEOF);
582       if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse)
583           || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor)
584           || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch)
585           || (token == TokenNameenddeclare) || (token == TokenNameEOF) || (token == TokenNameERROR)) {
586         return;
587       }
588     } while (true);
589   }
590
591   private void functionBody(MethodDeclaration methodDecl) {
592     // '{' [statement-list] '}'
593     if (token == TokenNameLBRACE) {
594       getNextToken();
595     } else {
596       throwSyntaxError("'{' expected in compound-statement.");
597     }
598     if (token != TokenNameRBRACE) {
599       statementList();
600     }
601     if (token == TokenNameRBRACE) {
602       methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
603       getNextToken();
604     } else {
605       throwSyntaxError("'}' expected in compound-statement.");
606     }
607   }
608
609   private Statement statement(int previousToken) {
610     Statement statement = null;
611     Expression expression;
612     int sourceStart = scanner.getCurrentTokenStartPosition();
613     if (token == TokenNameif) {
614       getNextToken();
615       if (token == TokenNameLPAREN) {
616         getNextToken();
617       } else {
618         throwSyntaxError("'(' expected after 'if' keyword.");
619       }
620       expression = expr();
621       if (token == TokenNameRPAREN) {
622         getNextToken();
623       } else {
624         throwSyntaxError("')' expected after 'if' condition.");
625       }
626       ifStatement();
627       return new IfStatement(expression, statement, sourceStart, scanner.getCurrentTokenEndPosition());
628     } else if (token == TokenNameswitch) {
629       getNextToken();
630       if (token == TokenNameLPAREN) {
631         getNextToken();
632       } else {
633         throwSyntaxError("'(' expected after 'switch' keyword.");
634       }
635       expr();
636       if (token == TokenNameRPAREN) {
637         getNextToken();
638       } else {
639         throwSyntaxError("')' expected after 'switch' condition.");
640       }
641       switchStatement();
642       return statement;
643     } else if (token == TokenNamefor) {
644       getNextToken();
645       if (token == TokenNameLPAREN) {
646         getNextToken();
647       } else {
648         throwSyntaxError("'(' expected after 'for' keyword.");
649       }
650       if (token == TokenNameSEMICOLON) {
651         getNextToken();
652       } else {
653         expressionList();
654         if (token == TokenNameSEMICOLON) {
655           getNextToken();
656         } else {
657           throwSyntaxError("';' expected after 'for'.");
658         }
659       }
660       if (token == TokenNameSEMICOLON) {
661         getNextToken();
662       } else {
663         expressionList();
664         if (token == TokenNameSEMICOLON) {
665           getNextToken();
666         } else {
667           throwSyntaxError("';' expected after 'for'.");
668         }
669       }
670       if (token == TokenNameRPAREN) {
671         getNextToken();
672       } else {
673         expressionList();
674         if (token == TokenNameRPAREN) {
675           getNextToken();
676         } else {
677           throwSyntaxError("')' expected after 'for'.");
678         }
679       }
680       forStatement();
681       return statement;
682     } else if (token == TokenNamewhile) {
683       getNextToken();
684       if (token == TokenNameLPAREN) {
685         getNextToken();
686       } else {
687         throwSyntaxError("'(' expected after 'while' keyword.");
688       }
689       expr();
690       if (token == TokenNameRPAREN) {
691         getNextToken();
692       } else {
693         throwSyntaxError("')' expected after 'while' condition.");
694       }
695       whileStatement();
696       return statement;
697     } else if (token == TokenNamedo) {
698       getNextToken();
699       if (token == TokenNameLBRACE) {
700         getNextToken();
701         if (token != TokenNameRBRACE) {
702           statementList();
703         }
704         if (token == TokenNameRBRACE) {
705           getNextToken();
706         } else {
707           throwSyntaxError("'}' expected after 'do' keyword.");
708         }
709       } else {
710         statement(TokenNameEOF);
711       }
712       if (token == TokenNamewhile) {
713         getNextToken();
714         if (token == TokenNameLPAREN) {
715           getNextToken();
716         } else {
717           throwSyntaxError("'(' expected after 'while' keyword.");
718         }
719         expr();
720         if (token == TokenNameRPAREN) {
721           getNextToken();
722         } else {
723           throwSyntaxError("')' expected after 'while' condition.");
724         }
725       } else {
726         throwSyntaxError("'while' expected after 'do' keyword.");
727       }
728       if (token == TokenNameSEMICOLON) {
729         getNextToken();
730       } else {
731         if (token != TokenNameINLINE_HTML) {
732           throwSyntaxError("';' expected after do-while statement.");
733         }
734         getNextToken();
735       }
736       return statement;
737     } else if (token == TokenNameforeach) {
738       getNextToken();
739       if (token == TokenNameLPAREN) {
740         getNextToken();
741       } else {
742         throwSyntaxError("'(' expected after 'foreach' keyword.");
743       }
744       expr();
745       if (token == TokenNameas) {
746         getNextToken();
747       } else {
748         throwSyntaxError("'as' expected after 'foreach' exxpression.");
749       }
750       //      variable();
751       foreach_variable();
752       foreach_optional_arg();
753       if (token == TokenNameEQUAL_GREATER) {
754         getNextToken();
755         variable();
756       }
757       if (token == TokenNameRPAREN) {
758         getNextToken();
759       } else {
760         throwSyntaxError("')' expected after 'foreach' expression.");
761       }
762       foreachStatement();
763       return statement;
764     } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
765       getNextToken();
766       if (token != TokenNameSEMICOLON) {
767         expr();
768       }
769       if (token == TokenNameSEMICOLON) {
770         getNextToken();
771       } else {
772         if (token != TokenNameINLINE_HTML) {
773           throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
774         }
775         getNextToken();
776       }
777       return statement;
778     } else if (token == TokenNameecho) {
779       getNextToken();
780       expressionList();
781       if (token == TokenNameSEMICOLON) {
782         getNextToken();
783       } else {
784         if (token != TokenNameINLINE_HTML) {
785           throwSyntaxError("';' expected after 'echo' statement.");
786         }
787         getNextToken();
788       }
789       return statement;
790     } else if (token == TokenNameINLINE_HTML) {
791       getNextToken();
792       return statement;
793       //    } else if (token == TokenNameprint) {
794       //      getNextToken();
795       //      expression();
796       //      if (token == TokenNameSEMICOLON) {
797       //        getNextToken();
798       //      } else {
799       //        if (token != TokenNameStopPHP) {
800       //          throwSyntaxError("';' expected after 'print' statement.");
801       //        }
802       //        getNextToken();
803       //      }
804       //      return;
805     } else if (token == TokenNameglobal) {
806       getNextToken();
807       global_var_list();
808       if (token == TokenNameSEMICOLON) {
809         getNextToken();
810       } else {
811         if (token != TokenNameINLINE_HTML) {
812           throwSyntaxError("';' expected after 'global' statement.");
813         }
814         getNextToken();
815       }
816       return statement;
817     } else if (token == TokenNamestatic) {
818       getNextToken();
819       static_var_list();
820       if (token == TokenNameSEMICOLON) {
821         getNextToken();
822       } else {
823         if (token != TokenNameINLINE_HTML) {
824           throwSyntaxError("';' expected after 'static' statement.");
825         }
826         getNextToken();
827       }
828       return statement;
829     } else if (token == TokenNameunset) {
830       getNextToken();
831       if (token == TokenNameLPAREN) {
832         getNextToken();
833       } else {
834         throwSyntaxError("'(' expected after 'unset' statement.");
835       }
836       unset_variables();
837       if (token == TokenNameRPAREN) {
838         getNextToken();
839       } else {
840         throwSyntaxError("')' expected after 'unset' statement.");
841       }
842       if (token == TokenNameSEMICOLON) {
843         getNextToken();
844       } else {
845         if (token != TokenNameINLINE_HTML) {
846           throwSyntaxError("';' expected after 'unset' statement.");
847         }
848         getNextToken();
849       }
850       return statement;
851     } else if (token == TokenNamefunction) {
852       MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
853       methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
854       methodDecl.modifiers = AccDefault;
855       getNextToken();
856       functionDefinition(methodDecl);
857       return statement;
858     } else if (token == TokenNamedeclare) {
859       //T_DECLARE '(' declare_list ')' declare_statement
860       getNextToken();
861       if (token != TokenNameLPAREN) {
862         throwSyntaxError("'(' expected in 'declare' statement.");
863       }
864       getNextToken();
865       declare_list();
866       if (token != TokenNameRPAREN) {
867         throwSyntaxError("')' expected in 'declare' statement.");
868       }
869       getNextToken();
870       declare_statement();
871       return statement;
872     } else if (token == TokenNametry) {
873       getNextToken();
874       if (token != TokenNameLBRACE) {
875         throwSyntaxError("'{' expected in 'try' statement.");
876       }
877       getNextToken();
878       statementList();
879       if (token != TokenNameRBRACE) {
880         throwSyntaxError("'}' expected in 'try' statement.");
881       }
882       getNextToken();
883       return statement;
884     } else if (token == TokenNamecatch) {
885       getNextToken();
886       if (token != TokenNameLPAREN) {
887         throwSyntaxError("'(' expected in 'catch' statement.");
888       }
889       getNextToken();
890       fully_qualified_class_name();
891       if (token != TokenNameVariable) {
892         throwSyntaxError("Variable expected in 'catch' statement.");
893       }
894       getNextToken();
895       if (token != TokenNameRPAREN) {
896         throwSyntaxError("')' expected in 'catch' statement.");
897       }
898       getNextToken();
899       if (token != TokenNameLBRACE) {
900         throwSyntaxError("'{' expected in 'catch' statement.");
901       }
902       getNextToken();
903       if (token != TokenNameRBRACE) {
904         statementList();
905         if (token != TokenNameRBRACE) {
906           throwSyntaxError("'}' expected in 'catch' statement.");
907         }
908       }
909       getNextToken();
910       additional_catches();
911       return statement;
912     } else if (token == TokenNamethrow) {
913       getNextToken();
914       expr();
915       if (token == TokenNameSEMICOLON) {
916         getNextToken();
917       } else {
918         throwSyntaxError("';' expected after 'throw' exxpression.");
919       }
920       return statement;
921     } else if (token == TokenNamefinal || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) {
922       TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
923       typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
924       typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
925       typeDecl.name = new char[] { ' ' };
926       // default super class
927       typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
928       compilationUnit.types.add(typeDecl);
929       try {
930         pushOnAstStack(typeDecl);
931         unticked_class_declaration_statement(typeDecl);
932         //        classBody(typeDecl);
933       } finally {
934         astPtr--;
935         astLengthPtr--;
936       }
937       return statement;
938       //      } else {
939       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
940     } else if (token == TokenNameLBRACE) {
941       getNextToken();
942       if (token != TokenNameRBRACE) {
943         statementList();
944       }
945       if (token == TokenNameRBRACE) {
946         getNextToken();
947         return statement;
948       } else {
949         throwSyntaxError("'}' expected.");
950       }
951     } else {
952       if (token != TokenNameSEMICOLON) {
953         expr();
954       }
955       if (token == TokenNameSEMICOLON) {
956         getNextToken();
957         return statement;
958       } else {
959         if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
960           throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
961         }
962         getNextToken();
963       }
964     }
965     // may be null
966     return statement;
967   }
968
969   private void declare_statement() {
970     //  statement
971     //| ':' inner_statement_list T_ENDDECLARE ';'
972     //;
973     if (token == TokenNameCOLON) {
974       getNextToken();
975       // TODO: implement inner_statement_list();
976       statementList();
977       if (token != TokenNameenddeclare) {
978         throwSyntaxError("'enddeclare' expected in 'declare' statement.");
979       }
980       getNextToken();
981       if (token != TokenNameSEMICOLON) {
982         throwSyntaxError("';' expected after 'enddeclare' keyword.");
983       }
984       getNextToken();
985     } else {
986       statement(TokenNameRPAREN);
987     }
988   }
989
990   private void declare_list() {
991     //  T_STRING '=' static_scalar
992     //| declare_list ',' T_STRING '=' static_scalar
993     while (true) {
994       if (token != TokenNameIdentifier) {
995         throwSyntaxError("Identifier expected in 'declare' list.");
996       }
997       getNextToken();
998       if (token != TokenNameEQUAL) {
999         throwSyntaxError("'=' expected in 'declare' list.");
1000       }
1001       getNextToken();
1002       static_scalar();
1003       if (token != TokenNameCOMMA) {
1004         break;
1005       }
1006       getNextToken();
1007     }
1008   }
1009
1010   private void additional_catches() {
1011     while (token == TokenNamecatch) {
1012       getNextToken();
1013       if (token != TokenNameLPAREN) {
1014         throwSyntaxError("'(' expected in 'catch' statement.");
1015       }
1016       getNextToken();
1017       fully_qualified_class_name();
1018       if (token != TokenNameVariable) {
1019         throwSyntaxError("Variable expected in 'catch' statement.");
1020       }
1021       getNextToken();
1022       if (token != TokenNameRPAREN) {
1023         throwSyntaxError("')' expected in 'catch' statement.");
1024       }
1025       getNextToken();
1026       if (token != TokenNameLBRACE) {
1027         throwSyntaxError("'{' expected in 'catch' statement.");
1028       }
1029       getNextToken();
1030       if (token != TokenNameRBRACE) {
1031         statementList();
1032       }
1033       if (token != TokenNameRBRACE) {
1034         throwSyntaxError("'}' expected in 'catch' statement.");
1035       }
1036       getNextToken();
1037     }
1038   }
1039
1040   private void foreach_variable() {
1041     //  w_variable
1042     //| '&' w_variable
1043     if (token == TokenNameAND) {
1044       getNextToken();
1045     }
1046     w_variable();
1047   }
1048
1049   private void foreach_optional_arg() {
1050     //  /* empty */
1051     //| T_DOUBLE_ARROW foreach_variable
1052     if (token == TokenNameEQUAL_GREATER) {
1053       getNextToken();
1054       foreach_variable();
1055     }
1056   }
1057
1058   private void global_var_list() {
1059     //  global_var_list:
1060     //  global_var_list ',' global_var
1061     //| global_var
1062     while (true) {
1063       global_var();
1064       if (token != TokenNameCOMMA) {
1065         break;
1066       }
1067       getNextToken();
1068     }
1069   }
1070
1071   private void global_var() {
1072     //global_var:
1073     //  T_VARIABLE
1074     //| '$' r_variable
1075     //| '$' '{' expr '}'
1076     if (token == TokenNameVariable) {
1077       getNextToken();
1078     } else if (token == TokenNameDOLLAR) {
1079       getNextToken();
1080       if (token == TokenNameLPAREN) {
1081         getNextToken();
1082         expr();
1083         if (token != TokenNameLPAREN) {
1084           throwSyntaxError("')' expected in global variable.");
1085         }
1086         getNextToken();
1087       } else {
1088         r_variable();
1089       }
1090     }
1091   }
1092
1093   private void static_var_list() {
1094     //static_var_list:
1095     //  static_var_list ',' T_VARIABLE
1096     //| static_var_list ',' T_VARIABLE '=' static_scalar
1097     //| T_VARIABLE
1098     //| T_VARIABLE '=' static_scalar
1099     while (true) {
1100       if (token == TokenNameVariable) {
1101         getNextToken();
1102         if (token == TokenNameEQUAL) {
1103           getNextToken();
1104           static_scalar();
1105         }
1106         if (token != TokenNameCOMMA) {
1107           break;
1108         }
1109         getNextToken();
1110       } else {
1111         break;
1112       }
1113     }
1114   }
1115
1116   private void unset_variables() {
1117     //    unset_variables:
1118     //                  unset_variable
1119     //          | unset_variables ',' unset_variable
1120     //    unset_variable:
1121     //                  variable
1122     while (true) {
1123       variable();
1124       if (token != TokenNameCOMMA) {
1125         break;
1126       }
1127       getNextToken();
1128     }
1129   }
1130
1131   private final void initializeModifiers() {
1132     this.modifiers = 0;
1133     this.modifiersSourceStart = -1;
1134   }
1135
1136   private final void checkAndSetModifiers(int flag) {
1137     this.modifiers |= flag;
1138     if (this.modifiersSourceStart < 0)
1139       this.modifiersSourceStart = this.scanner.startPosition;
1140   }
1141
1142   private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1143     initializeModifiers();
1144     if (token == TokenNameinterface) {
1145       //      interface_entry T_STRING
1146       //                interface_extends_list
1147       //                '{' class_statement_list '}'
1148       checkAndSetModifiers(AccInterface);
1149       getNextToken();
1150       typeDecl.modifiers = this.modifiers;
1151       typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1152       typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1153       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1154         typeDecl.name = scanner.getCurrentIdentifierSource();
1155         if (token > TokenNameKEYWORD) {
1156           problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
1157               scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
1158           //          throwSyntaxError("Don't use a keyword for interface declaration [" + scanner.toStringAction(token) + "].",
1159           //              typeDecl.sourceStart, typeDecl.sourceEnd);
1160         }
1161         getNextToken();
1162         interface_extends_list();
1163       } else {
1164         typeDecl.name = new char[] { ' ' };
1165         throwSyntaxError("Interface name expected after keyword 'interface'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1166         return;
1167       }
1168     } else {
1169       //      class_entry_type T_STRING extends_from
1170       //                implements_list
1171       //                '{' class_statement_list'}'
1172       class_entry_type();
1173       typeDecl.modifiers = this.modifiers;
1174       typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1175       typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1176       //identifier
1177       //identifier 'extends' identifier
1178       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1179         typeDecl.name = scanner.getCurrentIdentifierSource();
1180         if (token > TokenNameKEYWORD) {
1181           problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
1182               scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
1183           //          throwSyntaxError("Don't use a keyword for class declaration [" + scanner.toStringAction(token) + "].",
1184           //              typeDecl.sourceStart, typeDecl.sourceEnd);
1185         }
1186         getNextToken();
1187         //    extends_from:
1188         //              /* empty */
1189         //      | T_EXTENDS fully_qualified_class_name
1190         if (token == TokenNameextends) {
1191           interface_extends_list();
1192           //          getNextToken();
1193           //          if (token != TokenNameIdentifier) {
1194           //            throwSyntaxError("Class name expected after keyword
1195           // 'extends'.",
1196           //                scanner.getCurrentTokenStartPosition(), scanner
1197           //                    .getCurrentTokenEndPosition());
1198           //          }
1199         }
1200         implements_list();
1201       } else {
1202         typeDecl.name = new char[] { ' ' };
1203         throwSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1204         return;
1205       }
1206     }
1207     //  '{' class_statement_list '}'
1208     if (token == TokenNameLBRACE) {
1209       getNextToken();
1210       if (token != TokenNameRBRACE) {
1211         ArrayList list = new ArrayList();
1212         class_statement_list(list);
1213         typeDecl.fields = new FieldDeclaration[list.size()];
1214         for (int i = 0; i < list.size(); i++) {
1215           typeDecl.fields[i] = (FieldDeclaration) list.get(i);
1216         }
1217       }
1218       if (token == TokenNameRBRACE) {
1219         typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1220         getNextToken();
1221       } else {
1222         throwSyntaxError("'}' expected at end of class body.");
1223       }
1224     } else {
1225       throwSyntaxError("'{' expected at start of class body.");
1226     }
1227   }
1228
1229   private void class_entry_type() {
1230     //  T_CLASS
1231     //  | T_ABSTRACT T_CLASS
1232     //  | T_FINAL T_CLASS
1233     if (token == TokenNameclass) {
1234       getNextToken();
1235     } else if (token == TokenNameabstract) {
1236       checkAndSetModifiers(AccAbstract);
1237       getNextToken();
1238       if (token != TokenNameclass) {
1239         throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1240       }
1241       getNextToken();
1242     } else if (token == TokenNamefinal) {
1243       checkAndSetModifiers(AccFinal);
1244       getNextToken();
1245       if (token != TokenNameclass) {
1246         throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1247       }
1248       getNextToken();
1249     } else {
1250       throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1251     }
1252   }
1253
1254   private void interface_extends_list() {
1255     //  /* empty */
1256     //  | T_EXTENDS interface_list
1257     if (token == TokenNameextends) {
1258       getNextToken();
1259       interface_list();
1260     }
1261   }
1262
1263   private void implements_list() {
1264     //  /* empty */
1265     //  | T_IMPLEMENTS interface_list
1266     if (token == TokenNameimplements) {
1267       getNextToken();
1268       interface_list();
1269     }
1270   }
1271
1272   private void interface_list() {
1273     //  interface_list:
1274     //  fully_qualified_class_name
1275     //| interface_list ',' fully_qualified_class_name
1276     do {
1277       if (token == TokenNameIdentifier) {
1278         getNextToken();
1279       } else {
1280         throwSyntaxError("Interface name expected after keyword 'implements'.");
1281       }
1282       if (token != TokenNameCOMMA) {
1283         return;
1284       }
1285       getNextToken();
1286     } while (true);
1287   }
1288
1289   //  private void classBody(TypeDeclaration typeDecl) {
1290   //    //'{' [class-element-list] '}'
1291   //    if (token == TokenNameLBRACE) {
1292   //      getNextToken();
1293   //      if (token != TokenNameRBRACE) {
1294   //        class_statement_list();
1295   //      }
1296   //      if (token == TokenNameRBRACE) {
1297   //        typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1298   //        getNextToken();
1299   //      } else {
1300   //        throwSyntaxError("'}' expected at end of class body.");
1301   //      }
1302   //    } else {
1303   //      throwSyntaxError("'{' expected at start of class body.");
1304   //    }
1305   //  }
1306   private void class_statement_list(ArrayList list) {
1307     do {
1308       class_statement(list);
1309     } while (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic
1310         || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar
1311         || token == TokenNameconst);
1312   }
1313
1314   private void class_statement(ArrayList list) {
1315     //    class_statement:
1316     //          variable_modifiers class_variable_declaration ';'
1317     //  | class_constant_declaration ';'
1318     //  | method_modifiers T_FUNCTION is_reference T_STRING
1319     //    '(' parameter_list ')' method_body
1320     initializeModifiers();
1321     int declarationSourceStart = scanner.getCurrentTokenStartPosition();
1322
1323     if (token == TokenNamevar) {
1324       checkAndSetModifiers(AccPublic);
1325       problemReporter.phpVarDeprecatedWarning(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
1326           referenceContext, compilationUnit.compilationResult);
1327       getNextToken();
1328       class_variable_declaration(declarationSourceStart, list);
1329     } else if (token == TokenNameconst) {
1330       checkAndSetModifiers(AccFinal | AccPublic);
1331       class_constant_declaration(declarationSourceStart, list);
1332       if (token != TokenNameSEMICOLON) {
1333         throwSyntaxError("';' expected after class const declaration.");
1334       }
1335       getNextToken();
1336     } else {
1337       boolean hasModifiers = member_modifiers();
1338       if (token == TokenNamefunction) {
1339         if (!hasModifiers) {
1340           checkAndSetModifiers(AccPublic);
1341         }
1342         MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1343         methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1344         methodDecl.modifiers = this.modifiers;
1345         getNextToken();
1346         functionDefinition(methodDecl);
1347       } else {
1348         if (!hasModifiers) {
1349           throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1350         }
1351         class_variable_declaration(declarationSourceStart, list);
1352       }
1353     }
1354   }
1355
1356   private void class_constant_declaration(int declarationSourceStart, ArrayList list) {
1357     //  class_constant_declaration ',' T_STRING '=' static_scalar
1358     //  | T_CONST T_STRING '=' static_scalar
1359     if (token != TokenNameconst) {
1360       throwSyntaxError("'const' keyword expected in class declaration.");
1361     } else {
1362       getNextToken();
1363     }
1364     while (true) {
1365       if (token != TokenNameIdentifier) {
1366         throwSyntaxError("Identifier expected in class const declaration.");
1367       }
1368       FieldDeclaration fieldDeclaration = new FieldDeclaration(scanner.getCurrentIdentifierSource(), scanner
1369           .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1370       fieldDeclaration.modifiers = this.modifiers;
1371       fieldDeclaration.declarationSourceStart = declarationSourceStart;
1372       fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1373       fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1374       //        fieldDeclaration.type
1375       list.add(fieldDeclaration);
1376       getNextToken();
1377       if (token != TokenNameEQUAL) {
1378         throwSyntaxError("'=' expected in class const declaration.");
1379       }
1380       getNextToken();
1381       static_scalar();
1382       if (token != TokenNameCOMMA) {
1383         break; // while(true)-loop
1384       }
1385       getNextToken();
1386     }
1387   }
1388
1389   //  private void variable_modifiers() {
1390   //    // variable_modifiers:
1391   //    // non_empty_member_modifiers
1392   //    //| T_VAR
1393   //    initializeModifiers();
1394   //    if (token == TokenNamevar) {
1395   //      checkAndSetModifiers(AccPublic);
1396   //      reportSyntaxError(
1397   //          "Keyword 'var' is deprecated. Please use 'public' 'private' or
1398   // 'protected'
1399   // modifier for field declarations.",
1400   //          scanner.getCurrentTokenStartPosition(), scanner
1401   //              .getCurrentTokenEndPosition());
1402   //      getNextToken();
1403   //    } else {
1404   //      if (!member_modifiers()) {
1405   //        throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1406   // field declarations.");
1407   //      }
1408   //    }
1409   //  }
1410   //  private void method_modifiers() {
1411   //    //method_modifiers:
1412   //    // /* empty */
1413   //    //| non_empty_member_modifiers
1414   //    initializeModifiers();
1415   //    if (!member_modifiers()) {
1416   //      checkAndSetModifiers(AccPublic);
1417   //    }
1418   //  }
1419   private boolean member_modifiers() {
1420     //  T_PUBLIC
1421     //| T_PROTECTED
1422     //| T_PRIVATE
1423     //| T_STATIC
1424     //| T_ABSTRACT
1425     //| T_FINAL
1426     boolean foundToken = false;
1427     while (true) {
1428       if (token == TokenNamepublic) {
1429         checkAndSetModifiers(AccPublic);
1430         getNextToken();
1431         foundToken = true;
1432       } else if (token == TokenNameprotected) {
1433         checkAndSetModifiers(AccProtected);
1434         getNextToken();
1435         foundToken = true;
1436       } else if (token == TokenNameprivate) {
1437         checkAndSetModifiers(AccPrivate);
1438         getNextToken();
1439         foundToken = true;
1440       } else if (token == TokenNamestatic) {
1441         checkAndSetModifiers(AccStatic);
1442         getNextToken();
1443         foundToken = true;
1444       } else if (token == TokenNameabstract) {
1445         checkAndSetModifiers(AccAbstract);
1446         getNextToken();
1447         foundToken = true;
1448       } else if (token == TokenNamefinal) {
1449         checkAndSetModifiers(AccFinal);
1450         getNextToken();
1451         foundToken = true;
1452       } else {
1453         break;
1454       }
1455     }
1456     return foundToken;
1457   }
1458
1459   private void class_variable_declaration(int declarationSourceStart, ArrayList list) {
1460     //    class_variable_declaration:
1461     //          class_variable_declaration ',' T_VARIABLE
1462     //  | class_variable_declaration ',' T_VARIABLE '=' static_scalar
1463     //  | T_VARIABLE
1464     //  | T_VARIABLE '=' static_scalar
1465     char[] classVariable;
1466     do {
1467       if (token == TokenNameVariable) {
1468         classVariable = scanner.getCurrentIdentifierSource();
1469         //  indexManager.addIdentifierInformation('v', classVariable, buf, -1, -1);
1470         FieldDeclaration fieldDeclaration = new FieldDeclaration(classVariable, scanner.getCurrentTokenStartPosition(), scanner
1471             .getCurrentTokenEndPosition());
1472         fieldDeclaration.modifiers = this.modifiers;
1473         fieldDeclaration.declarationSourceStart = declarationSourceStart;
1474         fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1475         fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1476         //        fieldDeclaration.type
1477         list.add(fieldDeclaration);
1478         getNextToken();
1479         if (token == TokenNameEQUAL) {
1480           getNextToken();
1481           static_scalar();
1482         }
1483       } else {
1484         //        if (token == TokenNamethis) {
1485         //          throwSyntaxError("'$this' not allowed after keyword 'public'
1486         // 'protected' 'private' 'var'.");
1487         //        }
1488         throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
1489       }
1490       if (token != TokenNameCOMMA) {
1491         break;
1492       }
1493       getNextToken();
1494     } while (true);
1495     if (token != TokenNameSEMICOLON) {
1496       throwSyntaxError("';' expected after field declaration.");
1497     }
1498     getNextToken();
1499   }
1500
1501   private void functionDefinition(MethodDeclaration methodDecl) {
1502     boolean isAbstract = false;
1503     if (astPtr == 0) {
1504       compilationUnit.types.add(methodDecl);
1505     } else {
1506       ASTNode node = astStack[astPtr];
1507       if (node instanceof TypeDeclaration) {
1508         TypeDeclaration typeDecl = ((TypeDeclaration) node);
1509         if (typeDecl.methods == null) {
1510           typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
1511         } else {
1512           AbstractMethodDeclaration[] newMethods;
1513           System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1,
1514               typeDecl.methods.length);
1515           newMethods[0] = methodDecl;
1516           typeDecl.methods = newMethods;
1517         }
1518         if ((typeDecl.modifiers & AccAbstract) == AccAbstract) {
1519           isAbstract = true;
1520         } else if ((typeDecl.modifiers & AccInterface) == AccInterface) {
1521           isAbstract = true;
1522         }
1523       }
1524     }
1525     functionDeclarator(methodDecl);
1526     if (token == TokenNameSEMICOLON) {
1527       if (!isAbstract) {
1528         throwSyntaxError("Body declaration expected for method: " + new String(methodDecl.selector));
1529       }
1530       getNextToken();
1531       return;
1532     }
1533     functionBody(methodDecl);
1534   }
1535
1536   private void functionDeclarator(MethodDeclaration methodDecl) {
1537     //identifier '(' [parameter-list] ')'
1538     if (token == TokenNameAND) {
1539       getNextToken();
1540     }
1541     methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1542     methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1543     if (Scanner.isIdentifierOrKeyword(token)) {
1544       methodDecl.selector = scanner.getCurrentIdentifierSource();
1545       if (token > TokenNameKEYWORD) {
1546         problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
1547             scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
1548         //        reportSyntaxWarning("Don't use keyword for function declaration [" + scanner.toStringAction(token) + "].",
1549         //          scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1550       }
1551       getNextToken();
1552       if (token == TokenNameLPAREN) {
1553         getNextToken();
1554       } else {
1555         throwSyntaxError("'(' expected in function declaration.");
1556       }
1557       if (token != TokenNameRPAREN) {
1558         parameter_list();
1559       }
1560       if (token != TokenNameRPAREN) {
1561         throwSyntaxError("')' expected in function declaration.");
1562       } else {
1563         methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1564         getNextToken();
1565       }
1566     } else {
1567       methodDecl.selector = "<undefined>".toCharArray();
1568       throwSyntaxError("Function name expected after keyword 'function'.");
1569     }
1570   }
1571
1572   //
1573   private void parameter_list() {
1574     //  non_empty_parameter_list
1575     //  | /* empty */
1576     non_empty_parameter_list(true);
1577   }
1578
1579   private void non_empty_parameter_list(boolean empty_allowed) {
1580     //  optional_class_type T_VARIABLE
1581     //  | optional_class_type '&' T_VARIABLE
1582     //  | optional_class_type '&' T_VARIABLE '=' static_scalar
1583     //  | optional_class_type T_VARIABLE '=' static_scalar
1584     //  | non_empty_parameter_list ',' optional_class_type T_VARIABLE
1585     //  | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
1586     //  | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
1587     // static_scalar
1588     //  | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
1589     // static_scalar
1590     if (token == TokenNameIdentifier || token == TokenNameVariable || token == TokenNameAND) {
1591       while (true) {
1592         if (token == TokenNameIdentifier) {
1593           getNextToken();
1594         }
1595         if (token == TokenNameAND) {
1596           getNextToken();
1597         }
1598         if (token == TokenNameVariable) {
1599           getNextToken();
1600           if (token == TokenNameEQUAL) {
1601             getNextToken();
1602             static_scalar();
1603           }
1604         } else {
1605           throwSyntaxError("Variable expected in parameter list.");
1606         }
1607         if (token != TokenNameCOMMA) {
1608           break;
1609         }
1610         getNextToken();
1611       }
1612       return;
1613     }
1614     if (!empty_allowed) {
1615       throwSyntaxError("Identifier expected in parameter list.");
1616     }
1617   }
1618
1619   private void optional_class_type() {
1620     //  /* empty */
1621     //| T_STRING
1622   }
1623
1624   private void parameterDeclaration() {
1625     //variable
1626     //variable-reference
1627     if (token == TokenNameAND) {
1628       getNextToken();
1629       if (isVariable()) {
1630         getNextToken();
1631       } else {
1632         throwSyntaxError("Variable expected after reference operator '&'.");
1633       }
1634     }
1635     //variable '=' constant
1636     if (token == TokenNameVariable) {
1637       getNextToken();
1638       if (token == TokenNameEQUAL) {
1639         getNextToken();
1640         static_scalar();
1641       }
1642       return;
1643     }
1644     //    if (token == TokenNamethis) {
1645     //      throwSyntaxError("Reserved word '$this' not allowed in parameter
1646     // declaration.");
1647     //    }
1648   }
1649
1650   private void labeledStatementList() {
1651     if (token != TokenNamecase && token != TokenNamedefault) {
1652       throwSyntaxError("'case' or 'default' expected.");
1653     }
1654     do {
1655       if (token == TokenNamecase) {
1656         getNextToken();
1657         expr(); //constant();
1658         if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1659           getNextToken();
1660           if (token == TokenNamecase || token == TokenNamedefault) {
1661             // empty case statement ?
1662             continue;
1663           }
1664           statementList();
1665         }
1666         //        else if (token == TokenNameSEMICOLON) {
1667         //          setMarker(
1668         //            "':' expected after 'case' keyword (Found token: " +
1669         // scanner.toStringAction(token) + ")",
1670         //            scanner.getCurrentTokenStartPosition(),
1671         //            scanner.getCurrentTokenEndPosition(),
1672         //            INFO);
1673         //          getNextToken();
1674         //          if (token == TokenNamecase) { // empty case statement ?
1675         //            continue;
1676         //          }
1677         //          statementList();
1678         //        }
1679         else {
1680           throwSyntaxError("':' character expected after 'case' constant (Found token: " + scanner.toStringAction(token) + ")");
1681         }
1682       } else { // TokenNamedefault
1683         getNextToken();
1684         if (token == TokenNameCOLON) {
1685           getNextToken();
1686           if (token == TokenNameRBRACE) {
1687             // empty default case
1688             break;
1689           }
1690           if (token != TokenNamecase) {
1691             statementList();
1692           }
1693         } else {
1694           throwSyntaxError("':' character expected after 'default'.");
1695         }
1696       }
1697     } while (token == TokenNamecase || token == TokenNamedefault);
1698   }
1699
1700   //  public void labeledStatement() {
1701   //    if (token == TokenNamecase) {
1702   //      getNextToken();
1703   //      constant();
1704   //      if (token == TokenNameDDOT) {
1705   //        getNextToken();
1706   //        statement();
1707   //      } else {
1708   //        throwSyntaxError("':' character after 'case' constant expected.");
1709   //      }
1710   //      return;
1711   //    } else if (token == TokenNamedefault) {
1712   //      getNextToken();
1713   //      if (token == TokenNameDDOT) {
1714   //        getNextToken();
1715   //        statement();
1716   //      } else {
1717   //        throwSyntaxError("':' character after 'default' expected.");
1718   //      }
1719   //      return;
1720   //    }
1721   //  }
1722   //  public void expressionStatement() {
1723   //  }
1724   //  private void inclusionStatement() {
1725   //  }
1726   //  public void compoundStatement() {
1727   //  }
1728   //  public void selectionStatement() {
1729   //  }
1730   //
1731   //  public void iterationStatement() {
1732   //  }
1733   //
1734   //  public void jumpStatement() {
1735   //  }
1736   //
1737   //  public void outputStatement() {
1738   //  }
1739   //
1740   //  public void scopeStatement() {
1741   //  }
1742   //
1743   //  public void flowStatement() {
1744   //  }
1745   //
1746   //  public void definitionStatement() {
1747   //  }
1748   private void ifStatement() {
1749     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1750     if (token == TokenNameCOLON) {
1751       getNextToken();
1752       if (token != TokenNameendif) {
1753         statementList();
1754         switch (token) {
1755         case TokenNameelse:
1756           getNextToken();
1757           if (token == TokenNameCOLON) {
1758             getNextToken();
1759             if (token != TokenNameendif) {
1760               statementList();
1761             }
1762           } else {
1763             if (token == TokenNameif) { //'else if'
1764               getNextToken();
1765               elseifStatementList();
1766             } else {
1767               throwSyntaxError("':' expected after 'else'.");
1768             }
1769           }
1770           break;
1771         case TokenNameelseif:
1772           getNextToken();
1773           elseifStatementList();
1774           break;
1775         }
1776       }
1777       if (token != TokenNameendif) {
1778         throwSyntaxError("'endif' expected.");
1779       }
1780       getNextToken();
1781       if (token != TokenNameSEMICOLON) {
1782         throwSyntaxError("';' expected after if-statement.");
1783       }
1784       getNextToken();
1785     } else {
1786       // statement [else-statement]
1787       statement(TokenNameEOF);
1788       if (token == TokenNameelseif) {
1789         getNextToken();
1790         if (token == TokenNameLPAREN) {
1791           getNextToken();
1792         } else {
1793           throwSyntaxError("'(' expected after 'elseif' keyword.");
1794         }
1795         expr();
1796         if (token == TokenNameRPAREN) {
1797           getNextToken();
1798         } else {
1799           throwSyntaxError("')' expected after 'elseif' condition.");
1800         }
1801         ifStatement();
1802       } else if (token == TokenNameelse) {
1803         getNextToken();
1804         statement(TokenNameEOF);
1805       }
1806     }
1807   }
1808
1809   private void elseifStatementList() {
1810     do {
1811       elseifStatement();
1812       switch (token) {
1813       case TokenNameelse:
1814         getNextToken();
1815         if (token == TokenNameCOLON) {
1816           getNextToken();
1817           if (token != TokenNameendif) {
1818             statementList();
1819           }
1820           return;
1821         } else {
1822           if (token == TokenNameif) { //'else if'
1823             getNextToken();
1824           } else {
1825             throwSyntaxError("':' expected after 'else'.");
1826           }
1827         }
1828         break;
1829       case TokenNameelseif:
1830         getNextToken();
1831         break;
1832       default:
1833         return;
1834       }
1835     } while (true);
1836   }
1837
1838   private void elseifStatement() {
1839     if (token == TokenNameLPAREN) {
1840       getNextToken();
1841       expr();
1842       if (token != TokenNameRPAREN) {
1843         throwSyntaxError("')' expected in else-if-statement.");
1844       }
1845       getNextToken();
1846       if (token != TokenNameCOLON) {
1847         throwSyntaxError("':' expected in else-if-statement.");
1848       }
1849       getNextToken();
1850       if (token != TokenNameendif) {
1851         statementList();
1852       }
1853     }
1854   }
1855
1856   private void switchStatement() {
1857     if (token == TokenNameCOLON) {
1858       // ':' [labeled-statement-list] 'endswitch' ';'
1859       getNextToken();
1860       labeledStatementList();
1861       if (token != TokenNameendswitch) {
1862         throwSyntaxError("'endswitch' expected.");
1863       }
1864       getNextToken();
1865       if (token != TokenNameSEMICOLON) {
1866         throwSyntaxError("';' expected after switch-statement.");
1867       }
1868       getNextToken();
1869     } else {
1870       // '{' [labeled-statement-list] '}'
1871       if (token != TokenNameLBRACE) {
1872         throwSyntaxError("'{' expected in switch statement.");
1873       }
1874       getNextToken();
1875       if (token != TokenNameRBRACE) {
1876         labeledStatementList();
1877       }
1878       if (token != TokenNameRBRACE) {
1879         throwSyntaxError("'}' expected in switch statement.");
1880       }
1881       getNextToken();
1882     }
1883   }
1884
1885   private void forStatement() {
1886     if (token == TokenNameCOLON) {
1887       getNextToken();
1888       statementList();
1889       if (token != TokenNameendfor) {
1890         throwSyntaxError("'endfor' expected.");
1891       }
1892       getNextToken();
1893       if (token != TokenNameSEMICOLON) {
1894         throwSyntaxError("';' expected after for-statement.");
1895       }
1896       getNextToken();
1897     } else {
1898       statement(TokenNameEOF);
1899     }
1900   }
1901
1902   private void whileStatement() {
1903     // ':' statement-list 'endwhile' ';'
1904     if (token == TokenNameCOLON) {
1905       getNextToken();
1906       statementList();
1907       if (token != TokenNameendwhile) {
1908         throwSyntaxError("'endwhile' expected.");
1909       }
1910       getNextToken();
1911       if (token != TokenNameSEMICOLON) {
1912         throwSyntaxError("';' expected after while-statement.");
1913       }
1914       getNextToken();
1915     } else {
1916       statement(TokenNameEOF);
1917     }
1918   }
1919
1920   private void foreachStatement() {
1921     if (token == TokenNameCOLON) {
1922       getNextToken();
1923       statementList();
1924       if (token != TokenNameendforeach) {
1925         throwSyntaxError("'endforeach' expected.");
1926       }
1927       getNextToken();
1928       if (token != TokenNameSEMICOLON) {
1929         throwSyntaxError("';' expected after foreach-statement.");
1930       }
1931       getNextToken();
1932     } else {
1933       statement(TokenNameEOF);
1934     }
1935   }
1936
1937   //  private void exitStatus() {
1938   //    if (token == TokenNameLPAREN) {
1939   //      getNextToken();
1940   //    } else {
1941   //      throwSyntaxError("'(' expected in 'exit-status'.");
1942   //    }
1943   //    if (token != TokenNameRPAREN) {
1944   //      expression();
1945   //    }
1946   //    if (token == TokenNameRPAREN) {
1947   //      getNextToken();
1948   //    } else {
1949   //      throwSyntaxError("')' expected after 'exit-status'.");
1950   //    }
1951   //  }
1952   private void expressionList() {
1953     do {
1954       expr();
1955       if (token == TokenNameCOMMA) {
1956         getNextToken();
1957       } else {
1958         break;
1959       }
1960     } while (true);
1961   }
1962
1963   private Expression expr() {
1964     //  r_variable
1965     //  | expr_without_variable
1966     //    if (token!=TokenNameEOF) {
1967     if (Scanner.TRACE) {
1968       System.out.println("TRACE: expr()");
1969     }
1970     return expr_without_variable(true);
1971     //    }
1972   }
1973
1974   private Expression expr_without_variable(boolean only_variable) {
1975     int exprSourceStart = scanner.getCurrentTokenStartPosition();
1976     int exprSourceEnd = scanner.getCurrentTokenEndPosition();
1977     Expression expression = new Expression();
1978     expression.sourceStart = exprSourceStart;
1979     // default, may be overwritten
1980     expression.sourceEnd = exprSourceEnd;
1981     //          internal_functions_in_yacc
1982     //  | T_CLONE expr
1983     //  | T_PRINT expr
1984     //  | '(' expr ')'
1985     //  | '@' expr
1986     //  | '+' expr
1987     //  | '-' expr
1988     //  | '!' expr
1989     //  | '~' expr
1990     //  | T_INC rw_variable
1991     //  | T_DEC rw_variable
1992     //  | T_INT_CAST expr
1993     //  | T_DOUBLE_CAST expr
1994     //  | T_STRING_CAST expr
1995     //  | T_ARRAY_CAST expr
1996     //  | T_OBJECT_CAST expr
1997     //  | T_BOOL_CAST expr
1998     //  | T_UNSET_CAST expr
1999     //  | T_EXIT exit_expr
2000     //  | scalar
2001     //  | T_ARRAY '(' array_pair_list ')'
2002     //  | '`' encaps_list '`'
2003     //  | T_LIST '(' assignment_list ')' '=' expr
2004     //  | T_NEW class_name_reference ctor_arguments
2005     //  | variable '=' expr
2006     //  | variable '=' '&' variable
2007     //  | variable '=' '&' T_NEW class_name_reference ctor_arguments
2008     //  | variable T_PLUS_EQUAL expr
2009     //  | variable T_MINUS_EQUAL expr
2010     //  | variable T_MUL_EQUAL expr
2011     //  | variable T_DIV_EQUAL expr
2012     //  | variable T_CONCAT_EQUAL expr
2013     //  | variable T_MOD_EQUAL expr
2014     //  | variable T_AND_EQUAL expr
2015     //  | variable T_OR_EQUAL expr
2016     //  | variable T_XOR_EQUAL expr
2017     //  | variable T_SL_EQUAL expr
2018     //  | variable T_SR_EQUAL expr
2019     //  | rw_variable T_INC
2020     //  | rw_variable T_DEC
2021     //  | expr T_BOOLEAN_OR expr
2022     //  | expr T_BOOLEAN_AND expr
2023     //  | expr T_LOGICAL_OR expr
2024     //  | expr T_LOGICAL_AND expr
2025     //  | expr T_LOGICAL_XOR expr
2026     //  | expr '|' expr
2027     //  | expr '&' expr
2028     //  | expr '^' expr
2029     //  | expr '.' expr
2030     //  | expr '+' expr
2031     //  | expr '-' expr
2032     //  | expr '*' expr
2033     //  | expr '/' expr
2034     //  | expr '%' expr
2035     //  | expr T_SL expr
2036     //  | expr T_SR expr
2037     //  | expr T_IS_IDENTICAL expr
2038     //  | expr T_IS_NOT_IDENTICAL expr
2039     //  | expr T_IS_EQUAL expr
2040     //  | expr T_IS_NOT_EQUAL expr
2041     //  | expr '<' expr
2042     //  | expr T_IS_SMALLER_OR_EQUAL expr
2043     //  | expr '>' expr
2044     //  | expr T_IS_GREATER_OR_EQUAL expr
2045     //  | expr T_INSTANCEOF class_name_reference
2046     //  | expr '?' expr ':' expr
2047     if (Scanner.TRACE) {
2048       System.out.println("TRACE: expr_without_variable() PART 1");
2049     }
2050     switch (token) {
2051     case TokenNameisset:
2052     case TokenNameempty:
2053     case TokenNameeval:
2054     case TokenNameinclude:
2055     case TokenNameinclude_once:
2056     case TokenNamerequire:
2057     case TokenNamerequire_once:
2058       internal_functions_in_yacc();
2059       break;
2060     //          | '(' expr ')'
2061     case TokenNameLPAREN:
2062       getNextToken();
2063       expr();
2064       if (token == TokenNameRPAREN) {
2065         getNextToken();
2066       } else {
2067         throwSyntaxError("')' expected in expression.");
2068       }
2069       break;
2070     //    | T_CLONE expr
2071     //    | T_PRINT expr
2072     //    | '@' expr
2073     //    | '+' expr
2074     //    | '-' expr
2075     //    | '!' expr
2076     //    | '~' expr
2077     //    | T_INT_CAST expr
2078     //  | T_DOUBLE_CAST expr
2079     //  | T_STRING_CAST expr
2080     //  | T_ARRAY_CAST expr
2081     //  | T_OBJECT_CAST expr
2082     //  | T_BOOL_CAST expr
2083     //  | T_UNSET_CAST expr
2084     case TokenNameclone:
2085     case TokenNameprint:
2086     case TokenNameAT:
2087     case TokenNamePLUS:
2088     case TokenNameMINUS:
2089     case TokenNameNOT:
2090     case TokenNameTWIDDLE:
2091     case TokenNameintCAST:
2092     case TokenNamedoubleCAST:
2093     case TokenNamestringCAST:
2094     case TokenNamearrayCAST:
2095     case TokenNameobjectCAST:
2096     case TokenNameboolCAST:
2097     case TokenNameunsetCAST:
2098       getNextToken();
2099       expr();
2100       break;
2101     case TokenNameexit:
2102       getNextToken();
2103       exit_expr();
2104       break;
2105     //  scalar:
2106     //  T_STRING
2107     //| T_STRING_VARNAME
2108     //| class_constant
2109     //| T_START_HEREDOC encaps_list T_END_HEREDOC
2110     //          | '`' encaps_list '`'
2111     //  | common_scalar
2112     //  | '`' encaps_list '`'
2113     case TokenNameEncapsedString0:
2114       scanner.encapsedStringStack.push(new Character('`'));
2115       getNextToken();
2116       try {
2117         if (token == TokenNameEncapsedString0) {
2118         } else {
2119           encaps_list();
2120           if (token != TokenNameEncapsedString0) {
2121             throwSyntaxError("\'`\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2122           }
2123         }
2124       } finally {
2125         scanner.encapsedStringStack.pop();
2126         getNextToken();
2127       }
2128       break;
2129     //      | '\'' encaps_list '\''
2130     case TokenNameEncapsedString1:
2131       scanner.encapsedStringStack.push(new Character('\''));
2132       getNextToken();
2133       try {
2134         exprSourceStart = scanner.getCurrentTokenStartPosition();
2135         if (token == TokenNameEncapsedString1) {
2136           expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
2137               .getCurrentTokenEndPosition());
2138         } else {
2139           encaps_list();
2140           if (token != TokenNameEncapsedString1) {
2141             throwSyntaxError("\'\'\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2142           } else {
2143             expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
2144                 .getCurrentTokenEndPosition());
2145           }
2146         }
2147       } finally {
2148         scanner.encapsedStringStack.pop();
2149         getNextToken();
2150       }
2151       break;
2152     //| '"' encaps_list '"'
2153     case TokenNameEncapsedString2:
2154       scanner.encapsedStringStack.push(new Character('"'));
2155       getNextToken();
2156       try {
2157         exprSourceStart = scanner.getCurrentTokenStartPosition();
2158         if (token == TokenNameEncapsedString2) {
2159           expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
2160               .getCurrentTokenEndPosition());
2161         } else {
2162           encaps_list();
2163           if (token != TokenNameEncapsedString2) {
2164             throwSyntaxError("'\"' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2165           } else {
2166             expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
2167                 .getCurrentTokenEndPosition());
2168           }
2169         }
2170       } finally {
2171         scanner.encapsedStringStack.pop();
2172         getNextToken();
2173       }
2174       break;
2175     case TokenNameStringDoubleQuote:
2176       expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(), scanner.getCurrentTokenStartPosition(), scanner
2177           .getCurrentTokenEndPosition());
2178       common_scalar();
2179       break;
2180     case TokenNameStringSingleQuote:
2181       expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(), scanner.getCurrentTokenStartPosition(), scanner
2182           .getCurrentTokenEndPosition());
2183       common_scalar();
2184       break;
2185     case TokenNameIntegerLiteral:
2186     case TokenNameDoubleLiteral:
2187     case TokenNameStringInterpolated:
2188     case TokenNameFILE:
2189     case TokenNameLINE:
2190     case TokenNameCLASS_C:
2191     case TokenNameMETHOD_C:
2192     case TokenNameFUNC_C:
2193       common_scalar();
2194       break;
2195     case TokenNameHEREDOC:
2196       getNextToken();
2197       break;
2198     case TokenNamearray:
2199       //    T_ARRAY '(' array_pair_list ')'
2200       getNextToken();
2201       if (token == TokenNameLPAREN) {
2202         getNextToken();
2203         if (token == TokenNameRPAREN) {
2204           getNextToken();
2205           break;
2206         }
2207         array_pair_list();
2208         if (token != TokenNameRPAREN) {
2209           throwSyntaxError("')' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2210         }
2211         getNextToken();
2212       } else {
2213         throwSyntaxError("'(' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2214       }
2215       break;
2216     case TokenNamelist:
2217       //    | T_LIST '(' assignment_list ')' '=' expr
2218       getNextToken();
2219       if (token == TokenNameLPAREN) {
2220         getNextToken();
2221         assignment_list();
2222         if (token != TokenNameRPAREN) {
2223           throwSyntaxError("')' expected after 'list' keyword.");
2224         }
2225         getNextToken();
2226         if (token != TokenNameEQUAL) {
2227           throwSyntaxError("'=' expected after 'list' keyword.");
2228         }
2229         getNextToken();
2230         expr();
2231       } else {
2232         throwSyntaxError("'(' expected after 'list' keyword.");
2233       }
2234       break;
2235     case TokenNamenew:
2236       //        | T_NEW class_name_reference ctor_arguments
2237       getNextToken();
2238       class_name_reference();
2239       ctor_arguments();
2240       break;
2241     //          | T_INC rw_variable
2242     //          | T_DEC rw_variable
2243     case TokenNamePLUS_PLUS:
2244     case TokenNameMINUS_MINUS:
2245       getNextToken();
2246       rw_variable();
2247       break;
2248     //  | variable '=' expr
2249     //  | variable '=' '&' variable
2250     //  | variable '=' '&' T_NEW class_name_reference ctor_arguments
2251     //  | variable T_PLUS_EQUAL expr
2252     //  | variable T_MINUS_EQUAL expr
2253     //  | variable T_MUL_EQUAL expr
2254     //  | variable T_DIV_EQUAL expr
2255     //  | variable T_CONCAT_EQUAL expr
2256     //  | variable T_MOD_EQUAL expr
2257     //  | variable T_AND_EQUAL expr
2258     //  | variable T_OR_EQUAL expr
2259     //  | variable T_XOR_EQUAL expr
2260     //  | variable T_SL_EQUAL expr
2261     //  | variable T_SR_EQUAL expr
2262     //  | rw_variable T_INC
2263     //  | rw_variable T_DEC
2264     case TokenNameIdentifier:
2265     case TokenNameVariable:
2266     case TokenNameDOLLAR:
2267       variable();
2268       switch (token) {
2269       case TokenNameEQUAL:
2270         getNextToken();
2271         if (token == TokenNameAND) {
2272           getNextToken();
2273           if (token == TokenNamenew) {
2274             // | variable '=' '&' T_NEW class_name_reference
2275             // ctor_arguments
2276             getNextToken();
2277             class_name_reference();
2278             ctor_arguments();
2279           } else {
2280             variable();
2281           }
2282         } else {
2283           expr();
2284         }
2285         break;
2286       case TokenNamePLUS_EQUAL:
2287       case TokenNameMINUS_EQUAL:
2288       case TokenNameMULTIPLY_EQUAL:
2289       case TokenNameDIVIDE_EQUAL:
2290       case TokenNameDOT_EQUAL:
2291       case TokenNameREMAINDER_EQUAL:
2292       case TokenNameAND_EQUAL:
2293       case TokenNameOR_EQUAL:
2294       case TokenNameXOR_EQUAL:
2295       case TokenNameRIGHT_SHIFT_EQUAL:
2296       case TokenNameLEFT_SHIFT_EQUAL:
2297         getNextToken();
2298         expr();
2299         break;
2300       case TokenNamePLUS_PLUS:
2301       case TokenNameMINUS_MINUS:
2302         getNextToken();
2303         break;
2304       default:
2305         if (!only_variable) {
2306           throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "').");
2307         }
2308       }
2309       break;
2310     default:
2311       if (token != TokenNameINLINE_HTML) {
2312         if (token > TokenNameKEYWORD) {
2313           getNextToken();
2314           break;
2315         } else {
2316           throwSyntaxError("Error in expression (found token '" + scanner.toStringAction(token) + "').");
2317         }
2318       }
2319       return expression;
2320     }
2321     if (Scanner.TRACE) {
2322       System.out.println("TRACE: expr_without_variable() PART 2");
2323     }
2324     //  | expr T_BOOLEAN_OR expr
2325     //  | expr T_BOOLEAN_AND expr
2326     //  | expr T_LOGICAL_OR expr
2327     //  | expr T_LOGICAL_AND expr
2328     //  | expr T_LOGICAL_XOR expr
2329     //  | expr '|' expr
2330     //  | expr '&' expr
2331     //  | expr '^' expr
2332     //  | expr '.' expr
2333     //  | expr '+' expr
2334     //  | expr '-' expr
2335     //  | expr '*' expr
2336     //  | expr '/' expr
2337     //  | expr '%' expr
2338     //  | expr T_SL expr
2339     //  | expr T_SR expr
2340     //  | expr T_IS_IDENTICAL expr
2341     //  | expr T_IS_NOT_IDENTICAL expr
2342     //  | expr T_IS_EQUAL expr
2343     //  | expr T_IS_NOT_EQUAL expr
2344     //  | expr '<' expr
2345     //  | expr T_IS_SMALLER_OR_EQUAL expr
2346     //  | expr '>' expr
2347     //  | expr T_IS_GREATER_OR_EQUAL expr
2348     while (true) {
2349       switch (token) {
2350       case TokenNameOR_OR:
2351         getNextToken();
2352         expression = new OR_OR_Expression(expression, expr(), token);
2353         break;
2354       case TokenNameAND_AND:
2355         getNextToken();
2356         expression = new AND_AND_Expression(expression, expr(), token);
2357         break;
2358       case TokenNameEQUAL_EQUAL:
2359         getNextToken();
2360         expression = new EqualExpression(expression, expr(), token);
2361         break;
2362       case TokenNameand:
2363       case TokenNameor:
2364       case TokenNamexor:
2365       case TokenNameAND:
2366       case TokenNameOR:
2367       case TokenNameXOR:
2368       case TokenNameDOT:
2369       case TokenNamePLUS:
2370       case TokenNameMINUS:
2371       case TokenNameMULTIPLY:
2372       case TokenNameDIVIDE:
2373       case TokenNameREMAINDER:
2374       case TokenNameLEFT_SHIFT:
2375       case TokenNameRIGHT_SHIFT:
2376       case TokenNameEQUAL_EQUAL_EQUAL:
2377       case TokenNameNOT_EQUAL_EQUAL:
2378       case TokenNameNOT_EQUAL:
2379       case TokenNameLESS:
2380       case TokenNameLESS_EQUAL:
2381       case TokenNameGREATER:
2382       case TokenNameGREATER_EQUAL:
2383         getNextToken();
2384         expression = new BinaryExpression(expression, expr(), token);
2385         break;
2386       //  | expr T_INSTANCEOF class_name_reference
2387       //        | expr '?' expr ':' expr
2388       case TokenNameinstanceof:
2389         getNextToken();
2390         class_name_reference();
2391         // TODO use InstanceofExpression
2392         expression = new Expression();
2393         expression.sourceStart = exprSourceStart;
2394         expression.sourceEnd = scanner.getCurrentTokenEndPosition();
2395         break;
2396       case TokenNameQUESTION:
2397         getNextToken();
2398         Expression valueIfTrue = expr();
2399         if (token != TokenNameCOLON) {
2400           throwSyntaxError("':' expected in conditional expression.");
2401         }
2402         getNextToken();
2403         Expression valueIfFalse = expr();
2404
2405         expression = new ConditionalExpression(expression, valueIfTrue, valueIfFalse);
2406         break;
2407       default:
2408         return expression;
2409       }
2410     }
2411   }
2412
2413   private void class_name_reference() {
2414     //  class_name_reference:
2415     //  T_STRING
2416     //| dynamic_class_name_reference
2417     if (Scanner.TRACE) {
2418       System.out.println("TRACE: class_name_reference()");
2419     }
2420     if (token == TokenNameIdentifier) {
2421       getNextToken();
2422     } else {
2423       dynamic_class_name_reference();
2424     }
2425   }
2426
2427   private void dynamic_class_name_reference() {
2428     //dynamic_class_name_reference:
2429     //  base_variable T_OBJECT_OPERATOR object_property
2430     // dynamic_class_name_variable_properties
2431     //| base_variable
2432     if (Scanner.TRACE) {
2433       System.out.println("TRACE: dynamic_class_name_reference()");
2434     }
2435     base_variable();
2436     if (token == TokenNameMINUS_GREATER) {
2437       getNextToken();
2438       object_property();
2439       dynamic_class_name_variable_properties();
2440     }
2441   }
2442
2443   private void dynamic_class_name_variable_properties() {
2444     //  dynamic_class_name_variable_properties:
2445     //                  dynamic_class_name_variable_properties
2446     // dynamic_class_name_variable_property
2447     //          | /* empty */
2448     if (Scanner.TRACE) {
2449       System.out.println("TRACE: dynamic_class_name_variable_properties()");
2450     }
2451     while (token == TokenNameMINUS_GREATER) {
2452       dynamic_class_name_variable_property();
2453     }
2454   }
2455
2456   private void dynamic_class_name_variable_property() {
2457     //  dynamic_class_name_variable_property:
2458     //  T_OBJECT_OPERATOR object_property
2459     if (Scanner.TRACE) {
2460       System.out.println("TRACE: dynamic_class_name_variable_property()");
2461     }
2462     if (token == TokenNameMINUS_GREATER) {
2463       getNextToken();
2464       object_property();
2465     }
2466   }
2467
2468   private void ctor_arguments() {
2469     //  ctor_arguments:
2470     //  /* empty */
2471     //| '(' function_call_parameter_list ')'
2472     if (token == TokenNameLPAREN) {
2473       getNextToken();
2474       if (token == TokenNameRPAREN) {
2475         getNextToken();
2476         return;
2477       }
2478       non_empty_function_call_parameter_list();
2479       if (token != TokenNameRPAREN) {
2480         throwSyntaxError("')' expected in ctor_arguments.");
2481       }
2482       getNextToken();
2483     }
2484   }
2485
2486   private void assignment_list() {
2487     //  assignment_list:
2488     //  assignment_list ',' assignment_list_element
2489     //| assignment_list_element
2490     while (true) {
2491       assignment_list_element();
2492       if (token != TokenNameCOMMA) {
2493         break;
2494       }
2495       getNextToken();
2496     }
2497   }
2498
2499   private void assignment_list_element() {
2500     //assignment_list_element:
2501     //  variable
2502     //| T_LIST '(' assignment_list ')'
2503     //| /* empty */
2504     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2505       variable();
2506     } else {
2507       if (token == TokenNamelist) {
2508         getNextToken();
2509         if (token == TokenNameLPAREN) {
2510           getNextToken();
2511           assignment_list();
2512           if (token != TokenNameRPAREN) {
2513             throwSyntaxError("')' expected after 'list' keyword.");
2514           }
2515           getNextToken();
2516         } else {
2517           throwSyntaxError("'(' expected after 'list' keyword.");
2518         }
2519       }
2520     }
2521   }
2522
2523   private void array_pair_list() {
2524     //  array_pair_list:
2525     //  /* empty */
2526     //| non_empty_array_pair_list possible_comma
2527     non_empty_array_pair_list();
2528     if (token == TokenNameCOMMA) {
2529       getNextToken();
2530     }
2531   }
2532
2533   private void non_empty_array_pair_list() {
2534     //non_empty_array_pair_list:
2535     //  non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2536     //| non_empty_array_pair_list ',' expr
2537     //| expr T_DOUBLE_ARROW expr
2538     //| expr
2539     //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2540     //| non_empty_array_pair_list ',' '&' w_variable
2541     //| expr T_DOUBLE_ARROW '&' w_variable
2542     //| '&' w_variable
2543     while (true) {
2544       if (token == TokenNameAND) {
2545         getNextToken();
2546         variable();
2547       } else {
2548         expr();
2549         if (token == TokenNameAND) {
2550           getNextToken();
2551           variable();
2552         } else if (token == TokenNameEQUAL_GREATER) {
2553           getNextToken();
2554           if (token == TokenNameAND) {
2555             getNextToken();
2556             variable();
2557           } else {
2558             expr();
2559           }
2560         }
2561       }
2562       if (token != TokenNameCOMMA) {
2563         return;
2564       }
2565       getNextToken();
2566       if (token == TokenNameRPAREN) {
2567         return;
2568       }
2569     }
2570   }
2571
2572   //  private void variableList() {
2573   //    do {
2574   //      variable();
2575   //      if (token == TokenNameCOMMA) {
2576   //        getNextToken();
2577   //      } else {
2578   //        break;
2579   //      }
2580   //    } while (true);
2581   //  }
2582   private void variable_without_objects() {
2583     //  variable_without_objects:
2584     //                  reference_variable
2585     //          | simple_indirect_reference reference_variable
2586     if (Scanner.TRACE) {
2587       System.out.println("TRACE: variable_without_objects()");
2588     }
2589     while (token == TokenNameDOLLAR) {
2590       getNextToken();
2591     }
2592     reference_variable();
2593   }
2594
2595   private void function_call() {
2596     //  function_call:
2597     //  T_STRING '(' function_call_parameter_list ')'
2598     //| class_constant '(' function_call_parameter_list ')'
2599     //| static_member '(' function_call_parameter_list ')'
2600     //| variable_without_objects '(' function_call_parameter_list ')'
2601     char[] defineName = null;
2602     char[] ident = null;
2603     int startPos = 0;
2604     int endPos = 0;
2605     if (Scanner.TRACE) {
2606       System.out.println("TRACE: function_call()");
2607     }
2608     if (token == TokenNameIdentifier) {
2609       ident = scanner.getCurrentIdentifierSource();
2610       defineName = ident;
2611       startPos = scanner.getCurrentTokenStartPosition();
2612       endPos = scanner.getCurrentTokenEndPosition();
2613       getNextToken();
2614       switch (token) {
2615       case TokenNamePAAMAYIM_NEKUDOTAYIM:
2616         // static member:
2617         defineName = null;
2618         getNextToken();
2619         if (token == TokenNameIdentifier) {
2620           // class _constant
2621           getNextToken();
2622         } else {
2623           //        static member:
2624           variable_without_objects();
2625         }
2626         break;
2627       }
2628     } else {
2629       variable_without_objects();
2630     }
2631     if (token != TokenNameLPAREN) {
2632       if (defineName != null) {
2633         // does this identifier contain only uppercase characters?
2634         if (defineName.length == 3) {
2635           if (defineName[0] == 'd' && defineName[1] == 'i' && defineName[2] == 'e') {
2636             defineName = null;
2637           }
2638         } else if (defineName.length == 4) {
2639           if (defineName[0] == 't' && defineName[1] == 'r' && defineName[2] == 'u' && defineName[3] == 'e') {
2640             defineName = null;
2641           } else if (defineName[0] == 'n' && defineName[1] == 'u' && defineName[2] == 'l' && defineName[3] == 'l') {
2642             defineName = null;
2643           }
2644         } else if (defineName.length == 5) {
2645           if (defineName[0] == 'f' && defineName[1] == 'a' && defineName[2] == 'l' && defineName[3] == 's' && defineName[4] == 'e') {
2646             defineName = null;
2647           }
2648         }
2649         if (defineName != null) {
2650           for (int i = 0; i < defineName.length; i++) {
2651             if (Character.isLowerCase(defineName[i])) {
2652               problemReporter.phpUppercaseIdentifierWarning(startPos, endPos, referenceContext, compilationUnit.compilationResult);
2653               break;
2654             }
2655           }
2656         }
2657       }
2658       // TODO is this ok ?
2659       return;
2660       //      throwSyntaxError("'(' expected in function call.");
2661     }
2662     getNextToken();
2663     if (token == TokenNameRPAREN) {
2664       getNextToken();
2665       return;
2666     }
2667     non_empty_function_call_parameter_list();
2668     if (token != TokenNameRPAREN) {
2669       String functionName;
2670       if (ident == null) {
2671         functionName = new String(" ");
2672       } else {
2673         functionName = new String(ident);
2674       }
2675       throwSyntaxError("')' expected in function call (" + functionName + ").");
2676     }
2677     getNextToken();
2678   }
2679
2680   //  private void function_call_parameter_list() {
2681   //    function_call_parameter_list:
2682   //            non_empty_function_call_parameter_list { $$ = $1; }
2683   //    | /* empty */
2684   //  }
2685   private void non_empty_function_call_parameter_list() {
2686     //non_empty_function_call_parameter_list:
2687     //          expr_without_variable
2688     //  | variable
2689     //  | '&' w_variable
2690     //  | non_empty_function_call_parameter_list ',' expr_without_variable
2691     //  | non_empty_function_call_parameter_list ',' variable
2692     //  | non_empty_function_call_parameter_list ',' '&' w_variable
2693     if (Scanner.TRACE) {
2694       System.out.println("TRACE: non_empty_function_call_parameter_list()");
2695     }
2696     while (true) {
2697       if (token == TokenNameAND) {
2698         getNextToken();
2699         w_variable();
2700       } else {
2701         //        if (token == TokenNameIdentifier || token ==
2702         // TokenNameVariable
2703         //            || token == TokenNameDOLLAR) {
2704         //          variable();
2705         //        } else {
2706         expr_without_variable(true);
2707         //        }
2708       }
2709       if (token != TokenNameCOMMA) {
2710         break;
2711       }
2712       getNextToken();
2713     }
2714   }
2715
2716   private void fully_qualified_class_name() {
2717     if (token == TokenNameIdentifier) {
2718       getNextToken();
2719     } else {
2720       throwSyntaxError("Class name expected.");
2721     }
2722   }
2723
2724   private void static_member() {
2725     //  static_member:
2726     //  fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
2727     // variable_without_objects
2728     if (Scanner.TRACE) {
2729       System.out.println("TRACE: static_member()");
2730     }
2731     fully_qualified_class_name();
2732     if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
2733       throwSyntaxError("'::' expected after class name (static_member).");
2734     }
2735     getNextToken();
2736     variable_without_objects();
2737   }
2738
2739   private void base_variable_with_function_calls() {
2740     //  base_variable_with_function_calls:
2741     //  base_variable
2742     //| function_call
2743     boolean functionCall = false;
2744     if (Scanner.TRACE) {
2745       System.out.println("TRACE: base_variable_with_function_calls()");
2746     }
2747     //    if (token == TokenNameIdentifier) {
2748     //      functionCall = true;
2749     //    } else if (token == TokenNameVariable) {
2750     //      int tempToken = token;
2751     //      int tempPosition = scanner.currentPosition;
2752     //      getNextToken();
2753     //      if (token == TokenNameLPAREN) {
2754     //        functionCall = true;
2755     //      }
2756     //      token = tempToken;
2757     //      scanner.currentPosition = tempPosition;
2758     //      scanner.phpMode = true;
2759     //    }
2760     //    if (functionCall) {
2761     function_call();
2762     //    } else {
2763     //      base_variable();
2764     //    }
2765   }
2766
2767   private void base_variable() {
2768     //  base_variable:
2769     //                  reference_variable
2770     //          | simple_indirect_reference reference_variable
2771     //          | static_member
2772     if (Scanner.TRACE) {
2773       System.out.println("TRACE: base_variable()");
2774     }
2775     if (token == TokenNameIdentifier) {
2776       static_member();
2777     } else {
2778       while (token == TokenNameDOLLAR) {
2779         getNextToken();
2780       }
2781       reference_variable();
2782     }
2783   }
2784
2785   //  private void simple_indirect_reference() {
2786   //    // simple_indirect_reference:
2787   //    // '$'
2788   //    //| simple_indirect_reference '$'
2789   //  }
2790   private void reference_variable() {
2791     //  reference_variable:
2792     //                  reference_variable '[' dim_offset ']'
2793     //          | reference_variable '{' expr '}'
2794     //          | compound_variable
2795     if (Scanner.TRACE) {
2796       System.out.println("TRACE: reference_variable()");
2797     }
2798     compound_variable();
2799     while (true) {
2800       if (token == TokenNameLBRACE) {
2801         getNextToken();
2802         expr();
2803         if (token != TokenNameRBRACE) {
2804           throwSyntaxError("'}' expected in reference variable.");
2805         }
2806         getNextToken();
2807       } else if (token == TokenNameLBRACKET) {
2808         getNextToken();
2809         if (token != TokenNameRBRACKET) {
2810           expr();
2811           //        dim_offset();
2812           if (token != TokenNameRBRACKET) {
2813             throwSyntaxError("']' expected in reference variable.");
2814           }
2815         }
2816         getNextToken();
2817       } else {
2818         break;
2819       }
2820     }
2821   }
2822
2823   private void compound_variable() {
2824     //  compound_variable:
2825     //                  T_VARIABLE
2826     //          | '$' '{' expr '}'
2827     if (Scanner.TRACE) {
2828       System.out.println("TRACE: compound_variable()");
2829     }
2830     if (token == TokenNameVariable) {
2831       getNextToken();
2832     } else {
2833       // because of simple_indirect_reference
2834       while (token == TokenNameDOLLAR) {
2835         getNextToken();
2836       }
2837       if (token != TokenNameLBRACE) {
2838         throwSyntaxError("'{' expected after compound variable token '$'.");
2839       }
2840       getNextToken();
2841       expr();
2842       if (token != TokenNameRBRACE) {
2843         throwSyntaxError("'}' expected after compound variable token '$'.");
2844       }
2845       getNextToken();
2846     }
2847   }
2848
2849   //  private void dim_offset() {
2850   //    // dim_offset:
2851   //    // /* empty */
2852   //    // | expr
2853   //    expr();
2854   //  }
2855   private void object_property() {
2856     //  object_property:
2857     //  object_dim_list
2858     //| variable_without_objects
2859     if (Scanner.TRACE) {
2860       System.out.println("TRACE: object_property()");
2861     }
2862     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2863       variable_without_objects();
2864     } else {
2865       object_dim_list();
2866     }
2867   }
2868
2869   private void object_dim_list() {
2870     //object_dim_list:
2871     //  object_dim_list '[' dim_offset ']'
2872     //| object_dim_list '{' expr '}'
2873     //| variable_name
2874     if (Scanner.TRACE) {
2875       System.out.println("TRACE: object_dim_list()");
2876     }
2877     variable_name();
2878     while (true) {
2879       if (token == TokenNameLBRACE) {
2880         getNextToken();
2881         expr();
2882         if (token != TokenNameRBRACE) {
2883           throwSyntaxError("'}' expected in object_dim_list.");
2884         }
2885         getNextToken();
2886       } else if (token == TokenNameLBRACKET) {
2887         getNextToken();
2888         if (token == TokenNameRBRACKET) {
2889           getNextToken();
2890           continue;
2891         }
2892         expr();
2893         if (token != TokenNameRBRACKET) {
2894           throwSyntaxError("']' expected in object_dim_list.");
2895         }
2896         getNextToken();
2897       } else {
2898         break;
2899       }
2900     }
2901   }
2902
2903   private void variable_name() {
2904     //variable_name:
2905     //  T_STRING
2906     //| '{' expr '}'
2907     if (Scanner.TRACE) {
2908       System.out.println("TRACE: variable_name()");
2909     }
2910     if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
2911       if (token > TokenNameKEYWORD) {
2912         // TODO show a warning "Keyword used as variable" ?
2913       }
2914       getNextToken();
2915     } else {
2916       if (token != TokenNameLBRACE) {
2917         throwSyntaxError("'{' expected in variable name.");
2918       }
2919       getNextToken();
2920       expr();
2921       if (token != TokenNameRBRACE) {
2922         throwSyntaxError("'}' expected in variable name.");
2923       }
2924       getNextToken();
2925     }
2926   }
2927
2928   private void r_variable() {
2929     variable();
2930   }
2931
2932   private void w_variable() {
2933     variable();
2934   }
2935
2936   private void rw_variable() {
2937     variable();
2938   }
2939
2940   private void variable() {
2941     //    variable:
2942     //          base_variable_with_function_calls T_OBJECT_OPERATOR
2943     //                  object_property method_or_not variable_properties
2944     //  | base_variable_with_function_calls
2945     base_variable_with_function_calls();
2946     if (token == TokenNameMINUS_GREATER) {
2947       getNextToken();
2948       object_property();
2949       method_or_not();
2950       variable_properties();
2951     }
2952     //    if (token == TokenNameDOLLAR_LBRACE) {
2953     //      getNextToken();
2954     //      expr();
2955     //      ;
2956     //      if (token != TokenNameRBRACE) {
2957     //        throwSyntaxError("'}' expected after indirect variable token '${'.");
2958     //      }
2959     //      getNextToken();
2960     //    } else {
2961     //      if (token == TokenNameVariable) {
2962     //        getNextToken();
2963     //        if (token == TokenNameLBRACKET) {
2964     //          getNextToken();
2965     //          expr();
2966     //          if (token != TokenNameRBRACKET) {
2967     //            throwSyntaxError("']' expected in variable-list.");
2968     //          }
2969     //          getNextToken();
2970     //        } else if (token == TokenNameEQUAL) {
2971     //          getNextToken();
2972     //          static_scalar();
2973     //        }
2974     //      } else {
2975     //        throwSyntaxError("$-variable expected in variable-list.");
2976     //      }
2977     //    }
2978   }
2979
2980   private void variable_properties() {
2981     //  variable_properties:
2982     //                  variable_properties variable_property
2983     //          | /* empty */
2984     while (token == TokenNameMINUS_GREATER) {
2985       variable_property();
2986     }
2987   }
2988
2989   private void variable_property() {
2990     //  variable_property:
2991     //                  T_OBJECT_OPERATOR object_property method_or_not
2992     if (Scanner.TRACE) {
2993       System.out.println("TRACE: variable_property()");
2994     }
2995     if (token == TokenNameMINUS_GREATER) {
2996       getNextToken();
2997       object_property();
2998       method_or_not();
2999     } else {
3000       throwSyntaxError("'->' expected in variable_property.");
3001     }
3002   }
3003
3004   private void method_or_not() {
3005     //  method_or_not:
3006     //                  '(' function_call_parameter_list ')'
3007     //          | /* empty */
3008     if (Scanner.TRACE) {
3009       System.out.println("TRACE: method_or_not()");
3010     }
3011     if (token == TokenNameLPAREN) {
3012       getNextToken();
3013       if (token == TokenNameRPAREN) {
3014         getNextToken();
3015         return;
3016       }
3017       non_empty_function_call_parameter_list();
3018       if (token != TokenNameRPAREN) {
3019         throwSyntaxError("')' expected in method_or_not.");
3020       }
3021       getNextToken();
3022     }
3023   }
3024
3025   private void exit_expr() {
3026     //  /* empty */
3027     //  | '(' ')'
3028     //  | '(' expr ')'
3029     if (token != TokenNameLPAREN) {
3030       return;
3031     }
3032     getNextToken();
3033     if (token == TokenNameRPAREN) {
3034       getNextToken();
3035       return;
3036     }
3037     expr();
3038     if (token != TokenNameRPAREN) {
3039       throwSyntaxError("')' expected after keyword 'exit'");
3040     }
3041     getNextToken();
3042   }
3043
3044   private void encaps_list() {
3045     //                  encaps_list encaps_var
3046     //          | encaps_list T_STRING
3047     //          | encaps_list T_NUM_STRING
3048     //          | encaps_list T_ENCAPSED_AND_WHITESPACE
3049     //          | encaps_list T_CHARACTER
3050     //          | encaps_list T_BAD_CHARACTER
3051     //          | encaps_list '['
3052     //          | encaps_list ']'
3053     //          | encaps_list '{'
3054     //          | encaps_list '}'
3055     //          | encaps_list T_OBJECT_OPERATOR
3056     //          | /* empty */
3057     while (true) {
3058       switch (token) {
3059       case TokenNameSTRING:
3060         getNextToken();
3061         break;
3062       case TokenNameLBRACE:
3063         //          scanner.encapsedStringStack.pop();
3064         getNextToken();
3065         break;
3066       case TokenNameRBRACE:
3067         //          scanner.encapsedStringStack.pop();
3068         getNextToken();
3069         break;
3070       case TokenNameLBRACKET:
3071         //          scanner.encapsedStringStack.pop();
3072         getNextToken();
3073         break;
3074       case TokenNameRBRACKET:
3075         //          scanner.encapsedStringStack.pop();
3076         getNextToken();
3077         break;
3078       case TokenNameMINUS_GREATER:
3079         //          scanner.encapsedStringStack.pop();
3080         getNextToken();
3081         break;
3082       case TokenNameVariable:
3083       case TokenNameDOLLAR_LBRACE:
3084       case TokenNameLBRACE_DOLLAR:
3085         encaps_var();
3086         break;
3087       default:
3088         char encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
3089         if (encapsedChar == '$') {
3090           scanner.encapsedStringStack.pop();
3091           encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
3092           switch (encapsedChar) {
3093           case '`':
3094             if (token == TokenNameEncapsedString0) {
3095               return;
3096             }
3097             token = TokenNameSTRING;
3098             continue;
3099           case '\'':
3100             if (token == TokenNameEncapsedString1) {
3101               return;
3102             }
3103             token = TokenNameSTRING;
3104             continue;
3105           case '"':
3106             if (token == TokenNameEncapsedString2) {
3107               return;
3108             }
3109             token = TokenNameSTRING;
3110             continue;
3111           }
3112         }
3113         return;
3114       }
3115     }
3116   }
3117
3118   private void encaps_var() {
3119     //                  T_VARIABLE
3120     //          | T_VARIABLE '[' encaps_var_offset ']'
3121     //          | T_VARIABLE T_OBJECT_OPERATOR T_STRING
3122     //          | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
3123     //          | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
3124     //          | T_CURLY_OPEN variable '}'
3125     switch (token) {
3126     case TokenNameVariable:
3127       getNextToken();
3128       if (token == TokenNameLBRACKET) {
3129         getNextToken();
3130         expr(); //encaps_var_offset();
3131         if (token != TokenNameRBRACKET) {
3132           throwSyntaxError("']' expected after variable.");
3133         }
3134         //          scanner.encapsedStringStack.pop();
3135         getNextToken();
3136         //          }
3137       } else if (token == TokenNameMINUS_GREATER) {
3138         getNextToken();
3139         if (token != TokenNameIdentifier) {
3140           throwSyntaxError("Identifier expected after '->'.");
3141         }
3142         //          scanner.encapsedStringStack.pop();
3143         getNextToken();
3144       }
3145       //        else {
3146       //          // scanner.encapsedStringStack.pop();
3147       //          int tempToken = TokenNameSTRING;
3148       //          if (!scanner.encapsedStringStack.isEmpty()
3149       //              && (token == TokenNameEncapsedString0
3150       //                  || token == TokenNameEncapsedString1
3151       //                  || token == TokenNameEncapsedString2 || token ==
3152       // TokenNameERROR)) {
3153       //            char encapsedChar = ((Character)
3154       // scanner.encapsedStringStack.peek())
3155       //                .charValue();
3156       //            switch (token) {
3157       //              case TokenNameEncapsedString0 :
3158       //                if (encapsedChar == '`') {
3159       //                  tempToken = TokenNameEncapsedString0;
3160       //                }
3161       //                break;
3162       //              case TokenNameEncapsedString1 :
3163       //                if (encapsedChar == '\'') {
3164       //                  tempToken = TokenNameEncapsedString1;
3165       //                }
3166       //                break;
3167       //              case TokenNameEncapsedString2 :
3168       //                if (encapsedChar == '"') {
3169       //                  tempToken = TokenNameEncapsedString2;
3170       //                }
3171       //                break;
3172       //              case TokenNameERROR :
3173       //                if (scanner.source[scanner.currentPosition - 1] == '\\') {
3174       //                  scanner.currentPosition--;
3175       //                  getNextToken();
3176       //                }
3177       //                break;
3178       //            }
3179       //          }
3180       //          token = tempToken;
3181       //        }
3182       break;
3183     case TokenNameDOLLAR_LBRACE:
3184       getNextToken();
3185       if (token == TokenNameDOLLAR_LBRACE) {
3186         encaps_var();
3187       } else if (token == TokenNameIdentifier) {
3188         getNextToken();
3189         if (token == TokenNameLBRACKET) {
3190           getNextToken();
3191           //            if (token == TokenNameRBRACKET) {
3192           //              getNextToken();
3193           //            } else {
3194           expr();
3195           if (token != TokenNameRBRACKET) {
3196             throwSyntaxError("']' expected after '${'.");
3197           }
3198           getNextToken();
3199           //            }
3200         }
3201       } else {
3202         expr();
3203       }
3204       if (token != TokenNameRBRACE) {
3205         throwSyntaxError("'}' expected.");
3206       }
3207       getNextToken();
3208       break;
3209     case TokenNameLBRACE_DOLLAR:
3210       getNextToken();
3211       if (token == TokenNameLBRACE_DOLLAR) {
3212         encaps_var();
3213       } else if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
3214         getNextToken();
3215         if (token == TokenNameLBRACKET) {
3216           getNextToken();
3217           //            if (token == TokenNameRBRACKET) {
3218           //              getNextToken();
3219           //            } else {
3220           expr();
3221           if (token != TokenNameRBRACKET) {
3222             throwSyntaxError("']' expected.");
3223           }
3224           getNextToken();
3225           //            }
3226         } else if (token == TokenNameMINUS_GREATER) {
3227           getNextToken();
3228           if (token != TokenNameIdentifier && token != TokenNameVariable) {
3229             throwSyntaxError("String or Variable token expected.");
3230           }
3231           getNextToken();
3232           if (token == TokenNameLBRACKET) {
3233             getNextToken();
3234             //            if (token == TokenNameRBRACKET) {
3235             //              getNextToken();
3236             //            } else {
3237             expr();
3238             if (token != TokenNameRBRACKET) {
3239               throwSyntaxError("']' expected after '${'.");
3240             }
3241             getNextToken();
3242             //            }
3243           }
3244         }
3245         //          if (token != TokenNameRBRACE) {
3246         //            throwSyntaxError("'}' expected after '{$'.");
3247         //          }
3248         //          // scanner.encapsedStringStack.pop();
3249         //          getNextToken();
3250       } else {
3251         expr();
3252         if (token != TokenNameRBRACE) {
3253           throwSyntaxError("'}' expected.");
3254         }
3255         //          scanner.encapsedStringStack.pop();
3256         getNextToken();
3257       }
3258       break;
3259     }
3260   }
3261
3262   private void encaps_var_offset() {
3263     //                  T_STRING
3264     //          | T_NUM_STRING
3265     //          | T_VARIABLE
3266     switch (token) {
3267     case TokenNameSTRING:
3268       getNextToken();
3269       break;
3270     case TokenNameIntegerLiteral:
3271       getNextToken();
3272       break;
3273     case TokenNameVariable:
3274       getNextToken();
3275       break;
3276     case TokenNameIdentifier:
3277       getNextToken();
3278       break;
3279     default:
3280       throwSyntaxError("Variable or String token expected.");
3281       break;
3282     }
3283   }
3284
3285   private void internal_functions_in_yacc() {
3286     //    int start = 0;
3287     ImportReference impt = null;
3288     switch (token) {
3289     case TokenNameisset:
3290       //        T_ISSET '(' isset_variables ')'
3291       getNextToken();
3292       if (token != TokenNameLPAREN) {
3293         throwSyntaxError("'(' expected after keyword 'isset'");
3294       }
3295       getNextToken();
3296       isset_variables();
3297       if (token != TokenNameRPAREN) {
3298         throwSyntaxError("')' expected after keyword 'isset'");
3299       }
3300       getNextToken();
3301       break;
3302     case TokenNameempty:
3303       //        T_EMPTY '(' variable ')'
3304       getNextToken();
3305       if (token != TokenNameLPAREN) {
3306         throwSyntaxError("'(' expected after keyword 'empty'");
3307       }
3308       getNextToken();
3309       variable();
3310       if (token != TokenNameRPAREN) {
3311         throwSyntaxError("')' expected after keyword 'empty'");
3312       }
3313       getNextToken();
3314       break;
3315     case TokenNameinclude:
3316       //T_INCLUDE expr
3317       checkFileName(token, impt);
3318       break;
3319     case TokenNameinclude_once:
3320       //        T_INCLUDE_ONCE expr
3321       checkFileName(token, impt);
3322       break;
3323     case TokenNameeval:
3324       //        T_EVAL '(' expr ')'
3325       getNextToken();
3326       if (token != TokenNameLPAREN) {
3327         throwSyntaxError("'(' expected after keyword 'eval'");
3328       }
3329       getNextToken();
3330       expr();
3331       if (token != TokenNameRPAREN) {
3332         throwSyntaxError("')' expected after keyword 'eval'");
3333       }
3334       getNextToken();
3335       break;
3336     case TokenNamerequire:
3337       //T_REQUIRE expr
3338       checkFileName(token, impt);
3339       break;
3340     case TokenNamerequire_once:
3341       //        T_REQUIRE_ONCE expr
3342       checkFileName(token, impt);
3343       break;
3344     }
3345   }
3346
3347   private void checkFileName(int includeToken, ImportReference impt) {
3348     //<include-token> expr
3349     int start = scanner.getCurrentTokenStartPosition();
3350     boolean hasLPAREN = false;
3351     getNextToken();
3352     if (token == TokenNameLPAREN) {
3353       hasLPAREN = true;
3354       getNextToken();
3355     }
3356     Expression expression = expr();
3357     if (hasLPAREN) {
3358       if (token == TokenNameRPAREN) {
3359         getNextToken();
3360       } else {
3361         throwSyntaxError("')' expected for keyword '" + scanner.toStringAction(includeToken) + "'");
3362       }
3363     }
3364     impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3365     impt.declarationSourceEnd = impt.sourceEnd;
3366     impt.declarationEnd = impt.declarationSourceEnd;
3367     //endPosition is just before the ;
3368     impt.declarationSourceStart = start;
3369     includesList.add(impt);
3370
3371     if (expression instanceof StringLiteral) {
3372       StringLiteral literal = (StringLiteral) expression;
3373       char[] includeName = literal.source();
3374       if (includeName.length == 0) {
3375         reportSyntaxError("Empty filename after keyword '" + scanner.toStringAction(includeToken) + "'", literal.sourceStart,
3376             literal.sourceStart + 1);
3377       }
3378       String includeNameString = new String(includeName);
3379       if (literal instanceof StringLiteralDQ) {
3380         if (includeNameString.indexOf('$') >= 0) {
3381           // assuming that the filename contains a variable => no filename check
3382           return;
3383         }
3384       }
3385       if (includeNameString.startsWith("http://")) {
3386         // assuming external include location
3387         return;
3388       }
3389       if (scanner.compilationUnit != null) {
3390         IResource resource = scanner.compilationUnit.getResource();
3391         //        java.io.File f = new java.io.File(new String(compilationUnit.getFileName()));
3392         //        System.out.println(expression.toStringExpression());
3393         //      }
3394         if (resource != null && resource instanceof IFile) {
3395           // check the filename:
3396           //      System.out.println(new String(compilationUnit.getFileName())+" - "+ expression.toStringExpression());
3397           IProject project = resource.getProject();
3398           if (project != null) {
3399             if (PHPFileUtil.determineFilePath(includeNameString, resource, project) == null) {
3400               reportSyntaxError("File: " + expression.toStringExpression() + " doesn't exist in project: "
3401                   + project.getLocation().toString(), literal.sourceStart, literal.sourceEnd);
3402               //              System.out.println(path.toString() + " - " + expression.toStringExpression());
3403             }
3404           }
3405         }
3406       }
3407     }
3408   }
3409
3410   private void isset_variables() {
3411     //  variable
3412     //  | isset_variables ','
3413     if (token == TokenNameRPAREN) {
3414       throwSyntaxError("Variable expected after keyword 'isset'");
3415     }
3416     while (true) {
3417       variable();
3418       if (token == TokenNameCOMMA) {
3419         getNextToken();
3420       } else {
3421         break;
3422       }
3423     }
3424   }
3425
3426   private boolean common_scalar() {
3427     //  common_scalar:
3428     //  T_LNUMBER
3429     //  | T_DNUMBER
3430     //  | T_CONSTANT_ENCAPSED_STRING
3431     //  | T_LINE
3432     //  | T_FILE
3433     //  | T_CLASS_C
3434     //  | T_METHOD_C
3435     //  | T_FUNC_C
3436     switch (token) {
3437     case TokenNameIntegerLiteral:
3438       getNextToken();
3439       return true;
3440     case TokenNameDoubleLiteral:
3441       getNextToken();
3442       return true;
3443     case TokenNameStringDoubleQuote:
3444       getNextToken();
3445       return true;
3446     case TokenNameStringSingleQuote:
3447       getNextToken();
3448       return true;
3449     case TokenNameStringInterpolated:
3450       getNextToken();
3451       return true;
3452     case TokenNameFILE:
3453       getNextToken();
3454       return true;
3455     case TokenNameLINE:
3456       getNextToken();
3457       return true;
3458     case TokenNameCLASS_C:
3459       getNextToken();
3460       return true;
3461     case TokenNameMETHOD_C:
3462       getNextToken();
3463       return true;
3464     case TokenNameFUNC_C:
3465       getNextToken();
3466       return true;
3467     }
3468     return false;
3469   }
3470
3471   private void scalar() {
3472     //  scalar:
3473     //  T_STRING
3474     //| T_STRING_VARNAME
3475     //| class_constant
3476     //| common_scalar
3477     //| '"' encaps_list '"'
3478     //| '\'' encaps_list '\''
3479     //| T_START_HEREDOC encaps_list T_END_HEREDOC
3480     throwSyntaxError("Not yet implemented (scalar).");
3481   }
3482
3483   private void static_scalar() {
3484     //    static_scalar: /* compile-time evaluated scalars */
3485     //          common_scalar
3486     //  | T_STRING
3487     //  | '+' static_scalar
3488     //  | '-' static_scalar
3489     //  | T_ARRAY '(' static_array_pair_list ')'
3490     //  | static_class_constant
3491     if (common_scalar()) {
3492       return;
3493     }
3494     switch (token) {
3495     case TokenNameIdentifier:
3496       getNextToken();
3497       //        static_class_constant:
3498       //                T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3499       if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3500         getNextToken();
3501         if (token == TokenNameIdentifier) {
3502           getNextToken();
3503         } else {
3504           throwSyntaxError("Identifier expected after '::' operator.");
3505         }
3506       }
3507       break;
3508     case TokenNameEncapsedString0:
3509       try {
3510         scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3511         while (scanner.currentCharacter != '`') {
3512           if (scanner.currentCharacter == '\\') {
3513             scanner.currentPosition++;
3514           }
3515           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3516         }
3517         getNextToken();
3518       } catch (IndexOutOfBoundsException e) {
3519         throwSyntaxError("'`' expected at end of static string.");
3520       }
3521       break;
3522     case TokenNameEncapsedString1:
3523       try {
3524         scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3525         while (scanner.currentCharacter != '\'') {
3526           if (scanner.currentCharacter == '\\') {
3527             scanner.currentPosition++;
3528           }
3529           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3530         }
3531         getNextToken();
3532       } catch (IndexOutOfBoundsException e) {
3533         throwSyntaxError("'\'' expected at end of static string.");
3534       }
3535       break;
3536     case TokenNameEncapsedString2:
3537       try {
3538         scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3539         while (scanner.currentCharacter != '"') {
3540           if (scanner.currentCharacter == '\\') {
3541             scanner.currentPosition++;
3542           }
3543           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3544         }
3545         getNextToken();
3546       } catch (IndexOutOfBoundsException e) {
3547         throwSyntaxError("'\"' expected at end of static string.");
3548       }
3549       break;
3550     case TokenNamePLUS:
3551       getNextToken();
3552       static_scalar();
3553       break;
3554     case TokenNameMINUS:
3555       getNextToken();
3556       static_scalar();
3557       break;
3558     case TokenNamearray:
3559       getNextToken();
3560       if (token != TokenNameLPAREN) {
3561         throwSyntaxError("'(' expected after keyword 'array'");
3562       }
3563       getNextToken();
3564       if (token == TokenNameRPAREN) {
3565         getNextToken();
3566         break;
3567       }
3568       non_empty_static_array_pair_list();
3569       if (token != TokenNameRPAREN) {
3570         throwSyntaxError("')' expected after keyword 'array'");
3571       }
3572       getNextToken();
3573       break;
3574     //      case TokenNamenull :
3575     //        getNextToken();
3576     //        break;
3577     //      case TokenNamefalse :
3578     //        getNextToken();
3579     //        break;
3580     //      case TokenNametrue :
3581     //        getNextToken();
3582     //        break;
3583     default:
3584       throwSyntaxError("Static scalar/constant expected.");
3585     }
3586   }
3587
3588   private void non_empty_static_array_pair_list() {
3589     //  non_empty_static_array_pair_list:
3590     //  non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3591     // static_scalar
3592     //| non_empty_static_array_pair_list ',' static_scalar
3593     //| static_scalar T_DOUBLE_ARROW static_scalar
3594     //| static_scalar
3595     while (true) {
3596       static_scalar();
3597       if (token == TokenNameEQUAL_GREATER) {
3598         getNextToken();
3599         static_scalar();
3600       }
3601       if (token != TokenNameCOMMA) {
3602         break;
3603       }
3604       getNextToken();
3605       if (token == TokenNameRPAREN) {
3606         break;
3607       }
3608     }
3609   }
3610
3611   public void reportSyntaxError() { //int act, int currentKind, int
3612     // stateStackTop) {
3613     /* remember current scanner position */
3614     int startPos = scanner.startPosition;
3615     int currentPos = scanner.currentPosition;
3616     //          String[] expectings;
3617     //          String tokenName = name[symbol_index[currentKind]];
3618     //fetch all "accurate" possible terminals that could recover the error
3619     //          int start, end = start = asi(stack[stateStackTop]);
3620     //          while (asr[end] != 0)
3621     //                  end++;
3622     //          int length = end - start;
3623     //          expectings = new String[length];
3624     //          if (length != 0) {
3625     //                  char[] indexes = new char[length];
3626     //                  System.arraycopy(asr, start, indexes, 0, length);
3627     //                  for (int i = 0; i < length; i++) {
3628     //                          expectings[i] = name[symbol_index[indexes[i]]];
3629     //                  }
3630     //          }
3631     //if the pb is an EOF, try to tell the user that they are some
3632     //          if (tokenName.equals(UNEXPECTED_EOF)) {
3633     //                  if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3634     //                          char[] tokenSource;
3635     //                          try {
3636     //                                  tokenSource = this.scanner.getCurrentTokenSource();
3637     //                          } catch (Exception e) {
3638     //                                  tokenSource = new char[] {};
3639     //                          }
3640     //                          problemReporter().parseError(
3641     //                                  this.scanner.startPosition,
3642     //                                  this.scanner.currentPosition - 1,
3643     //                                  tokenSource,
3644     //                                  tokenName,
3645     //                                  expectings);
3646     //                  }
3647     //          } else { //the next test is HEAVILY grammar DEPENDENT.
3648     //                  if ((length == 14)
3649     //                          && (expectings[0] == "=") //$NON-NLS-1$
3650     //                          && (expectings[1] == "*=") //$NON-NLS-1$
3651     //                          && (expressionPtr > -1)) {
3652     //                                  switch(currentKind) {
3653     //                                          case TokenNameSEMICOLON:
3654     //                                          case TokenNamePLUS:
3655     //                                          case TokenNameMINUS:
3656     //                                          case TokenNameDIVIDE:
3657     //                                          case TokenNameREMAINDER:
3658     //                                          case TokenNameMULTIPLY:
3659     //                                          case TokenNameLEFT_SHIFT:
3660     //                                          case TokenNameRIGHT_SHIFT:
3661     //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3662     //                                          case TokenNameLESS:
3663     //                                          case TokenNameGREATER:
3664     //                                          case TokenNameLESS_EQUAL:
3665     //                                          case TokenNameGREATER_EQUAL:
3666     //                                          case TokenNameEQUAL_EQUAL:
3667     //                                          case TokenNameNOT_EQUAL:
3668     //                                          case TokenNameXOR:
3669     //                                          case TokenNameAND:
3670     //                                          case TokenNameOR:
3671     //                                          case TokenNameOR_OR:
3672     //                                          case TokenNameAND_AND:
3673     //                                                  // the ; is not the expected token ==> it ends a statement when an
3674     // expression is not ended
3675     //                                                  problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3676     //                                                  break;
3677     //                                          case TokenNameRBRACE :
3678     //                                                  problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3679     //                                                  break;
3680     //                                          default:
3681     //                                                  char[] tokenSource;
3682     //                                                  try {
3683     //                                                          tokenSource = this.scanner.getCurrentTokenSource();
3684     //                                                  } catch (Exception e) {
3685     //                                                          tokenSource = new char[] {};
3686     //                                                  }
3687     //                                                  problemReporter().parseError(
3688     //                                                          this.scanner.startPosition,
3689     //                                                          this.scanner.currentPosition - 1,
3690     //                                                          tokenSource,
3691     //                                                          tokenName,
3692     //                                                          expectings);
3693     //                                                  this.checkAndReportBracketAnomalies(problemReporter());
3694     //                                  }
3695     //                  } else {
3696     char[] tokenSource;
3697     try {
3698       tokenSource = this.scanner.getCurrentTokenSource();
3699     } catch (Exception e) {
3700       tokenSource = new char[] {};
3701     }
3702     //                          problemReporter().parseError(
3703     //                                  this.scanner.startPosition,
3704     //                                  this.scanner.currentPosition - 1,
3705     //                                  tokenSource,
3706     //                                  tokenName,
3707     //                                  expectings);
3708     this.checkAndReportBracketAnomalies(problemReporter());
3709     //                  }
3710     //          }
3711     /* reset scanner where it was */
3712     scanner.startPosition = startPos;
3713     scanner.currentPosition = currentPos;
3714   }
3715
3716   public static final int RoundBracket = 0;
3717
3718   public static final int SquareBracket = 1;
3719
3720   public static final int CurlyBracket = 2;
3721
3722   public static final int BracketKinds = 3;
3723
3724   protected int[] nestedMethod; //the ptr is nestedType
3725
3726   protected int nestedType, dimensions;
3727
3728   //ast stack
3729   final static int AstStackIncrement = 100;
3730
3731   protected int astPtr;
3732
3733   protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
3734
3735   protected int astLengthPtr;
3736
3737   protected int[] astLengthStack;
3738
3739   ASTNode[] noAstNodes = new ASTNode[AstStackIncrement];
3740
3741   public CompilationUnitDeclaration compilationUnit; /*
3742                                                       * the result from parse()
3743                                                       */
3744
3745   protected ReferenceContext referenceContext;
3746
3747   protected ProblemReporter problemReporter;
3748
3749   protected CompilerOptions options;
3750
3751   private ArrayList includesList;
3752
3753   //  protected CompilationResult compilationResult;
3754   /**
3755    * Returns this parser's problem reporter initialized with its reference context. Also it is assumed that a problem is going to be
3756    * reported, so initializes the compilation result's line positions.
3757    */
3758   public ProblemReporter problemReporter() {
3759     if (scanner.recordLineSeparator) {
3760       compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
3761     }
3762     problemReporter.referenceContext = referenceContext;
3763     return problemReporter;
3764   }
3765
3766   /*
3767    * Reconsider the entire source looking for inconsistencies in {} () []
3768    */
3769   public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3770     scanner.wasAcr = false;
3771     boolean anomaliesDetected = false;
3772     try {
3773       char[] source = scanner.source;
3774       int[] leftCount = { 0, 0, 0 };
3775       int[] rightCount = { 0, 0, 0 };
3776       int[] depths = { 0, 0, 0 };
3777       int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] };
3778       int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] };
3779       int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] };
3780       int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] };
3781       scanner.currentPosition = scanner.initialPosition; //starting
3782       // point
3783       // (first-zero-based
3784       // char)
3785       while (scanner.currentPosition < scanner.eofPosition) { //loop for
3786         // jumping
3787         // over
3788         // comments
3789         try {
3790           // ---------Consume white space and handles
3791           // startPosition---------
3792           boolean isWhiteSpace;
3793           do {
3794             scanner.startPosition = scanner.currentPosition;
3795             //                                          if (((scanner.currentCharacter =
3796             // source[scanner.currentPosition++]) == '\\') &&
3797             // (source[scanner.currentPosition] == 'u')) {
3798             //                                                  isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3799             //                                          } else {
3800             if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3801               if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3802                 // only record line positions we have not
3803                 // recorded yet
3804                 scanner.pushLineSeparator();
3805               }
3806             }
3807             isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3808             //                                          }
3809           } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
3810           // -------consume token until } is found---------
3811           switch (scanner.currentCharacter) {
3812           case '{': {
3813             int index = leftCount[CurlyBracket]++;
3814             if (index == leftPositions[CurlyBracket].length) {
3815               System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
3816               System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
3817             }
3818             leftPositions[CurlyBracket][index] = scanner.startPosition;
3819             leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3820           }
3821             break;
3822           case '}': {
3823             int index = rightCount[CurlyBracket]++;
3824             if (index == rightPositions[CurlyBracket].length) {
3825               System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
3826               System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
3827             }
3828             rightPositions[CurlyBracket][index] = scanner.startPosition;
3829             rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3830           }
3831             break;
3832           case '(': {
3833             int index = leftCount[RoundBracket]++;
3834             if (index == leftPositions[RoundBracket].length) {
3835               System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
3836               System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
3837             }
3838             leftPositions[RoundBracket][index] = scanner.startPosition;
3839             leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3840           }
3841             break;
3842           case ')': {
3843             int index = rightCount[RoundBracket]++;
3844             if (index == rightPositions[RoundBracket].length) {
3845               System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
3846               System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
3847             }
3848             rightPositions[RoundBracket][index] = scanner.startPosition;
3849             rightDepths[RoundBracket][index] = --depths[RoundBracket];
3850           }
3851             break;
3852           case '[': {
3853             int index = leftCount[SquareBracket]++;
3854             if (index == leftPositions[SquareBracket].length) {
3855               System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
3856               System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
3857             }
3858             leftPositions[SquareBracket][index] = scanner.startPosition;
3859             leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3860           }
3861             break;
3862           case ']': {
3863             int index = rightCount[SquareBracket]++;
3864             if (index == rightPositions[SquareBracket].length) {
3865               System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
3866               System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
3867             }
3868             rightPositions[SquareBracket][index] = scanner.startPosition;
3869             rightDepths[SquareBracket][index] = --depths[SquareBracket];
3870           }
3871             break;
3872           case '\'': {
3873             if (scanner.getNextChar('\\')) {
3874               scanner.scanEscapeCharacter();
3875             } else { // consume next character
3876               scanner.unicodeAsBackSlash = false;
3877               //                                                                        if (((scanner.currentCharacter =
3878               // source[scanner.currentPosition++]) ==
3879               // '\\') &&
3880               // (source[scanner.currentPosition] ==
3881               // 'u')) {
3882               //                                                                                scanner.getNextUnicodeChar();
3883               //                                                                        } else {
3884               if (scanner.withoutUnicodePtr != 0) {
3885                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3886               }
3887               //                                                                        }
3888             }
3889             scanner.getNextChar('\'');
3890             break;
3891           }
3892           case '"':
3893             // consume next character
3894             scanner.unicodeAsBackSlash = false;
3895             //                                                  if (((scanner.currentCharacter =
3896             // source[scanner.currentPosition++]) == '\\') &&
3897             // (source[scanner.currentPosition] == 'u')) {
3898             //                                                          scanner.getNextUnicodeChar();
3899             //                                                  } else {
3900             if (scanner.withoutUnicodePtr != 0) {
3901               scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3902             }
3903             //                                                  }
3904             while (scanner.currentCharacter != '"') {
3905               if (scanner.currentCharacter == '\r') {
3906                 if (source[scanner.currentPosition] == '\n')
3907                   scanner.currentPosition++;
3908                 break; // the string cannot go further that
3909                 // the line
3910               }
3911               if (scanner.currentCharacter == '\n') {
3912                 break; // the string cannot go further that
3913                 // the line
3914               }
3915               if (scanner.currentCharacter == '\\') {
3916                 scanner.scanEscapeCharacter();
3917               }
3918               // consume next character
3919               scanner.unicodeAsBackSlash = false;
3920               //                                                                if (((scanner.currentCharacter =
3921               // source[scanner.currentPosition++]) == '\\')
3922               // && (source[scanner.currentPosition] == 'u'))
3923               // {
3924               //                                                                        scanner.getNextUnicodeChar();
3925               //                                                                } else {
3926               if (scanner.withoutUnicodePtr != 0) {
3927                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3928               }
3929               //                                                                }
3930             }
3931             break;
3932           case '/': {
3933             int test;
3934             if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3935               // comment
3936               //get the next char
3937               if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3938                   && (source[scanner.currentPosition] == 'u')) {
3939                 //-------------unicode traitement
3940                 // ------------
3941                 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3942                 scanner.currentPosition++;
3943                 while (source[scanner.currentPosition] == 'u') {
3944                   scanner.currentPosition++;
3945                 }
3946                 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3947                     || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3948                     || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3949                     || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3950                   // don't
3951                   // care of the
3952                   // value
3953                   scanner.currentCharacter = 'A';
3954                 } //something different from \n and \r
3955                 else {
3956                   scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3957                 }
3958               }
3959               while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
3960                 //get the next char
3961                 scanner.startPosition = scanner.currentPosition;
3962                 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3963                     && (source[scanner.currentPosition] == 'u')) {
3964                   //-------------unicode traitement
3965                   // ------------
3966                   int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3967                   scanner.currentPosition++;
3968                   while (source[scanner.currentPosition] == 'u') {
3969                     scanner.currentPosition++;
3970                   }
3971                   if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3972                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3973                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3974                       || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3975                     // don't
3976                     // care of the
3977                     // value
3978                     scanner.currentCharacter = 'A';
3979                   } //something different from \n
3980                   // and \r
3981                   else {
3982                     scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3983                   }
3984                 }
3985               }
3986               if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3987                 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3988                   // only record line positions we
3989                   // have not recorded yet
3990                   scanner.pushLineSeparator();
3991                   if (this.scanner.taskTags != null) {
3992                     this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner
3993                         .getCurrentTokenEndPosition());
3994                   }
3995                 }
3996               }
3997               break;
3998             }
3999             if (test > 0) { //traditional and annotation
4000               // comment
4001               boolean star = false;
4002               // consume next character
4003               scanner.unicodeAsBackSlash = false;
4004               //                                                                        if (((scanner.currentCharacter =
4005               // source[scanner.currentPosition++]) ==
4006               // '\\') &&
4007               // (source[scanner.currentPosition] ==
4008               // 'u')) {
4009               //                                                                                scanner.getNextUnicodeChar();
4010               //                                                                        } else {
4011               if (scanner.withoutUnicodePtr != 0) {
4012                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
4013               }
4014               //                                                                        }
4015               if (scanner.currentCharacter == '*') {
4016                 star = true;
4017               }
4018               //get the next char
4019               if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
4020                   && (source[scanner.currentPosition] == 'u')) {
4021                 //-------------unicode traitement
4022                 // ------------
4023                 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4024                 scanner.currentPosition++;
4025                 while (source[scanner.currentPosition] == 'u') {
4026                   scanner.currentPosition++;
4027                 }
4028                 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
4029                     || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
4030                     || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
4031                     || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
4032                   // don't
4033                   // care of the
4034                   // value
4035                   scanner.currentCharacter = 'A';
4036                 } //something different from * and /
4037                 else {
4038                   scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4039                 }
4040               }
4041               //loop until end of comment */
4042               while ((scanner.currentCharacter != '/') || (!star)) {
4043                 star = scanner.currentCharacter == '*';
4044                 //get next char
4045                 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
4046                     && (source[scanner.currentPosition] == 'u')) {
4047                   //-------------unicode traitement
4048                   // ------------
4049                   int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4050                   scanner.currentPosition++;
4051                   while (source[scanner.currentPosition] == 'u') {
4052                     scanner.currentPosition++;
4053                   }
4054                   if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
4055                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
4056                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
4057                       || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
4058                     // don't
4059                     // care of the
4060                     // value
4061                     scanner.currentCharacter = 'A';
4062                   } //something different from * and
4063                   // /
4064                   else {
4065                     scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4066                   }
4067                 }
4068               }
4069               if (this.scanner.taskTags != null) {
4070                 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
4071               }
4072               break;
4073             }
4074             break;
4075           }
4076           default:
4077             if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
4078               scanner.scanIdentifierOrKeyword(false);
4079               break;
4080             }
4081             if (Character.isDigit(scanner.currentCharacter)) {
4082               scanner.scanNumber(false);
4083               break;
4084             }
4085           }
4086           //-----------------end switch while
4087           // try--------------------
4088         } catch (IndexOutOfBoundsException e) {
4089           break; // read until EOF
4090         } catch (InvalidInputException e) {
4091           return false; // no clue
4092         }
4093       }
4094       if (scanner.recordLineSeparator) {
4095         //                              compilationUnit.compilationResult.lineSeparatorPositions =
4096         // scanner.getLineEnds();
4097       }
4098       // check placement anomalies against other kinds of brackets
4099       for (int kind = 0; kind < BracketKinds; kind++) {
4100         for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
4101           int start = leftPositions[kind][leftIndex]; // deepest
4102           // first
4103           // find matching closing bracket
4104           int depth = leftDepths[kind][leftIndex];
4105           int end = -1;
4106           for (int i = 0; i < rightCount[kind]; i++) {
4107             int pos = rightPositions[kind][i];
4108             // want matching bracket further in source with same
4109             // depth
4110             if ((pos > start) && (depth == rightDepths[kind][i])) {
4111               end = pos;
4112               break;
4113             }
4114           }
4115           if (end < 0) { // did not find a good closing match
4116             problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
4117             return true;
4118           }
4119           // check if even number of opening/closing other brackets
4120           // in between this pair of brackets
4121           int balance = 0;
4122           for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
4123             for (int i = 0; i < leftCount[otherKind]; i++) {
4124               int pos = leftPositions[otherKind][i];
4125               if ((pos > start) && (pos < end))
4126                 balance++;
4127             }
4128             for (int i = 0; i < rightCount[otherKind]; i++) {
4129               int pos = rightPositions[otherKind][i];
4130               if ((pos > start) && (pos < end))
4131                 balance--;
4132             }
4133             if (balance != 0) {
4134               problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket
4135               // anomaly
4136               return true;
4137             }
4138           }
4139         }
4140         // too many opening brackets ?
4141         for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
4142           anomaliesDetected = true;
4143           problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext,
4144               compilationUnit.compilationResult);
4145         }
4146         // too many closing brackets ?
4147         for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
4148           anomaliesDetected = true;
4149           problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
4150         }
4151         if (anomaliesDetected)
4152           return true;
4153       }
4154       return anomaliesDetected;
4155     } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
4156       return anomaliesDetected;
4157     } catch (NullPointerException e) { // jdk1.2.2 jit bug
4158       return anomaliesDetected;
4159     }
4160   }
4161
4162   protected void pushOnAstLengthStack(int pos) {
4163     try {
4164       astLengthStack[++astLengthPtr] = pos;
4165     } catch (IndexOutOfBoundsException e) {
4166       int oldStackLength = astLengthStack.length;
4167       int[] oldPos = astLengthStack;
4168       astLengthStack = new int[oldStackLength + StackIncrement];
4169       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
4170       astLengthStack[astLengthPtr] = pos;
4171     }
4172   }
4173
4174   protected void pushOnAstStack(ASTNode node) {
4175     /*
4176      * add a new obj on top of the ast stack
4177      */
4178     try {
4179       astStack[++astPtr] = node;
4180     } catch (IndexOutOfBoundsException e) {
4181       int oldStackLength = astStack.length;
4182       ASTNode[] oldStack = astStack;
4183       astStack = new ASTNode[oldStackLength + AstStackIncrement];
4184       System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
4185       astPtr = oldStackLength;
4186       astStack[astPtr] = node;
4187     }
4188     try {
4189       astLengthStack[++astLengthPtr] = 1;
4190     } catch (IndexOutOfBoundsException e) {
4191       int oldStackLength = astLengthStack.length;
4192       int[] oldPos = astLengthStack;
4193       astLengthStack = new int[oldStackLength + AstStackIncrement];
4194       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
4195       astLengthStack[astLengthPtr] = 1;
4196     }
4197   }
4198
4199   protected void resetModifiers() {
4200     this.modifiers = AccDefault;
4201     this.modifiersSourceStart = -1; // <-- see comment into
4202     // modifiersFlag(int)
4203     this.scanner.commentPtr = -1;
4204   }
4205 }