1 /*******************************************************************************
 
   2  * Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de All rights
 
   3  * reserved. This program and the accompanying material are made available under
 
   4  * the terms of the Common Public License v1.0 which accompanies this
 
   5  * distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html
 
   7  * Contributors: Klaus Hartlage - www.eclipseproject.de
 
   8  ******************************************************************************/
 
   9 package net.sourceforge.phpdt.internal.compiler.parser;
 
  10 import java.util.ArrayList;
 
  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.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
 
  23 import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
 
  24 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
 
  25 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
 
  26 import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
 
  27 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
 
  28 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
 
  29 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
 
  31 import org.eclipse.core.resources.IFile;
 
  32 public class Parser //extends PHPParserSuperclass
 
  33     implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
 
  34   //internal data for the automat
 
  35   protected final static int StackIncrement = 255;
 
  36   protected int stateStackTop;
 
  37   protected int[] stack = new int[StackIncrement];
 
  38   public int firstToken; // handle for multiple parsing goals
 
  39   public int lastAct; //handle for multiple parsing goals
 
  40   protected RecoveredElement currentElement;
 
  41   public static boolean VERBOSE_RECOVERY = false;
 
  42   protected boolean diet = false; //tells the scanner to jump over some
 
  43   // parts of the code/expressions like
 
  46   public Scanner scanner;
 
  47   private ArrayList phpList;
 
  48   private int currentPHPString;
 
  49   private boolean phpEnd;
 
  50   // private static HashMap keywordMap = null;
 
  56   // row counter for syntax errors:
 
  58   // column counter for syntax errors:
 
  62   //    // current identifier
 
  66   private String stringValue;
 
  67   /** Contains the current expression. */
 
  68   // private StringBuffer expression;
 
  69   //private boolean phpMode;
 
  70   protected int modifiers;
 
  71   protected int modifiersSourceStart;
 
  72   protected Parser(ProblemReporter problemReporter) {
 
  73     this.problemReporter = problemReporter;
 
  74     this.options = problemReporter.options;
 
  75     this.currentPHPString = 0;
 
  76     //          PHPParserSuperclass.fileToParse = fileToParse;
 
  79     this.token = TokenNameEOF;
 
  82     //    this.columnCount = 0;
 
  85     this.initializeScanner();
 
  87   public void setFileToParse(IFile fileToParse) {
 
  88     this.currentPHPString = 0;
 
  89     //    PHPParserSuperclass.fileToParse = fileToParse;
 
  92     this.token = TokenNameEOF;
 
  94     this.initializeScanner();
 
  97    * ClassDeclaration Constructor.
 
 101    *          Description of Parameter
 
 104   public Parser(IFile fileToParse) {
 
 105     //    if (keywordMap == null) {
 
 106     //      keywordMap = new HashMap();
 
 107     //      for (int i = 0; i < PHP_KEYWORS.length; i++) {
 
 108     //        keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
 
 111     this.currentPHPString = 0;
 
 112     //    PHPParserSuperclass.fileToParse = fileToParse;
 
 114     this.includesList = null;
 
 116     this.token = TokenNameEOF;
 
 118     //    this.rowCount = 1;
 
 119     //    this.columnCount = 0;
 
 122     this.initializeScanner();
 
 124   public void initializeScanner() {
 
 125     this.scanner = new Scanner(false /* comment */, false /* whitespace */, this.options
 
 126         .getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /* nls */, false, false,
 
 127         this.options.taskTags/* taskTags */, this.options.taskPriorites/* taskPriorities */);
 
 130    * Create marker for the parse error
 
 132   //  private void setMarker(String message, int charStart, int charEnd, int
 
 134   //    setMarker(fileToParse, message, charStart, charEnd, errorLevel);
 
 137    * This method will throw the SyntaxError. It will add the good lines and
 
 138    * columns to the Error
 
 142    * @throws SyntaxError
 
 145   private void throwSyntaxError(String error) {
 
 146     int problemStartPosition = scanner.getCurrentTokenStartPosition();
 
 147     int problemEndPosition = scanner.getCurrentTokenEndPosition();
 
 148     throwSyntaxError(error, problemStartPosition, problemEndPosition + 1);
 
 151    * This method will throw the SyntaxError. It will add the good lines and
 
 152    * columns to the Error
 
 156    * @throws SyntaxError
 
 159   //  private void throwSyntaxError(String error, int startRow) {
 
 160   //    throw new SyntaxError(startRow, 0, " ", error);
 
 162   private void throwSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
 
 163     problemReporter.phpParsingError(new String[]{error}, problemStartPosition, problemEndPosition, referenceContext,
 
 164         compilationUnit.compilationResult);
 
 165     throw new SyntaxError(1, 0, " ", error);
 
 167   private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
 
 168     problemReporter.phpParsingError(new String[]{error}, problemStartPosition, problemEndPosition, referenceContext,
 
 169         compilationUnit.compilationResult);
 
 171   private void reportSyntaxWarning(String error, int problemStartPosition, int problemEndPosition) {
 
 172     problemReporter.phpParsingWarning(new String[]{error}, problemStartPosition, problemEndPosition, referenceContext,
 
 173         compilationUnit.compilationResult);
 
 176    * Method Declaration.
 
 180   //  private void getChar() {
 
 181   //    if (str.length() > chIndx) {
 
 182   //      ch = str.charAt(chIndx++);
 
 187   //    chIndx = str.length() + 1;
 
 189   //    // token = TokenNameEOF;
 
 193    * gets the next token from input
 
 195   private void getNextToken() {
 
 197       token = scanner.getNextToken();
 
 199         int currentEndPosition = scanner.getCurrentTokenEndPosition();
 
 200         int currentStartPosition = scanner.getCurrentTokenStartPosition();
 
 201         System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
 
 202         System.out.println(scanner.toStringAction(token));
 
 204     } catch (InvalidInputException e) {
 
 205       token = TokenNameERROR;
 
 209   public void init(String s) {
 
 211     this.token = TokenNameEOF;
 
 213     //    this.rowCount = 1;
 
 214     //    this.columnCount = 0;
 
 216     //    this.phpMode = false;
 
 217     /* scanner initialization */
 
 218     scanner.setSource(s.toCharArray());
 
 219     scanner.setPHPMode(false);
 
 221   protected void initialize(boolean phpMode) {
 
 222     compilationUnit = null;
 
 223     referenceContext = null;
 
 224     includesList = new ArrayList();
 
 226     this.token = TokenNameEOF;
 
 228     //    this.rowCount = 1;
 
 229     //    this.columnCount = 0;
 
 231     //    this.phpMode = phpMode;
 
 232     scanner.setPHPMode(phpMode);
 
 235    * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
 
 238   public void parse(String s) {
 
 243    * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
 
 246   protected void parse() {
 
 250         if (token != TokenNameEOF && token != TokenNameERROR) {
 
 253         if (token != TokenNameEOF) {
 
 254           if (token == TokenNameERROR) {
 
 255             throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
 
 257           if (token == TokenNameRPAREN) {
 
 258             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
 
 260           if (token == TokenNameRBRACE) {
 
 261             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
 
 263           if (token == TokenNameRBRACKET) {
 
 264             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
 
 266           if (token == TokenNameLPAREN) {
 
 267             throwSyntaxError("Read character '('; end-of-file not reached.");
 
 269           if (token == TokenNameLBRACE) {
 
 270             throwSyntaxError("Read character '{';  end-of-file not reached.");
 
 272           if (token == TokenNameLBRACKET) {
 
 273             throwSyntaxError("Read character '[';  end-of-file not reached.");
 
 275           throwSyntaxError("End-of-file not reached.");
 
 278       } catch (SyntaxError sytaxErr1) {
 
 279         // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(),
 
 281         //        setMarker(sytaxErr1.getMessage(),
 
 282         // scanner.getCurrentTokenStartPosition(),
 
 283         // scanner.getCurrentTokenEndPosition(), ERROR);
 
 285           // if an error occured,
 
 286           // try to find keywords 'class' or 'function'
 
 287           // to parse the rest of the string
 
 288           while (token != TokenNameEOF && token != TokenNameERROR) {
 
 289             if (token == TokenNameabstract || token == TokenNamefinal || token == TokenNameclass || token == TokenNamefunction) {
 
 294           if (token == TokenNameEOF || token == TokenNameERROR) {
 
 297         } catch (SyntaxError sytaxErr2) {
 
 298           //    setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(),
 
 300           //          setMarker(sytaxErr2.getMessage(),
 
 301           // scanner.getCurrentTokenStartPosition(),
 
 302           // scanner.getCurrentTokenEndPosition(), ERROR);
 
 311   protected CompilationUnitDeclaration endParse(int act) {
 
 315     if (currentElement != null) {
 
 316       currentElement.topElement().updateParseTree();
 
 317       if (VERBOSE_RECOVERY) {
 
 318         System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
 
 319         System.out.println("--------------------------"); //$NON-NLS-1$
 
 320         System.out.println(compilationUnit);
 
 321         System.out.println("----------------------------------"); //$NON-NLS-1$
 
 324       if (diet & VERBOSE_RECOVERY) {
 
 325         System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
 
 326         System.out.println("--------------------------"); //$NON-NLS-1$
 
 327         System.out.println(compilationUnit);
 
 328         System.out.println("----------------------------------"); //$NON-NLS-1$
 
 331     if (scanner.recordLineSeparator) {
 
 332       compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
 
 334     if (scanner.taskTags != null) {
 
 335       for (int i = 0; i < scanner.foundTaskCount; i++) {
 
 336         problemReporter().task(new String(scanner.foundTaskTags[i]), new String(scanner.foundTaskMessages[i]),
 
 337             scanner.foundTaskPriorities[i] == null ? null : new String(scanner.foundTaskPriorities[i]),
 
 338             scanner.foundTaskPositions[i][0], scanner.foundTaskPositions[i][1]);
 
 341     compilationUnit.imports = new ImportReference[includesList.size()];
 
 342     for (int i = 0; i < includesList.size(); i++) {
 
 343       compilationUnit.imports[i] = (ImportReference) includesList.get(i);
 
 345     return compilationUnit;
 
 347   //  public PHPOutlineInfo parseInfo(Object parent, String s) {
 
 348   //    PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
 
 349   //    // Stack stack = new Stack();
 
 350   //    // stack.push(outlineInfo.getDeclarations());
 
 352   //    this.token = TokenNameEOF;
 
 353   //    // this.chIndx = 0;
 
 354   //    // this.rowCount = 1;
 
 355   //    // this.columnCount = 0;
 
 356   //    this.phpEnd = false;
 
 357   //    this.phpMode = false;
 
 358   //    scanner.setSource(s.toCharArray());
 
 359   //    scanner.setPHPMode(false);
 
 362   //    parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
 
 364   //    return outlineInfo;
 
 366   private boolean isVariable() {
 
 367     return token == TokenNameVariable; //  || token == TokenNamethis;
 
 369   //  private void parseDeclarations(PHPOutlineInfo outlineInfo,
 
 370   //      OutlineableWithChildren current, boolean goBack) {
 
 372   //    // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
 
 373   //    PHPSegmentWithChildren temp;
 
 375   //    IPreferenceStore store =
 
 376   // PHPeclipsePlugin.getDefault().getPreferenceStore();
 
 378   //      while (token != TokenNameEOF && token != TokenNameERROR) {
 
 379   //        if (token == TokenNameVariable) {
 
 380   //          ident = scanner.getCurrentIdentifierSource();
 
 381   //          outlineInfo.addVariable(new String(ident));
 
 383   //        } else if (token == TokenNamevar) {
 
 385   //          if (token == TokenNameVariable
 
 386   //              && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
 
 387   //            ident = scanner.getCurrentIdentifierSource();
 
 388   //            //substring(1) added because PHPVarDeclaration doesn't
 
 389   //            // need the $ anymore
 
 390   //            String variableName = new String(ident).substring(1);
 
 391   //            outlineInfo.addVariable(variableName);
 
 393   //            if (token != TokenNameSEMICOLON) {
 
 395   //              ident = scanner.getCurrentTokenSource();
 
 396   //              if (token > TokenNameKEYWORD) {
 
 397   //                current.add(new PHPVarDeclaration(current, variableName,
 
 398   //                // chIndx - ident.length,
 
 399   //                    scanner.getCurrentTokenStartPosition(), new String(ident)));
 
 402   //                  case TokenNameVariable :
 
 403   //                  case TokenNamethis :
 
 404   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 407   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 410   //                  case TokenNameIdentifier :
 
 411   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 414   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 417   //                  case TokenNameDoubleLiteral :
 
 418   //                    current.add(new PHPVarDeclaration(current, variableName
 
 422   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 425   //                  case TokenNameIntegerLiteral :
 
 426   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 429   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 432   //                  case TokenNameStringInterpolated :
 
 433   //                  case TokenNameStringLiteral :
 
 434   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 437   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 440   //                  case TokenNameStringConstant :
 
 441   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 444   //                        scanner.getCurrentTokenStartPosition(), new String(
 
 448   //                    current.add(new PHPVarDeclaration(current, variableName,
 
 451   //                        scanner.getCurrentTokenStartPosition()));
 
 456   //              ident = scanner.getCurrentIdentifierSource();
 
 457   //              current.add(new PHPVarDeclaration(current, variableName,
 
 458   //              // chIndx - ident.length
 
 459   //                  scanner.getCurrentTokenStartPosition()));
 
 462   //        } else if (token == TokenNamefunction) {
 
 464   //          if (token == TokenNameAND) {
 
 467   //          if (token == TokenNameIdentifier
 
 468   //              && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
 
 469   //            ident = scanner.getCurrentIdentifierSource();
 
 470   //            outlineInfo.addVariable(new String(ident));
 
 471   //            temp = new PHPFunctionDeclaration(current, new String(ident),
 
 472   //            // chIndx - ident.length
 
 473   //                scanner.getCurrentTokenStartPosition());
 
 474   //            current.add(temp);
 
 476   //            parseDeclarations(outlineInfo, temp, true);
 
 478   //        } else if (token == TokenNameclass) {
 
 480   //          if (token == TokenNameIdentifier
 
 481   //              && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
 
 482   //            ident = scanner.getCurrentIdentifierSource();
 
 483   //            outlineInfo.addVariable(new String(ident));
 
 484   //            temp = new PHPClassDeclaration(current, new String(ident),
 
 485   //            // chIndx - ident.len
 
 486   //                scanner.getCurrentTokenStartPosition());
 
 487   //            current.add(temp);
 
 488   //            // stack.push(temp);
 
 490   //            //skip tokens for classname, extends and others until
 
 491   //            // we have the opening '{'
 
 492   //            while (token != TokenNameLBRACE && token != TokenNameEOF
 
 493   //                && token != TokenNameERROR) {
 
 496   //            parseDeclarations(outlineInfo, temp, true);
 
 499   //        } else if ((token == TokenNameLBRACE)
 
 500   //            || (token == TokenNameDOLLAR_LBRACE)) {
 
 503   //        } else if (token == TokenNameRBRACE) {
 
 506   //          if (counter == 0 && goBack) {
 
 509   //        } else if (token == TokenNamerequire || token == TokenNamerequire_once
 
 510   //            || token == TokenNameinclude || token == TokenNameinclude_once) {
 
 511   //          ident = scanner.getCurrentTokenSource();
 
 513   //          int startPosition = scanner.getCurrentTokenStartPosition();
 
 515   //          char[] expr = scanner.getCurrentTokenSource(startPosition);
 
 516   //          outlineInfo.addVariable(new String(ident));
 
 517   //          current.add(new PHPReqIncDeclaration(current, new String(ident),
 
 518   //          // chIndx - ident.length,
 
 519   //              startPosition, new String(expr)));
 
 525   //    } catch (SyntaxError sytaxErr) {
 
 527   //      // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
 
 528   //      // setMarker(sytaxErr.getMessage(),
 
 529   //      // scanner.getCurrentTokenStartPosition(),
 
 530   //      // scanner.getCurrentTokenEndPosition(), ERROR);
 
 531   //      // } catch (CoreException e) {
 
 535   private void statementList() {
 
 537       statement(TokenNameEOF);
 
 538       if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse)
 
 539           || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor)
 
 540           || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch)
 
 541           || (token == TokenNameEOF) || (token == TokenNameERROR)) {
 
 546   private void functionBody(MethodDeclaration methodDecl) {
 
 547     // '{' [statement-list] '}'
 
 548     if (token == TokenNameLBRACE) {
 
 551       throwSyntaxError("'{' expected in compound-statement.");
 
 553     if (token != TokenNameRBRACE) {
 
 556     if (token == TokenNameRBRACE) {
 
 557       methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
 560       throwSyntaxError("'}' expected in compound-statement.");
 
 563   private void statement(int previousToken) {
 
 564     //   if (token > TokenNameKEYWORD && token != TokenNamelist && token !=
 
 566     //  char[] ident = scanner.getCurrentIdentifierSource();
 
 567     //  String keyword = new String(ident);
 
 568     //    if (token == TokenNameAT) {
 
 570     //      if (token != TokenNamerequire && token != TokenNamerequire_once
 
 571     //          && token != TokenNameinclude && token != TokenNameinclude_once
 
 572     //          && token != TokenNameIdentifier && token != TokenNameVariable
 
 573     //          && token != TokenNameStringInterpolated) {
 
 574     //        throwSyntaxError("identifier expected after '@'.");
 
 577     //    if (token == TokenNameinclude || token == TokenNameinclude_once) {
 
 579     //      if (token == TokenNameLPAREN) {
 
 581     //        if (token == TokenNameSEMICOLON) {
 
 584     //          if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
 
 585     //            throwSyntaxError("';' expected after 'include' or 'include_once'.");
 
 587     //          // getNextToken();
 
 590     //        concatenationExpression();
 
 593     //    } else if (token == TokenNamerequire || token ==
 
 594     // TokenNamerequire_once)
 
 598     //      if (token == TokenNameLPAREN) {
 
 600     //        if (token == TokenNameSEMICOLON) {
 
 603     //          if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
 
 604     //            throwSyntaxError("';' expected after 'require' or 'require_once'.");
 
 606     //          // getNextToken();
 
 609     //        concatenationExpression();
 
 613     if (token == TokenNameif) {
 
 615       if (token == TokenNameLPAREN) {
 
 618         throwSyntaxError("'(' expected after 'if' keyword.");
 
 621       if (token == TokenNameRPAREN) {
 
 624         throwSyntaxError("')' expected after 'if' condition.");
 
 628     } else if (token == TokenNameswitch) {
 
 630       if (token == TokenNameLPAREN) {
 
 633         throwSyntaxError("'(' expected after 'switch' keyword.");
 
 636       if (token == TokenNameRPAREN) {
 
 639         throwSyntaxError("')' expected after 'switch' condition.");
 
 643     } else if (token == TokenNamefor) {
 
 645       if (token == TokenNameLPAREN) {
 
 648         throwSyntaxError("'(' expected after 'for' keyword.");
 
 650       if (token == TokenNameSEMICOLON) {
 
 654         if (token == TokenNameSEMICOLON) {
 
 657           throwSyntaxError("';' expected after 'for'.");
 
 660       if (token == TokenNameSEMICOLON) {
 
 664         if (token == TokenNameSEMICOLON) {
 
 667           throwSyntaxError("';' expected after 'for'.");
 
 670       if (token == TokenNameRPAREN) {
 
 674         if (token == TokenNameRPAREN) {
 
 677           throwSyntaxError("')' expected after 'for'.");
 
 682     } else if (token == TokenNamewhile) {
 
 684       if (token == TokenNameLPAREN) {
 
 687         throwSyntaxError("'(' expected after 'while' keyword.");
 
 690       if (token == TokenNameRPAREN) {
 
 693         throwSyntaxError("')' expected after 'while' condition.");
 
 697     } else if (token == TokenNamedo) {
 
 699       if (token == TokenNameLBRACE) {
 
 701         if (token != TokenNameRBRACE) {
 
 704         if (token == TokenNameRBRACE) {
 
 707           throwSyntaxError("'}' expected after 'do' keyword.");
 
 710         statement(TokenNameEOF);
 
 712       if (token == TokenNamewhile) {
 
 714         if (token == TokenNameLPAREN) {
 
 717           throwSyntaxError("'(' expected after 'while' keyword.");
 
 720         if (token == TokenNameRPAREN) {
 
 723           throwSyntaxError("')' expected after 'while' condition.");
 
 726         throwSyntaxError("'while' expected after 'do' keyword.");
 
 728       if (token == TokenNameSEMICOLON) {
 
 731         if (token != TokenNameINLINE_HTML) {
 
 732           throwSyntaxError("';' expected after do-while statement.");
 
 737     } else if (token == TokenNameforeach) {
 
 739       if (token == TokenNameLPAREN) {
 
 742         throwSyntaxError("'(' expected after 'foreach' keyword.");
 
 745       if (token == TokenNameas) {
 
 748         throwSyntaxError("'as' expected after 'foreach' exxpression.");
 
 752       foreach_optional_arg();
 
 753       if (token == TokenNameEQUAL_GREATER) {
 
 757       if (token == TokenNameRPAREN) {
 
 760         throwSyntaxError("')' expected after 'foreach' expression.");
 
 764     } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
 
 766       if (token != TokenNameSEMICOLON) {
 
 769       if (token == TokenNameSEMICOLON) {
 
 772         if (token != TokenNameINLINE_HTML) {
 
 773           throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
 
 778     } else if (token == TokenNameecho) {
 
 781       if (token == TokenNameSEMICOLON) {
 
 784         if (token != TokenNameINLINE_HTML) {
 
 785           throwSyntaxError("';' expected after 'echo' statement.");
 
 790     } else if (token == TokenNameINLINE_HTML) {
 
 793       //    } else if (token == TokenNameprint) {
 
 796       //      if (token == TokenNameSEMICOLON) {
 
 799       //        if (token != TokenNameStopPHP) {
 
 800       //          throwSyntaxError("';' expected after 'print' statement.");
 
 805     } else if (token == TokenNameglobal) {
 
 808       if (token == TokenNameSEMICOLON) {
 
 811         if (token != TokenNameINLINE_HTML) {
 
 812           throwSyntaxError("';' expected after 'global' statement.");
 
 817     } else if (token == TokenNamestatic) {
 
 820       if (token == TokenNameSEMICOLON) {
 
 823         if (token != TokenNameINLINE_HTML) {
 
 824           throwSyntaxError("';' expected after 'static' statement.");
 
 829     } else if (token == TokenNameunset) {
 
 831       if (token == TokenNameLPAREN) {
 
 834         throwSyntaxError("'(' expected after 'unset' statement.");
 
 837       if (token == TokenNameRPAREN) {
 
 840         throwSyntaxError("')' expected after 'unset' statement.");
 
 842       if (token == TokenNameSEMICOLON) {
 
 845         if (token != TokenNameINLINE_HTML) {
 
 846           throwSyntaxError("';' expected after 'unset' statement.");
 
 851     } else if (token == TokenNamefunction) {
 
 852       MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
 
 853       methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
 855       functionDefinition(methodDecl);
 
 857     } else if (token == TokenNametry) {
 
 859       if (token != TokenNameLBRACE) {
 
 860         throwSyntaxError("'{' expected in 'try' statement.");
 
 864       if (token != TokenNameRBRACE) {
 
 865         throwSyntaxError("'}' expected in 'try' statement.");
 
 869     } else if (token == TokenNamecatch) {
 
 871       if (token != TokenNameLPAREN) {
 
 872         throwSyntaxError("'(' expected in 'catch' statement.");
 
 875       fully_qualified_class_name();
 
 876       if (token != TokenNameVariable) {
 
 877         throwSyntaxError("Variable expected in 'catch' statement.");
 
 880       if (token != TokenNameRPAREN) {
 
 881         throwSyntaxError("')' expected in 'catch' statement.");
 
 884       if (token != TokenNameLBRACE) {
 
 885         throwSyntaxError("'{' expected in 'catch' statement.");
 
 888       if (token != TokenNameRBRACE) {
 
 890         if (token != TokenNameRBRACE) {
 
 891           throwSyntaxError("'}' expected in 'catch' statement.");
 
 895       additional_catches();
 
 897     } else if (token == TokenNamethrow) {
 
 900       if (token == TokenNameSEMICOLON) {
 
 903         throwSyntaxError("';' expected after 'throw' exxpression.");
 
 906     } else if (token == TokenNamefinal || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) {
 
 907       TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
 
 908       typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
 909       // default super class
 
 910       typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
 
 911       compilationUnit.types.add(typeDecl);
 
 913         pushOnAstStack(typeDecl);
 
 914         unticked_class_declaration_statement(typeDecl);
 
 915         //        classBody(typeDecl);
 
 922       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
 
 923     } else if (token == TokenNameLBRACE) {
 
 925       if (token != TokenNameRBRACE) {
 
 928       if (token == TokenNameRBRACE) {
 
 932         throwSyntaxError("'}' expected.");
 
 935       if (token != TokenNameSEMICOLON) {
 
 938       if (token == TokenNameSEMICOLON) {
 
 942         if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
 
 943           throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
 
 949   private void additional_catches() {
 
 950     while (token == TokenNamecatch) {
 
 952       if (token != TokenNameLPAREN) {
 
 953         throwSyntaxError("'(' expected in 'catch' statement.");
 
 956       fully_qualified_class_name();
 
 957       if (token != TokenNameVariable) {
 
 958         throwSyntaxError("Variable expected in 'catch' statement.");
 
 961       if (token != TokenNameRPAREN) {
 
 962         throwSyntaxError("')' expected in 'catch' statement.");
 
 965       if (token != TokenNameLBRACE) {
 
 966         throwSyntaxError("'{' expected in 'catch' statement.");
 
 970       if (token != TokenNameRBRACE) {
 
 971         throwSyntaxError("'}' expected in 'catch' statement.");
 
 976   private void foreach_variable() {
 
 979     if (token == TokenNameAND) {
 
 984   private void foreach_optional_arg() {
 
 986     //| T_DOUBLE_ARROW foreach_variable
 
 987     if (token == TokenNameEQUAL_GREATER) {
 
 992   private void global_var_list() {
 
 994     //  global_var_list ',' global_var
 
 998       if (token != TokenNameCOMMA) {
 
1004   private void global_var() {
 
1008     //| '$' '{' expr '}'
 
1009     if (token == TokenNameVariable) {
 
1011     } else if (token == TokenNameDOLLAR) {
 
1013       if (token == TokenNameLPAREN) {
 
1016         if (token != TokenNameLPAREN) {
 
1017           throwSyntaxError("')' expected in global variable.");
 
1025   private void static_var_list() {
 
1027     //  static_var_list ',' T_VARIABLE
 
1028     //| static_var_list ',' T_VARIABLE '=' static_scalar
 
1030     //| T_VARIABLE '=' static_scalar
 
1032       if (token == TokenNameVariable) {
 
1034         if (token == TokenNameEQUAL) {
 
1038         if (token != TokenNameCOMMA) {
 
1047   private void unset_variables() {
 
1050     //          | unset_variables ',' unset_variable
 
1055       if (token != TokenNameCOMMA) {
 
1061   private final void initializeModifiers() {
 
1063     this.modifiersSourceStart = -1;
 
1065   private final void checkAndSetModifiers(int flag) {
 
1066     this.modifiers |= flag;
 
1067     if (this.modifiersSourceStart < 0)
 
1068       this.modifiersSourceStart = this.scanner.startPosition;
 
1070   private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
 
1071     initializeModifiers();
 
1072     if (token == TokenNameinterface) {
 
1073       //      interface_entry T_STRING
 
1074       //                interface_extends_list
 
1075       //                '{' class_statement_list '}'
 
1076       checkAndSetModifiers(AccInterface);
 
1078       typeDecl.modifiers = this.modifiers;
 
1079       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
 
1080         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1081         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1082         typeDecl.name = scanner.getCurrentIdentifierSource();
 
1083         if (token > TokenNameKEYWORD) {
 
1084           throwSyntaxError("Don't use a keyword for interface declaration [" + scanner.toStringAction(token) + "].",
 
1085               typeDecl.sourceStart, typeDecl.sourceEnd);
 
1088         interface_extends_list();
 
1090         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1091         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1092         typeDecl.name = new char[]{' '};
 
1093         throwSyntaxError("Interface name expected after keyword 'interface'.", typeDecl.sourceStart, typeDecl.sourceEnd);
 
1097       //      class_entry_type T_STRING extends_from
 
1099       //                '{' class_statement_list'}'
 
1101       typeDecl.modifiers = this.modifiers;
 
1103       //identifier 'extends' identifier
 
1104       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
 
1105         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1106         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1107         typeDecl.name = scanner.getCurrentIdentifierSource();
 
1108         if (token > TokenNameKEYWORD) {
 
1109           throwSyntaxError("Don't use a keyword for class declaration [" + scanner.toStringAction(token) + "].",
 
1110               typeDecl.sourceStart, typeDecl.sourceEnd);
 
1115         //      | T_EXTENDS fully_qualified_class_name
 
1116         if (token == TokenNameextends) {
 
1117           interface_extends_list();
 
1119           //          if (token != TokenNameIdentifier) {
 
1120           //            throwSyntaxError("Class name expected after keyword
 
1122           //                scanner.getCurrentTokenStartPosition(), scanner
 
1123           //                    .getCurrentTokenEndPosition());
 
1128         typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1129         typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1130         typeDecl.name = new char[]{' '};
 
1131         throwSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
 
1135     //  '{' class_statement_list '}'
 
1136     if (token == TokenNameLBRACE) {
 
1138       if (token != TokenNameRBRACE) {
 
1139         ArrayList list = new ArrayList();
 
1140         class_statement_list(list);
 
1141         typeDecl.fields = new FieldDeclaration[list.size()];
 
1142         for (int i = 0; i < list.size(); i++) {
 
1143           typeDecl.fields[i] = (FieldDeclaration) list.get(i);
 
1146       if (token == TokenNameRBRACE) {
 
1147         typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1150         throwSyntaxError("'}' expected at end of class body.");
 
1153       throwSyntaxError("'{' expected at start of class body.");
 
1156   private void class_entry_type() {
 
1158     //  | T_ABSTRACT T_CLASS
 
1159     //  | T_FINAL T_CLASS
 
1160     if (token == TokenNameclass) {
 
1162     } else if (token == TokenNameabstract) {
 
1163       checkAndSetModifiers(AccAbstract);
 
1165       if (token != TokenNameclass) {
 
1166         throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
 
1169     } else if (token == TokenNamefinal) {
 
1170       checkAndSetModifiers(AccFinal);
 
1172       if (token != TokenNameclass) {
 
1173         throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
 
1177       throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
 
1180   private void interface_extends_list() {
 
1182     //  | T_EXTENDS interface_list
 
1183     if (token == TokenNameextends) {
 
1188   private void implements_list() {
 
1190     //  | T_IMPLEMENTS interface_list
 
1191     if (token == TokenNameimplements) {
 
1196   private void interface_list() {
 
1198     //  fully_qualified_class_name
 
1199     //| interface_list ',' fully_qualified_class_name
 
1201       if (token == TokenNameIdentifier) {
 
1204         throwSyntaxError("Interface name expected after keyword 'implements'.");
 
1206       if (token != TokenNameCOMMA) {
 
1212   //  private void classBody(TypeDeclaration typeDecl) {
 
1213   //    //'{' [class-element-list] '}'
 
1214   //    if (token == TokenNameLBRACE) {
 
1216   //      if (token != TokenNameRBRACE) {
 
1217   //        class_statement_list();
 
1219   //      if (token == TokenNameRBRACE) {
 
1220   //        typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1223   //        throwSyntaxError("'}' expected at end of class body.");
 
1226   //      throwSyntaxError("'{' expected at start of class body.");
 
1229   private void class_statement_list(ArrayList list) {
 
1231       class_statement(list);
 
1232     } while (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic
 
1233         || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar
 
1234         || token == TokenNameconst);
 
1236   private void class_statement(ArrayList list) {
 
1238     //          variable_modifiers class_variable_declaration ';'
 
1239     //  | class_constant_declaration ';'
 
1240     //  | method_modifiers T_FUNCTION is_reference T_STRING
 
1241     //    '(' parameter_list ')' method_body
 
1242     initializeModifiers();
 
1243     int declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
1245     if (token == TokenNamevar) {
 
1246       checkAndSetModifiers(AccPublic);
 
1247       problemReporter.phpVarDeprecatedWarning(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
 
1248           referenceContext, compilationUnit.compilationResult);
 
1250       class_variable_declaration(declarationSourceStart, list);
 
1251     } else if (token == TokenNameconst) {
 
1252       class_constant_declaration();
 
1253       if (token != TokenNameSEMICOLON) {
 
1254         throwSyntaxError("';' expected after class const declaration.");
 
1258       boolean hasModifiers = member_modifiers();
 
1259       if (token == TokenNamefunction) {
 
1260         if (!hasModifiers) {
 
1261           checkAndSetModifiers(AccPublic);
 
1263         MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
 
1264         methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
1265         methodDecl.modifiers = this.modifiers;
 
1267         functionDefinition(methodDecl);
 
1269         if (!hasModifiers) {
 
1270           throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
 
1272         class_variable_declaration(declarationSourceStart, list);
 
1275     //    if (token == TokenNamefunction) {
 
1276     //      MethodDeclaration methodDecl = new MethodDeclaration(
 
1277     //          this.compilationUnit.compilationResult);
 
1278     //      methodDecl.declarationSourceStart = scanner
 
1279     //          .getCurrentTokenStartPosition();
 
1281     //      functionDefinition(methodDecl);
 
1282     //    } else if (token == TokenNamevar) {
 
1286     //      throwSyntaxError("'function' or 'var' expected.");
 
1289   private void class_constant_declaration() {
 
1290     //  class_constant_declaration ',' T_STRING '=' static_scalar
 
1291     //  | T_CONST T_STRING '=' static_scalar
 
1292     if (token != TokenNameconst) {
 
1293       throwSyntaxError("'const' keyword expected in class declaration.");
 
1298       if (token != TokenNameIdentifier) {
 
1299         throwSyntaxError("Identifier expected in class const declaration.");
 
1302       if (token != TokenNameEQUAL) {
 
1303         throwSyntaxError("'=' expected in class const declaration.");
 
1307       if (token != TokenNameCOMMA) {
 
1308         break; // while(true)-loop
 
1313   //  private void variable_modifiers() {
 
1314   //    // variable_modifiers:
 
1315   //    // non_empty_member_modifiers
 
1317   //    initializeModifiers();
 
1318   //    if (token == TokenNamevar) {
 
1319   //      checkAndSetModifiers(AccPublic);
 
1320   //      reportSyntaxError(
 
1321   //          "Keyword 'var' is deprecated. Please use 'public' 'private' or
 
1323   // modifier for field declarations.",
 
1324   //          scanner.getCurrentTokenStartPosition(), scanner
 
1325   //              .getCurrentTokenEndPosition());
 
1328   //      if (!member_modifiers()) {
 
1329   //        throwSyntaxError("'public' 'private' or 'protected' modifier expected for
 
1330   // field declarations.");
 
1334   //  private void method_modifiers() {
 
1335   //    //method_modifiers:
 
1337   //    //| non_empty_member_modifiers
 
1338   //    initializeModifiers();
 
1339   //    if (!member_modifiers()) {
 
1340   //      checkAndSetModifiers(AccPublic);
 
1343   private boolean member_modifiers() {
 
1350     boolean foundToken = false;
 
1352       if (token == TokenNamepublic) {
 
1353         checkAndSetModifiers(AccPublic);
 
1356       } else if (token == TokenNameprotected) {
 
1357         checkAndSetModifiers(AccProtected);
 
1360       } else if (token == TokenNameprivate) {
 
1361         checkAndSetModifiers(AccPrivate);
 
1364       } else if (token == TokenNamestatic) {
 
1365         checkAndSetModifiers(AccStatic);
 
1368       } else if (token == TokenNameabstract) {
 
1369         checkAndSetModifiers(AccAbstract);
 
1372       } else if (token == TokenNamefinal) {
 
1373         checkAndSetModifiers(AccFinal);
 
1382   private void class_variable_declaration(int declarationSourceStart, ArrayList list) {
 
1383     //    class_variable_declaration:
 
1384     //          class_variable_declaration ',' T_VARIABLE
 
1385     //  | class_variable_declaration ',' T_VARIABLE '=' static_scalar
 
1387     //  | T_VARIABLE '=' static_scalar
 
1389       if (token == TokenNameVariable) {
 
1390         FieldDeclaration fieldDeclaration = new FieldDeclaration(scanner.getCurrentIdentifierSource(), scanner
 
1391             .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
 
1392         fieldDeclaration.modifiers = this.modifiers;
 
1393         fieldDeclaration.declarationSourceStart = declarationSourceStart;
 
1394         fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1395         fieldDeclaration.modifiersSourceStart = declarationSourceStart;
 
1396         //        fieldDeclaration.type
 
1397         list.add(fieldDeclaration);
 
1399         if (token == TokenNameEQUAL) {
 
1404         //        if (token == TokenNamethis) {
 
1405         //          throwSyntaxError("'$this' not allowed after keyword 'public'
 
1406         // 'protected' 'private' 'var'.");
 
1408         throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
 
1410       if (token != TokenNameCOMMA) {
 
1415     if (token != TokenNameSEMICOLON) {
 
1416       throwSyntaxError("';' expected after field declaration.");
 
1420   private void functionDefinition(MethodDeclaration methodDecl) {
 
1421     boolean isAbstract = false;
 
1423       compilationUnit.types.add(methodDecl);
 
1425       AstNode node = astStack[astPtr];
 
1426       if (node instanceof TypeDeclaration) {
 
1427         TypeDeclaration typeDecl = ((TypeDeclaration) node);
 
1428         if (typeDecl.methods == null) {
 
1429           typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
 
1431           AbstractMethodDeclaration[] newMethods;
 
1432           System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1,
 
1433               typeDecl.methods.length);
 
1434           newMethods[0] = methodDecl;
 
1435           typeDecl.methods = newMethods;
 
1437         if ((typeDecl.modifiers & AccAbstract) == AccAbstract) {
 
1439         } else if ((typeDecl.modifiers & AccInterface) == AccInterface) {
 
1444     functionDeclarator(methodDecl);
 
1445     if (token == TokenNameSEMICOLON) {
 
1447         throwSyntaxError("Body declaration expected for method: " + new String(methodDecl.selector));
 
1452     functionBody(methodDecl);
 
1454   private void functionDeclarator(MethodDeclaration methodDecl) {
 
1455     //identifier '(' [parameter-list] ')'
 
1456     if (token == TokenNameAND) {
 
1459     if (token == TokenNameIdentifier) {
 
1460       methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1461       methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1462       methodDecl.selector = scanner.getCurrentIdentifierSource();
 
1464       if (token == TokenNameLPAREN) {
 
1467         throwSyntaxError("'(' expected in function declaration.");
 
1469       if (token != TokenNameRPAREN) {
 
1472       if (token != TokenNameRPAREN) {
 
1473         throwSyntaxError("')' expected in function declaration.");
 
1475         methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
 
1479       if (token > TokenNameKEYWORD) {
 
1480         throwSyntaxError("Don't use keyword for function declaration [" + token + "].");
 
1482       throwSyntaxError("Function name expected after keyword 'function'.");
 
1486   private void parameter_list() {
 
1487     //  non_empty_parameter_list
 
1489     non_empty_parameter_list(true);
 
1491   private void non_empty_parameter_list(boolean empty_allowed) {
 
1492     //  optional_class_type T_VARIABLE
 
1493     //  | optional_class_type '&' T_VARIABLE
 
1494     //  | optional_class_type '&' T_VARIABLE '=' static_scalar
 
1495     //  | optional_class_type T_VARIABLE '=' static_scalar
 
1496     //  | non_empty_parameter_list ',' optional_class_type T_VARIABLE
 
1497     //  | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
 
1498     //  | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
 
1500     //  | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
 
1502     if (token == TokenNameIdentifier || token == TokenNameVariable || token == TokenNameAND) {
 
1504         if (token == TokenNameIdentifier) {
 
1507         if (token == TokenNameAND) {
 
1510         if (token == TokenNameVariable) {
 
1512           if (token == TokenNameEQUAL) {
 
1517           throwSyntaxError("Variable expected in parameter list.");
 
1519         if (token != TokenNameCOMMA) {
 
1526     if (!empty_allowed) {
 
1527       throwSyntaxError("Identifier expected in parameter list.");
 
1530   private void optional_class_type() {
 
1534   private void parameterDeclaration() {
 
1536     //variable-reference
 
1537     if (token == TokenNameAND) {
 
1542         throwSyntaxError("Variable expected after reference operator '&'.");
 
1545     //variable '=' constant
 
1546     if (token == TokenNameVariable) {
 
1548       if (token == TokenNameEQUAL) {
 
1554     //    if (token == TokenNamethis) {
 
1555     //      throwSyntaxError("Reserved word '$this' not allowed in parameter
 
1559   private void labeledStatementList() {
 
1560     if (token != TokenNamecase && token != TokenNamedefault) {
 
1561       throwSyntaxError("'case' or 'default' expected.");
 
1564       if (token == TokenNamecase) {
 
1566         expr(); //constant();
 
1567         if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
 
1569           if (token == TokenNamecase || token == TokenNamedefault) {
 
1570             // empty case statement ?
 
1575         //        else if (token == TokenNameSEMICOLON) {
 
1577         //            "':' expected after 'case' keyword (Found token: " +
 
1578         // scanner.toStringAction(token) + ")",
 
1579         //            scanner.getCurrentTokenStartPosition(),
 
1580         //            scanner.getCurrentTokenEndPosition(),
 
1583         //          if (token == TokenNamecase) { // empty case statement ?
 
1589           throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
 
1591       } else { // TokenNamedefault
 
1593         if (token == TokenNameCOLON) {
 
1595           if (token == TokenNameRBRACE) {
 
1596             // empty default case
 
1601           throwSyntaxError("':' character after 'default' expected.");
 
1604     } while (token == TokenNamecase || token == TokenNamedefault);
 
1606   //  public void labeledStatement() {
 
1607   //    if (token == TokenNamecase) {
 
1610   //      if (token == TokenNameDDOT) {
 
1614   //        throwSyntaxError("':' character after 'case' constant expected.");
 
1617   //    } else if (token == TokenNamedefault) {
 
1619   //      if (token == TokenNameDDOT) {
 
1623   //        throwSyntaxError("':' character after 'default' expected.");
 
1628   //  public void expressionStatement() {
 
1630   //  private void inclusionStatement() {
 
1632   //  public void compoundStatement() {
 
1634   //  public void selectionStatement() {
 
1637   //  public void iterationStatement() {
 
1640   //  public void jumpStatement() {
 
1643   //  public void outputStatement() {
 
1646   //  public void scopeStatement() {
 
1649   //  public void flowStatement() {
 
1652   //  public void definitionStatement() {
 
1654   private void ifStatement() {
 
1655     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
 
1656     if (token == TokenNameCOLON) {
 
1658       if (token != TokenNameendif) {
 
1661           case TokenNameelse :
 
1663             if (token == TokenNameCOLON) {
 
1665               if (token != TokenNameendif) {
 
1669               if (token == TokenNameif) { //'else if'
 
1671                 elseifStatementList();
 
1673                 throwSyntaxError("':' expected after 'else'.");
 
1677           case TokenNameelseif :
 
1679             elseifStatementList();
 
1683       if (token != TokenNameendif) {
 
1684         throwSyntaxError("'endif' expected.");
 
1687       if (token != TokenNameSEMICOLON) {
 
1688         throwSyntaxError("';' expected after if-statement.");
 
1692       // statement [else-statement]
 
1693       statement(TokenNameEOF);
 
1694       if (token == TokenNameelseif) {
 
1696         if (token == TokenNameLPAREN) {
 
1699           throwSyntaxError("'(' expected after 'elseif' keyword.");
 
1702         if (token == TokenNameRPAREN) {
 
1705           throwSyntaxError("')' expected after 'elseif' condition.");
 
1708       } else if (token == TokenNameelse) {
 
1710         statement(TokenNameEOF);
 
1714   private void elseifStatementList() {
 
1718         case TokenNameelse :
 
1720           if (token == TokenNameCOLON) {
 
1722             if (token != TokenNameendif) {
 
1727             if (token == TokenNameif) { //'else if'
 
1730               throwSyntaxError("':' expected after 'else'.");
 
1734         case TokenNameelseif :
 
1742   private void elseifStatement() {
 
1743     if (token == TokenNameLPAREN) {
 
1746       if (token != TokenNameRPAREN) {
 
1747         throwSyntaxError("')' expected in else-if-statement.");
 
1750       if (token != TokenNameCOLON) {
 
1751         throwSyntaxError("':' expected in else-if-statement.");
 
1754       if (token != TokenNameendif) {
 
1759   private void switchStatement() {
 
1760     if (token == TokenNameCOLON) {
 
1761       // ':' [labeled-statement-list] 'endswitch' ';'
 
1763       labeledStatementList();
 
1764       if (token != TokenNameendswitch) {
 
1765         throwSyntaxError("'endswitch' expected.");
 
1768       if (token != TokenNameSEMICOLON) {
 
1769         throwSyntaxError("';' expected after switch-statement.");
 
1773       // '{' [labeled-statement-list] '}'
 
1774       if (token != TokenNameLBRACE) {
 
1775         throwSyntaxError("'{' expected in switch statement.");
 
1778       if (token != TokenNameRBRACE) {
 
1779         labeledStatementList();
 
1781       if (token != TokenNameRBRACE) {
 
1782         throwSyntaxError("'}' expected in switch statement.");
 
1787   private void forStatement() {
 
1788     if (token == TokenNameCOLON) {
 
1791       if (token != TokenNameendfor) {
 
1792         throwSyntaxError("'endfor' expected.");
 
1795       if (token != TokenNameSEMICOLON) {
 
1796         throwSyntaxError("';' expected after for-statement.");
 
1800       statement(TokenNameEOF);
 
1803   private void whileStatement() {
 
1804     // ':' statement-list 'endwhile' ';'
 
1805     if (token == TokenNameCOLON) {
 
1808       if (token != TokenNameendwhile) {
 
1809         throwSyntaxError("'endwhile' expected.");
 
1812       if (token != TokenNameSEMICOLON) {
 
1813         throwSyntaxError("';' expected after while-statement.");
 
1817       statement(TokenNameEOF);
 
1820   private void foreachStatement() {
 
1821     if (token == TokenNameCOLON) {
 
1824       if (token != TokenNameendforeach) {
 
1825         throwSyntaxError("'endforeach' expected.");
 
1828       if (token != TokenNameSEMICOLON) {
 
1829         throwSyntaxError("';' expected after foreach-statement.");
 
1833       statement(TokenNameEOF);
 
1836   //  private void exitStatus() {
 
1837   //    if (token == TokenNameLPAREN) {
 
1840   //      throwSyntaxError("'(' expected in 'exit-status'.");
 
1842   //    if (token != TokenNameRPAREN) {
 
1845   //    if (token == TokenNameRPAREN) {
 
1848   //      throwSyntaxError("')' expected after 'exit-status'.");
 
1851   private void expressionList() {
 
1854       if (token == TokenNameCOMMA) {
 
1861   private void expr() {
 
1863     //  | expr_without_variable
 
1864     //    if (token!=TokenNameEOF) {
 
1865     if (Scanner.TRACE) {
 
1866       System.out.println("TRACE: expr()");
 
1868     expr_without_variable(true);
 
1871   private void expr_without_variable(boolean only_variable) {
 
1872     //          internal_functions_in_yacc
 
1881     //  | T_INC rw_variable
 
1882     //  | T_DEC rw_variable
 
1883     //  | T_INT_CAST expr
 
1884     //  | T_DOUBLE_CAST expr
 
1885     //  | T_STRING_CAST expr
 
1886     //  | T_ARRAY_CAST expr
 
1887     //  | T_OBJECT_CAST expr
 
1888     //  | T_BOOL_CAST expr
 
1889     //  | T_UNSET_CAST expr
 
1890     //  | T_EXIT exit_expr
 
1892     //  | T_ARRAY '(' array_pair_list ')'
 
1893     //  | '`' encaps_list '`'
 
1894     //  | T_LIST '(' assignment_list ')' '=' expr
 
1895     //  | T_NEW class_name_reference ctor_arguments
 
1896     //  | variable '=' expr
 
1897     //  | variable '=' '&' variable
 
1898     //  | variable '=' '&' T_NEW class_name_reference ctor_arguments
 
1899     //  | variable T_PLUS_EQUAL expr
 
1900     //  | variable T_MINUS_EQUAL expr
 
1901     //  | variable T_MUL_EQUAL expr
 
1902     //  | variable T_DIV_EQUAL expr
 
1903     //  | variable T_CONCAT_EQUAL expr
 
1904     //  | variable T_MOD_EQUAL expr
 
1905     //  | variable T_AND_EQUAL expr
 
1906     //  | variable T_OR_EQUAL expr
 
1907     //  | variable T_XOR_EQUAL expr
 
1908     //  | variable T_SL_EQUAL expr
 
1909     //  | variable T_SR_EQUAL expr
 
1910     //  | rw_variable T_INC
 
1911     //  | rw_variable T_DEC
 
1912     //  | expr T_BOOLEAN_OR expr
 
1913     //  | expr T_BOOLEAN_AND expr
 
1914     //  | expr T_LOGICAL_OR expr
 
1915     //  | expr T_LOGICAL_AND expr
 
1916     //  | expr T_LOGICAL_XOR expr
 
1928     //  | expr T_IS_IDENTICAL expr
 
1929     //  | expr T_IS_NOT_IDENTICAL expr
 
1930     //  | expr T_IS_EQUAL expr
 
1931     //  | expr T_IS_NOT_EQUAL expr
 
1933     //  | expr T_IS_SMALLER_OR_EQUAL expr
 
1935     //  | expr T_IS_GREATER_OR_EQUAL expr
 
1936     //  | expr T_INSTANCEOF class_name_reference
 
1937     //  | expr '?' expr ':' expr
 
1938     if (Scanner.TRACE) {
 
1939       System.out.println("TRACE: expr_without_variable() PART 1");
 
1942       case TokenNameisset :
 
1943       case TokenNameempty :
 
1944       case TokenNameeval :
 
1945       case TokenNameinclude :
 
1946       case TokenNameinclude_once :
 
1947       case TokenNamerequire :
 
1948       case TokenNamerequire_once :
 
1949         internal_functions_in_yacc();
 
1952       case TokenNameLPAREN :
 
1955         if (token == TokenNameRPAREN) {
 
1958           throwSyntaxError("')' expected in expression.");
 
1968       //    | T_INT_CAST expr
 
1969       //        | T_DOUBLE_CAST expr
 
1970       //        | T_STRING_CAST expr
 
1971       //        | T_ARRAY_CAST expr
 
1972       //        | T_OBJECT_CAST expr
 
1973       //        | T_BOOL_CAST expr
 
1974       //        | T_UNSET_CAST expr
 
1975       case TokenNameclone :
 
1976       case TokenNameprint :
 
1978       case TokenNamePLUS :
 
1979       case TokenNameMINUS :
 
1981       case TokenNameTWIDDLE :
 
1982       case TokenNameintCAST :
 
1983       case TokenNamedoubleCAST :
 
1984       case TokenNamestringCAST :
 
1985       case TokenNamearrayCAST :
 
1986       case TokenNameobjectCAST :
 
1987       case TokenNameboolCAST :
 
1988       case TokenNameunsetCAST :
 
1992       case TokenNameexit :
 
1998       //| T_STRING_VARNAME
 
2000       //| T_START_HEREDOC encaps_list T_END_HEREDOC
 
2001       //        | '`' encaps_list '`'
 
2003       //        | '`' encaps_list '`'
 
2004       case TokenNameEncapsedString0 :
 
2005         scanner.encapsedStringStack.push(new Character('`'));
 
2008           if (token == TokenNameEncapsedString0) {
 
2011             if (token != TokenNameEncapsedString0) {
 
2012               throwSyntaxError("\'`\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
 
2016           scanner.encapsedStringStack.pop();
 
2020       //      | '\'' encaps_list '\''
 
2021       case TokenNameEncapsedString1 :
 
2022         scanner.encapsedStringStack.push(new Character('\''));
 
2025           if (token == TokenNameEncapsedString1) {
 
2028             if (token != TokenNameEncapsedString1) {
 
2029               throwSyntaxError("\'\'\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
 
2033           scanner.encapsedStringStack.pop();
 
2037       //| '"' encaps_list '"'
 
2038       case TokenNameEncapsedString2 :
 
2039         scanner.encapsedStringStack.push(new Character('"'));
 
2042           if (token == TokenNameEncapsedString2) {
 
2045             if (token != TokenNameEncapsedString2) {
 
2046               throwSyntaxError("'\"' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
 
2050           scanner.encapsedStringStack.pop();
 
2054       case TokenNameIntegerLiteral :
 
2055       case TokenNameDoubleLiteral :
 
2056       case TokenNameStringLiteral :
 
2057       case TokenNameStringConstant :
 
2058       case TokenNameStringInterpolated :
 
2059       case TokenNameFILE :
 
2060       case TokenNameLINE :
 
2061       case TokenNameCLASS_C :
 
2062       case TokenNameMETHOD_C :
 
2063       case TokenNameFUNC_C :
 
2066       case TokenNameHEREDOC :
 
2069       case TokenNamearray :
 
2070         //    T_ARRAY '(' array_pair_list ')'
 
2072         if (token == TokenNameLPAREN) {
 
2074           if (token == TokenNameRPAREN) {
 
2079           if (token != TokenNameRPAREN) {
 
2080             throwSyntaxError("')' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
 
2084           throwSyntaxError("'(' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
 
2087       case TokenNamelist :
 
2088         //    | T_LIST '(' assignment_list ')' '=' expr
 
2090         if (token == TokenNameLPAREN) {
 
2093           if (token != TokenNameRPAREN) {
 
2094             throwSyntaxError("')' expected after 'list' keyword.");
 
2097           if (token != TokenNameEQUAL) {
 
2098             throwSyntaxError("'=' expected after 'list' keyword.");
 
2103           throwSyntaxError("'(' expected after 'list' keyword.");
 
2107         //      | T_NEW class_name_reference ctor_arguments
 
2109         class_name_reference();
 
2112       //        | T_INC rw_variable
 
2113       //        | T_DEC rw_variable
 
2114       case TokenNamePLUS_PLUS :
 
2115       case TokenNameMINUS_MINUS :
 
2119       //        | variable '=' expr
 
2120       //        | variable '=' '&' variable
 
2121       //        | variable '=' '&' T_NEW class_name_reference ctor_arguments
 
2122       //        | variable T_PLUS_EQUAL expr
 
2123       //        | variable T_MINUS_EQUAL expr
 
2124       //        | variable T_MUL_EQUAL expr
 
2125       //        | variable T_DIV_EQUAL expr
 
2126       //        | variable T_CONCAT_EQUAL expr
 
2127       //        | variable T_MOD_EQUAL expr
 
2128       //        | variable T_AND_EQUAL expr
 
2129       //        | variable T_OR_EQUAL expr
 
2130       //        | variable T_XOR_EQUAL expr
 
2131       //        | variable T_SL_EQUAL expr
 
2132       //        | variable T_SR_EQUAL expr
 
2133       //        | rw_variable T_INC
 
2134       //        | rw_variable T_DEC
 
2135       case TokenNameIdentifier :
 
2136       case TokenNameVariable :
 
2137       case TokenNameDOLLAR :
 
2140           case TokenNameEQUAL :
 
2142             if (token == TokenNameAND) {
 
2144               if (token == TokenNamenew) {
 
2145                 // | variable '=' '&' T_NEW class_name_reference
 
2148                 class_name_reference();
 
2157           case TokenNamePLUS_EQUAL :
 
2158           case TokenNameMINUS_EQUAL :
 
2159           case TokenNameMULTIPLY_EQUAL :
 
2160           case TokenNameDIVIDE_EQUAL :
 
2161           case TokenNameDOT_EQUAL :
 
2162           case TokenNameREMAINDER_EQUAL :
 
2163           case TokenNameAND_EQUAL :
 
2164           case TokenNameOR_EQUAL :
 
2165           case TokenNameXOR_EQUAL :
 
2166           case TokenNameRIGHT_SHIFT_EQUAL :
 
2167           case TokenNameLEFT_SHIFT_EQUAL :
 
2171           case TokenNamePLUS_PLUS :
 
2172           case TokenNameMINUS_MINUS :
 
2176             if (!only_variable) {
 
2177               throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "').");
 
2182         if (token != TokenNameINLINE_HTML) {
 
2183           if (token > TokenNameKEYWORD) {
 
2187             throwSyntaxError("Error in expression (found token '" + scanner.toStringAction(token) + "').");
 
2192     if (Scanner.TRACE) {
 
2193       System.out.println("TRACE: expr_without_variable() PART 2");
 
2195     //  | expr T_BOOLEAN_OR expr
 
2196     //  | expr T_BOOLEAN_AND expr
 
2197     //  | expr T_LOGICAL_OR expr
 
2198     //  | expr T_LOGICAL_AND expr
 
2199     //  | expr T_LOGICAL_XOR expr
 
2211     //  | expr T_IS_IDENTICAL expr
 
2212     //  | expr T_IS_NOT_IDENTICAL expr
 
2213     //  | expr T_IS_EQUAL expr
 
2214     //  | expr T_IS_NOT_EQUAL expr
 
2216     //  | expr T_IS_SMALLER_OR_EQUAL expr
 
2218     //  | expr T_IS_GREATER_OR_EQUAL expr
 
2221         case TokenNameOR_OR :
 
2222         case TokenNameAND_AND :
 
2230         case TokenNamePLUS :
 
2231         case TokenNameMINUS :
 
2232         case TokenNameMULTIPLY :
 
2233         case TokenNameDIVIDE :
 
2234         case TokenNameREMAINDER :
 
2235         case TokenNameLEFT_SHIFT :
 
2236         case TokenNameRIGHT_SHIFT :
 
2237         case TokenNameEQUAL_EQUAL_EQUAL :
 
2238         case TokenNameNOT_EQUAL_EQUAL :
 
2239         case TokenNameEQUAL_EQUAL :
 
2240         case TokenNameNOT_EQUAL :
 
2241         case TokenNameLESS :
 
2242         case TokenNameLESS_EQUAL :
 
2243         case TokenNameGREATER :
 
2244         case TokenNameGREATER_EQUAL :
 
2248         //  | expr T_INSTANCEOF class_name_reference
 
2249         //      | expr '?' expr ':' expr
 
2250         case TokenNameinstanceof :
 
2252           class_name_reference();
 
2254         case TokenNameQUESTION :
 
2257           if (token == TokenNameCOLON) {
 
2267   private void class_name_reference() {
 
2268     //  class_name_reference:
 
2270     //| dynamic_class_name_reference
 
2271     if (Scanner.TRACE) {
 
2272       System.out.println("TRACE: class_name_reference()");
 
2274     if (token == TokenNameIdentifier) {
 
2277       dynamic_class_name_reference();
 
2280   private void dynamic_class_name_reference() {
 
2281     //dynamic_class_name_reference:
 
2282     //  base_variable T_OBJECT_OPERATOR object_property
 
2283     // dynamic_class_name_variable_properties
 
2285     if (Scanner.TRACE) {
 
2286       System.out.println("TRACE: dynamic_class_name_reference()");
 
2289     if (token == TokenNameMINUS_GREATER) {
 
2292       dynamic_class_name_variable_properties();
 
2295   private void dynamic_class_name_variable_properties() {
 
2296     //  dynamic_class_name_variable_properties:
 
2297     //                  dynamic_class_name_variable_properties
 
2298     // dynamic_class_name_variable_property
 
2300     if (Scanner.TRACE) {
 
2301       System.out.println("TRACE: dynamic_class_name_variable_properties()");
 
2303     while (token == TokenNameMINUS_GREATER) {
 
2304       dynamic_class_name_variable_property();
 
2307   private void dynamic_class_name_variable_property() {
 
2308     //  dynamic_class_name_variable_property:
 
2309     //  T_OBJECT_OPERATOR object_property
 
2310     if (Scanner.TRACE) {
 
2311       System.out.println("TRACE: dynamic_class_name_variable_property()");
 
2313     if (token == TokenNameMINUS_GREATER) {
 
2318   private void ctor_arguments() {
 
2321     //| '(' function_call_parameter_list ')'
 
2322     if (token == TokenNameLPAREN) {
 
2324       if (token == TokenNameRPAREN) {
 
2328       non_empty_function_call_parameter_list();
 
2329       if (token != TokenNameRPAREN) {
 
2330         throwSyntaxError("')' expected in ctor_arguments.");
 
2335   private void assignment_list() {
 
2337     //  assignment_list ',' assignment_list_element
 
2338     //| assignment_list_element
 
2340       assignment_list_element();
 
2341       if (token != TokenNameCOMMA) {
 
2347   private void assignment_list_element() {
 
2348     //assignment_list_element:
 
2350     //| T_LIST '(' assignment_list ')'
 
2352     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
 
2355       if (token == TokenNamelist) {
 
2357         if (token == TokenNameLPAREN) {
 
2360           if (token != TokenNameRPAREN) {
 
2361             throwSyntaxError("')' expected after 'list' keyword.");
 
2365           throwSyntaxError("'(' expected after 'list' keyword.");
 
2370   private void array_pair_list() {
 
2373     //| non_empty_array_pair_list possible_comma
 
2374     non_empty_array_pair_list();
 
2375     if (token == TokenNameCOMMA) {
 
2379   private void non_empty_array_pair_list() {
 
2380     //non_empty_array_pair_list:
 
2381     //  non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
 
2382     //| non_empty_array_pair_list ',' expr
 
2383     //| expr T_DOUBLE_ARROW expr
 
2385     //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
 
2386     //| non_empty_array_pair_list ',' '&' w_variable
 
2387     //| expr T_DOUBLE_ARROW '&' w_variable
 
2390       if (token == TokenNameAND) {
 
2395         if (token == TokenNameAND) {
 
2398         } else if (token == TokenNameEQUAL_GREATER) {
 
2400           if (token == TokenNameAND) {
 
2408       if (token != TokenNameCOMMA) {
 
2412       if (token == TokenNameRPAREN) {
 
2417   //  private void variableList() {
 
2420   //      if (token == TokenNameCOMMA) {
 
2427   private void variable_without_objects() {
 
2428     //  variable_without_objects:
 
2429     //                  reference_variable
 
2430     //          | simple_indirect_reference reference_variable
 
2431     if (Scanner.TRACE) {
 
2432       System.out.println("TRACE: variable_without_objects()");
 
2434     while (token == TokenNameDOLLAR) {
 
2437     reference_variable();
 
2439   private void function_call() {
 
2441     //  T_STRING '(' function_call_parameter_list ')'
 
2442     //| class_constant '(' function_call_parameter_list ')'
 
2443     //| static_member '(' function_call_parameter_list ')'
 
2444     //| variable_without_objects '(' function_call_parameter_list ')'
 
2445     if (Scanner.TRACE) {
 
2446       System.out.println("TRACE: function_call()");
 
2448     if (token == TokenNameIdentifier) {
 
2451         case TokenNamePAAMAYIM_NEKUDOTAYIM :
 
2454           if (token == TokenNameIdentifier) {
 
2459             variable_without_objects();
 
2464       variable_without_objects();
 
2466     if (token != TokenNameLPAREN) {
 
2467       // TODO is this ok ?
 
2469       //      throwSyntaxError("'(' expected in function call.");
 
2472     if (token == TokenNameRPAREN) {
 
2476     non_empty_function_call_parameter_list();
 
2477     if (token != TokenNameRPAREN) {
 
2478       throwSyntaxError("')' expected in function call.");
 
2482   //  private void function_call_parameter_list() {
 
2483   //    function_call_parameter_list:
 
2484   //            non_empty_function_call_parameter_list { $$ = $1; }
 
2487   private void non_empty_function_call_parameter_list() {
 
2488     //non_empty_function_call_parameter_list:
 
2489     //          expr_without_variable
 
2492     //  | non_empty_function_call_parameter_list ',' expr_without_variable
 
2493     //  | non_empty_function_call_parameter_list ',' variable
 
2494     //  | non_empty_function_call_parameter_list ',' '&' w_variable
 
2495     if (Scanner.TRACE) {
 
2496       System.out.println("TRACE: non_empty_function_call_parameter_list()");
 
2499       if (token == TokenNameAND) {
 
2503         //        if (token == TokenNameIdentifier || token ==
 
2504         // TokenNameVariable
 
2505         //            || token == TokenNameDOLLAR) {
 
2508         expr_without_variable(true);
 
2511       if (token != TokenNameCOMMA) {
 
2517   private void fully_qualified_class_name() {
 
2518     if (token == TokenNameIdentifier) {
 
2521       throwSyntaxError("Class name expected.");
 
2524   private void static_member() {
 
2526     //  fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
 
2527     // variable_without_objects
 
2528     if (Scanner.TRACE) {
 
2529       System.out.println("TRACE: static_member()");
 
2531     fully_qualified_class_name();
 
2532     if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
 
2533       throwSyntaxError("'::' expected after class name (static_member).");
 
2536     variable_without_objects();
 
2538   private void base_variable_with_function_calls() {
 
2539     //  base_variable_with_function_calls:
 
2542     boolean functionCall = false;
 
2543     if (Scanner.TRACE) {
 
2544       System.out.println("TRACE: base_variable_with_function_calls()");
 
2546     //    if (token == TokenNameIdentifier) {
 
2547     //      functionCall = true;
 
2548     //    } else if (token == TokenNameVariable) {
 
2549     //      int tempToken = token;
 
2550     //      int tempPosition = scanner.currentPosition;
 
2552     //      if (token == TokenNameLPAREN) {
 
2553     //        functionCall = true;
 
2555     //      token = tempToken;
 
2556     //      scanner.currentPosition = tempPosition;
 
2557     //      scanner.phpMode = true;
 
2559     //    if (functionCall) {
 
2565   private void base_variable() {
 
2567     //                  reference_variable
 
2568     //          | simple_indirect_reference reference_variable
 
2570     if (Scanner.TRACE) {
 
2571       System.out.println("TRACE: base_variable()");
 
2573     if (token == TokenNameIdentifier) {
 
2576       while (token == TokenNameDOLLAR) {
 
2579       reference_variable();
 
2582   //  private void simple_indirect_reference() {
 
2583   //    // simple_indirect_reference:
 
2585   //    //| simple_indirect_reference '$'
 
2587   private void reference_variable() {
 
2588     //  reference_variable:
 
2589     //                  reference_variable '[' dim_offset ']'
 
2590     //          | reference_variable '{' expr '}'
 
2591     //          | compound_variable
 
2592     if (Scanner.TRACE) {
 
2593       System.out.println("TRACE: reference_variable()");
 
2595     compound_variable();
 
2597       if (token == TokenNameLBRACE) {
 
2600         if (token != TokenNameRBRACE) {
 
2601           throwSyntaxError("'}' expected in reference variable.");
 
2604       } else if (token == TokenNameLBRACKET) {
 
2606         if (token != TokenNameRBRACKET) {
 
2609           if (token != TokenNameRBRACKET) {
 
2610             throwSyntaxError("']' expected in reference variable.");
 
2619   private void compound_variable() {
 
2620     //  compound_variable:
 
2622     //          | '$' '{' expr '}'
 
2623     if (Scanner.TRACE) {
 
2624       System.out.println("TRACE: compound_variable()");
 
2626     if (token == TokenNameVariable) {
 
2629       // because of simple_indirect_reference
 
2630       while (token == TokenNameDOLLAR) {
 
2633       if (token != TokenNameLBRACE) {
 
2634         throwSyntaxError("'{' expected after compound variable token '$'.");
 
2638       if (token != TokenNameRBRACE) {
 
2639         throwSyntaxError("'}' expected after compound variable token '$'.");
 
2644   //  private void dim_offset() {
 
2650   private void object_property() {
 
2653     //| variable_without_objects
 
2654     if (Scanner.TRACE) {
 
2655       System.out.println("TRACE: object_property()");
 
2657     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
 
2658       variable_without_objects();
 
2663   private void object_dim_list() {
 
2665     //  object_dim_list '[' dim_offset ']'
 
2666     //| object_dim_list '{' expr '}'
 
2668     if (Scanner.TRACE) {
 
2669       System.out.println("TRACE: object_dim_list()");
 
2673       if (token == TokenNameLBRACE) {
 
2676         if (token != TokenNameRBRACE) {
 
2677           throwSyntaxError("'}' expected in object_dim_list.");
 
2680       } else if (token == TokenNameLBRACKET) {
 
2682         if (token == TokenNameRBRACKET) {
 
2687         if (token != TokenNameRBRACKET) {
 
2688           throwSyntaxError("']' expected in object_dim_list.");
 
2696   private void variable_name() {
 
2700     if (Scanner.TRACE) {
 
2701       System.out.println("TRACE: variable_name()");
 
2703     if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
 
2704       if (token > TokenNameKEYWORD) {
 
2705         // TODO show a warning "Keyword used as variable" ?
 
2709       if (token != TokenNameLBRACE) {
 
2710         throwSyntaxError("'{' expected in variable name.");
 
2714       if (token != TokenNameRBRACE) {
 
2715         throwSyntaxError("'}' expected in variable name.");
 
2720   private void r_variable() {
 
2723   private void w_variable() {
 
2726   private void rw_variable() {
 
2729   private void variable() {
 
2731     //          base_variable_with_function_calls T_OBJECT_OPERATOR
 
2732     //                  object_property method_or_not variable_properties
 
2733     //  | base_variable_with_function_calls
 
2734     base_variable_with_function_calls();
 
2735     if (token == TokenNameMINUS_GREATER) {
 
2739       variable_properties();
 
2741     //    if (token == TokenNameDOLLAR_LBRACE) {
 
2745     //      if (token != TokenNameRBRACE) {
 
2746     //        throwSyntaxError("'}' expected after indirect variable token '${'.");
 
2750     //      if (token == TokenNameVariable) {
 
2752     //        if (token == TokenNameLBRACKET) {
 
2755     //          if (token != TokenNameRBRACKET) {
 
2756     //            throwSyntaxError("']' expected in variable-list.");
 
2759     //        } else if (token == TokenNameEQUAL) {
 
2764     //        throwSyntaxError("$-variable expected in variable-list.");
 
2768   private void variable_properties() {
 
2769     //  variable_properties:
 
2770     //                  variable_properties variable_property
 
2772     while (token == TokenNameMINUS_GREATER) {
 
2773       variable_property();
 
2776   private void variable_property() {
 
2777     //  variable_property:
 
2778     //                  T_OBJECT_OPERATOR object_property method_or_not
 
2779     if (Scanner.TRACE) {
 
2780       System.out.println("TRACE: variable_property()");
 
2782     if (token == TokenNameMINUS_GREATER) {
 
2787       throwSyntaxError("'->' expected in variable_property.");
 
2790   private void method_or_not() {
 
2792     //                  '(' function_call_parameter_list ')'
 
2794     if (Scanner.TRACE) {
 
2795       System.out.println("TRACE: method_or_not()");
 
2797     if (token == TokenNameLPAREN) {
 
2799       if (token == TokenNameRPAREN) {
 
2803       non_empty_function_call_parameter_list();
 
2804       if (token != TokenNameRPAREN) {
 
2805         throwSyntaxError("')' expected in method_or_not.");
 
2810   private void exit_expr() {
 
2814     if (token != TokenNameLPAREN) {
 
2818     if (token == TokenNameRPAREN) {
 
2823     if (token != TokenNameRPAREN) {
 
2824       throwSyntaxError("')' expected after keyword 'exit'");
 
2828   private void encaps_list() {
 
2829     //                  encaps_list encaps_var
 
2830     //          | encaps_list T_STRING
 
2831     //          | encaps_list T_NUM_STRING
 
2832     //          | encaps_list T_ENCAPSED_AND_WHITESPACE
 
2833     //          | encaps_list T_CHARACTER
 
2834     //          | encaps_list T_BAD_CHARACTER
 
2835     //          | encaps_list '['
 
2836     //          | encaps_list ']'
 
2837     //          | encaps_list '{'
 
2838     //          | encaps_list '}'
 
2839     //          | encaps_list T_OBJECT_OPERATOR
 
2843         case TokenNameSTRING :
 
2846         case TokenNameLBRACE :
 
2847           //          scanner.encapsedStringStack.pop();
 
2850         case TokenNameRBRACE :
 
2851           //          scanner.encapsedStringStack.pop();
 
2854         case TokenNameLBRACKET :
 
2855           //          scanner.encapsedStringStack.pop();
 
2858         case TokenNameRBRACKET :
 
2859           //          scanner.encapsedStringStack.pop();
 
2862         case TokenNameMINUS_GREATER :
 
2863           //          scanner.encapsedStringStack.pop();
 
2866         case TokenNameVariable :
 
2867         case TokenNameDOLLAR_LBRACE :
 
2868         case TokenNameCURLY_OPEN :
 
2871         //        case TokenNameDOLLAR :
 
2873         //          if (token == TokenNameLBRACE) {
 
2874         //            token = TokenNameDOLLAR_LBRACE;
 
2879           char encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
 
2880           if (encapsedChar == '$') {
 
2881             scanner.encapsedStringStack.pop();
 
2882             encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
 
2883             switch (encapsedChar) {
 
2885                 if (token == TokenNameEncapsedString0) {
 
2888                 token = TokenNameSTRING;
 
2891                 if (token == TokenNameEncapsedString1) {
 
2894                 token = TokenNameSTRING;
 
2897                 if (token == TokenNameEncapsedString2) {
 
2900                 token = TokenNameSTRING;
 
2908   private void encaps_var() {
 
2910     //          | T_VARIABLE '[' encaps_var_offset ']'
 
2911     //          | T_VARIABLE T_OBJECT_OPERATOR T_STRING
 
2912     //          | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
 
2913     //          | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
 
2914     //          | T_CURLY_OPEN variable '}'
 
2916       case TokenNameVariable :
 
2918         if (token == TokenNameLBRACKET) {
 
2920           //          if (token == TokenNameRBRACKET) {
 
2923           expr(); //encaps_var_offset();
 
2924           if (token != TokenNameRBRACKET) {
 
2925             throwSyntaxError("']' expected after variable.");
 
2927           //          scanner.encapsedStringStack.pop();
 
2930         } else if (token == TokenNameMINUS_GREATER) {
 
2932           if (token != TokenNameIdentifier) {
 
2933             throwSyntaxError("Identifier expected after '->'.");
 
2935           //          scanner.encapsedStringStack.pop();
 
2939         //          // scanner.encapsedStringStack.pop();
 
2940         //          int tempToken = TokenNameSTRING;
 
2941         //          if (!scanner.encapsedStringStack.isEmpty()
 
2942         //              && (token == TokenNameEncapsedString0
 
2943         //                  || token == TokenNameEncapsedString1
 
2944         //                  || token == TokenNameEncapsedString2 || token ==
 
2945         // TokenNameERROR)) {
 
2946         //            char encapsedChar = ((Character)
 
2947         // scanner.encapsedStringStack.peek())
 
2950         //              case TokenNameEncapsedString0 :
 
2951         //                if (encapsedChar == '`') {
 
2952         //                  tempToken = TokenNameEncapsedString0;
 
2955         //              case TokenNameEncapsedString1 :
 
2956         //                if (encapsedChar == '\'') {
 
2957         //                  tempToken = TokenNameEncapsedString1;
 
2960         //              case TokenNameEncapsedString2 :
 
2961         //                if (encapsedChar == '"') {
 
2962         //                  tempToken = TokenNameEncapsedString2;
 
2965         //              case TokenNameERROR :
 
2966         //                if (scanner.source[scanner.currentPosition - 1] == '\\') {
 
2967         //                  scanner.currentPosition--;
 
2973         //          token = tempToken;
 
2976       case TokenNameDOLLAR_LBRACE :
 
2978         if (token == TokenNameIdentifier) {
 
2980           if (token == TokenNameLBRACKET) {
 
2982             //            if (token == TokenNameRBRACKET) {
 
2986             if (token != TokenNameRBRACKET) {
 
2987               throwSyntaxError("']' expected after '${'.");
 
2992           if (token != TokenNameRBRACE) {
 
2993             throwSyntaxError("'}' expected after '${'.");
 
2995           //          scanner.encapsedStringStack.pop();
 
2999           if (token != TokenNameRBRACE) {
 
3000             throwSyntaxError("'}' expected.");
 
3002           //          scanner.encapsedStringStack.pop();
 
3006       case TokenNameCURLY_OPEN :
 
3008         if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
 
3010           if (token == TokenNameLBRACKET) {
 
3012             //            if (token == TokenNameRBRACKET) {
 
3016             if (token != TokenNameRBRACKET) {
 
3017               throwSyntaxError("']' expected after '{$'.");
 
3021           } else if (token == TokenNameMINUS_GREATER) {
 
3023             if (token != TokenNameIdentifier) {
 
3024               throwSyntaxError("String token expected.");
 
3028           //          if (token != TokenNameRBRACE) {
 
3029           //            throwSyntaxError("'}' expected after '{$'.");
 
3031           //          // scanner.encapsedStringStack.pop();
 
3035           if (token != TokenNameRBRACE) {
 
3036             throwSyntaxError("'}' expected.");
 
3038           //          scanner.encapsedStringStack.pop();
 
3044   private void encaps_var_offset() {
 
3049       case TokenNameSTRING :
 
3052       case TokenNameIntegerLiteral :
 
3055       case TokenNameVariable :
 
3058       case TokenNameIdentifier :
 
3062         throwSyntaxError("Variable or String token expected.");
 
3066   private void internal_functions_in_yacc() {
 
3068     ImportReference impt = null;
 
3070       case TokenNameisset :
 
3071         //      T_ISSET '(' isset_variables ')'
 
3073         if (token != TokenNameLPAREN) {
 
3074           throwSyntaxError("'(' expected after keyword 'isset'");
 
3078         if (token != TokenNameRPAREN) {
 
3079           throwSyntaxError("')' expected after keyword 'isset'");
 
3083       case TokenNameempty :
 
3084         //      T_EMPTY '(' variable ')'
 
3086         if (token != TokenNameLPAREN) {
 
3087           throwSyntaxError("'(' expected after keyword 'empty'");
 
3091         if (token != TokenNameRPAREN) {
 
3092           throwSyntaxError("')' expected after keyword 'empty'");
 
3096       case TokenNameinclude :
 
3098         start = scanner.getCurrentTokenStartPosition();
 
3102         impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
 
3103         impt.declarationSourceEnd = impt.sourceEnd;
 
3104         impt.declarationEnd = impt.declarationSourceEnd;
 
3105         //endPosition is just before the ;
 
3106         impt.declarationSourceStart = start;
 
3107         includesList.add(impt);
 
3109       case TokenNameinclude_once :
 
3110         //      T_INCLUDE_ONCE expr
 
3111         start = scanner.getCurrentTokenStartPosition();
 
3114         impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
 
3115         impt.declarationSourceEnd = impt.sourceEnd;
 
3116         impt.declarationEnd = impt.declarationSourceEnd;
 
3117         //endPosition is just before the ;
 
3118         impt.declarationSourceStart = start;
 
3119         includesList.add(impt);
 
3121       case TokenNameeval :
 
3122         //      T_EVAL '(' expr ')'
 
3124         if (token != TokenNameLPAREN) {
 
3125           throwSyntaxError("'(' expected after keyword 'eval'");
 
3129         if (token != TokenNameRPAREN) {
 
3130           throwSyntaxError("')' expected after keyword 'eval'");
 
3134       case TokenNamerequire :
 
3136         start = scanner.getCurrentTokenStartPosition();
 
3139         impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
 
3140         impt.declarationSourceEnd = impt.sourceEnd;
 
3141         impt.declarationEnd = impt.declarationSourceEnd;
 
3142         //endPosition is just before the ;
 
3143         impt.declarationSourceStart = start;
 
3144         includesList.add(impt);
 
3146       case TokenNamerequire_once :
 
3147         //      T_REQUIRE_ONCE expr
 
3148         start = scanner.getCurrentTokenStartPosition();
 
3151         impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
 
3152         impt.declarationSourceEnd = impt.sourceEnd;
 
3153         impt.declarationEnd = impt.declarationSourceEnd;
 
3154         //endPosition is just before the ;
 
3155         impt.declarationSourceStart = start;
 
3156         includesList.add(impt);
 
3160   private void isset_variables() {
 
3162     //  | isset_variables ','
 
3163     if (token == TokenNameRPAREN) {
 
3164       throwSyntaxError("Variable expected after keyword 'isset'");
 
3168       if (token == TokenNameCOMMA) {
 
3175   private boolean common_scalar() {
 
3179     //  | T_CONSTANT_ENCAPSED_STRING
 
3186       case TokenNameIntegerLiteral :
 
3189       case TokenNameDoubleLiteral :
 
3192       case TokenNameStringLiteral :
 
3195       case TokenNameStringConstant :
 
3198       case TokenNameStringInterpolated :
 
3201       case TokenNameFILE :
 
3204       case TokenNameLINE :
 
3207       case TokenNameCLASS_C :
 
3210       case TokenNameMETHOD_C :
 
3213       case TokenNameFUNC_C :
 
3219   private void scalar() {
 
3222     //| T_STRING_VARNAME
 
3225     //| '"' encaps_list '"'
 
3226     //| '\'' encaps_list '\''
 
3227     //| T_START_HEREDOC encaps_list T_END_HEREDOC
 
3228     throwSyntaxError("Not yet implemented (scalar).");
 
3230   private void static_scalar() {
 
3231     //    static_scalar: /* compile-time evaluated scalars */
 
3234     //  | '+' static_scalar
 
3235     //  | '-' static_scalar
 
3236     //  | T_ARRAY '(' static_array_pair_list ')'
 
3237     //  | static_class_constant
 
3238     if (common_scalar()) {
 
3242       case TokenNameIdentifier :
 
3244         //        static_class_constant:
 
3245         //              T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
 
3246         if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
 
3248           if (token == TokenNameIdentifier) {
 
3251             throwSyntaxError("Identifier expected after '::' operator.");
 
3255       case TokenNameEncapsedString0 :
 
3257           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3258           while (scanner.currentCharacter != '`') {
 
3259             if (scanner.currentCharacter == '\\') {
 
3260               scanner.currentPosition++;
 
3262             scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3265         } catch (IndexOutOfBoundsException e) {
 
3266           throwSyntaxError("'`' expected at end of static string.");
 
3269       case TokenNameEncapsedString1 :
 
3271           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3272           while (scanner.currentCharacter != '\'') {
 
3273             if (scanner.currentCharacter == '\\') {
 
3274               scanner.currentPosition++;
 
3276             scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3279         } catch (IndexOutOfBoundsException e) {
 
3280           throwSyntaxError("'\'' expected at end of static string.");
 
3283       case TokenNameEncapsedString2 :
 
3285           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3286           while (scanner.currentCharacter != '"') {
 
3287             if (scanner.currentCharacter == '\\') {
 
3288               scanner.currentPosition++;
 
3290             scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3293         } catch (IndexOutOfBoundsException e) {
 
3294           throwSyntaxError("'\"' expected at end of static string.");
 
3297       case TokenNamePLUS :
 
3301       case TokenNameMINUS :
 
3305       case TokenNamearray :
 
3307         if (token != TokenNameLPAREN) {
 
3308           throwSyntaxError("'(' expected after keyword 'array'");
 
3311         if (token == TokenNameRPAREN) {
 
3315         non_empty_static_array_pair_list();
 
3316         if (token != TokenNameRPAREN) {
 
3317           throwSyntaxError("')' expected after keyword 'array'");
 
3321       //      case TokenNamenull :
 
3324       //      case TokenNamefalse :
 
3327       //      case TokenNametrue :
 
3331         throwSyntaxError("Static scalar/constant expected.");
 
3334   private void non_empty_static_array_pair_list() {
 
3335     //  non_empty_static_array_pair_list:
 
3336     //  non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
 
3338     //| non_empty_static_array_pair_list ',' static_scalar
 
3339     //| static_scalar T_DOUBLE_ARROW static_scalar
 
3343       if (token == TokenNameEQUAL_GREATER) {
 
3347       if (token != TokenNameCOMMA) {
 
3351       if (token == TokenNameRPAREN) {
 
3356   public void reportSyntaxError() { //int act, int currentKind, int
 
3358     /* remember current scanner position */
 
3359     int startPos = scanner.startPosition;
 
3360     int currentPos = scanner.currentPosition;
 
3361     //          String[] expectings;
 
3362     //          String tokenName = name[symbol_index[currentKind]];
 
3363     //fetch all "accurate" possible terminals that could recover the error
 
3364     //          int start, end = start = asi(stack[stateStackTop]);
 
3365     //          while (asr[end] != 0)
 
3367     //          int length = end - start;
 
3368     //          expectings = new String[length];
 
3369     //          if (length != 0) {
 
3370     //                  char[] indexes = new char[length];
 
3371     //                  System.arraycopy(asr, start, indexes, 0, length);
 
3372     //                  for (int i = 0; i < length; i++) {
 
3373     //                          expectings[i] = name[symbol_index[indexes[i]]];
 
3376     //if the pb is an EOF, try to tell the user that they are some
 
3377     //          if (tokenName.equals(UNEXPECTED_EOF)) {
 
3378     //                  if (!this.checkAndReportBracketAnomalies(problemReporter())) {
 
3379     //                          char[] tokenSource;
 
3381     //                                  tokenSource = this.scanner.getCurrentTokenSource();
 
3382     //                          } catch (Exception e) {
 
3383     //                                  tokenSource = new char[] {};
 
3385     //                          problemReporter().parseError(
 
3386     //                                  this.scanner.startPosition,
 
3387     //                                  this.scanner.currentPosition - 1,
 
3392     //          } else { //the next test is HEAVILY grammar DEPENDENT.
 
3393     //                  if ((length == 14)
 
3394     //                          && (expectings[0] == "=") //$NON-NLS-1$
 
3395     //                          && (expectings[1] == "*=") //$NON-NLS-1$
 
3396     //                          && (expressionPtr > -1)) {
 
3397     //                                  switch(currentKind) {
 
3398     //                                          case TokenNameSEMICOLON:
 
3399     //                                          case TokenNamePLUS:
 
3400     //                                          case TokenNameMINUS:
 
3401     //                                          case TokenNameDIVIDE:
 
3402     //                                          case TokenNameREMAINDER:
 
3403     //                                          case TokenNameMULTIPLY:
 
3404     //                                          case TokenNameLEFT_SHIFT:
 
3405     //                                          case TokenNameRIGHT_SHIFT:
 
3406     //// case TokenNameUNSIGNED_RIGHT_SHIFT:
 
3407     //                                          case TokenNameLESS:
 
3408     //                                          case TokenNameGREATER:
 
3409     //                                          case TokenNameLESS_EQUAL:
 
3410     //                                          case TokenNameGREATER_EQUAL:
 
3411     //                                          case TokenNameEQUAL_EQUAL:
 
3412     //                                          case TokenNameNOT_EQUAL:
 
3413     //                                          case TokenNameXOR:
 
3414     //                                          case TokenNameAND:
 
3415     //                                          case TokenNameOR:
 
3416     //                                          case TokenNameOR_OR:
 
3417     //                                          case TokenNameAND_AND:
 
3418     //                                                  // the ; is not the expected token ==> it ends a statement when an
 
3419     // expression is not ended
 
3420     //                                                  problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
 
3422     //                                          case TokenNameRBRACE :
 
3423     //                                                  problemReporter().missingSemiColon(expressionStack[expressionPtr]);
 
3426     //                                                  char[] tokenSource;
 
3428     //                                                          tokenSource = this.scanner.getCurrentTokenSource();
 
3429     //                                                  } catch (Exception e) {
 
3430     //                                                          tokenSource = new char[] {};
 
3432     //                                                  problemReporter().parseError(
 
3433     //                                                          this.scanner.startPosition,
 
3434     //                                                          this.scanner.currentPosition - 1,
 
3438     //                                                  this.checkAndReportBracketAnomalies(problemReporter());
 
3443       tokenSource = this.scanner.getCurrentTokenSource();
 
3444     } catch (Exception e) {
 
3445       tokenSource = new char[]{};
 
3447     //                          problemReporter().parseError(
 
3448     //                                  this.scanner.startPosition,
 
3449     //                                  this.scanner.currentPosition - 1,
 
3453     this.checkAndReportBracketAnomalies(problemReporter());
 
3456     /* reset scanner where it was */
 
3457     scanner.startPosition = startPos;
 
3458     scanner.currentPosition = currentPos;
 
3460   public static final int RoundBracket = 0;
 
3461   public static final int SquareBracket = 1;
 
3462   public static final int CurlyBracket = 2;
 
3463   public static final int BracketKinds = 3;
 
3464   protected int[] nestedMethod; //the ptr is nestedType
 
3465   protected int nestedType, dimensions;
 
3467   final static int AstStackIncrement = 100;
 
3468   protected int astPtr;
 
3469   protected AstNode[] astStack = new AstNode[AstStackIncrement];
 
3470   protected int astLengthPtr;
 
3471   protected int[] astLengthStack;
 
3472   AstNode[] noAstNodes = new AstNode[AstStackIncrement];
 
3473   public CompilationUnitDeclaration compilationUnit; /*
 
3474                                                       * the result from parse()
 
3476   protected ReferenceContext referenceContext;
 
3477   protected ProblemReporter problemReporter;
 
3478   protected CompilerOptions options;
 
3479   private ArrayList includesList;
 
3480   //  protected CompilationResult compilationResult;
 
3482    * Returns this parser's problem reporter initialized with its reference
 
3483    * context. Also it is assumed that a problem is going to be reported, so
 
3484    * initializes the compilation result's line positions.
 
3486   public ProblemReporter problemReporter() {
 
3487     if (scanner.recordLineSeparator) {
 
3488       compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
 
3490     problemReporter.referenceContext = referenceContext;
 
3491     return problemReporter;
 
3494    * Reconsider the entire source looking for inconsistencies in {} () []
 
3496   public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
 
3497     scanner.wasAcr = false;
 
3498     boolean anomaliesDetected = false;
 
3500       char[] source = scanner.source;
 
3501       int[] leftCount = {0, 0, 0};
 
3502       int[] rightCount = {0, 0, 0};
 
3503       int[] depths = {0, 0, 0};
 
3504       int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
 
3505       int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
 
3506       int[][] rightPositions = new int[][]{new int[10], new int[10], new int[10]};
 
3507       int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
 
3508       scanner.currentPosition = scanner.initialPosition; //starting
 
3510       // (first-zero-based
 
3512       while (scanner.currentPosition < scanner.eofPosition) { //loop for
 
3517           // ---------Consume white space and handles
 
3518           // startPosition---------
 
3519           boolean isWhiteSpace;
 
3521             scanner.startPosition = scanner.currentPosition;
 
3522             //                                          if (((scanner.currentCharacter =
 
3523             // source[scanner.currentPosition++]) == '\\') &&
 
3524             // (source[scanner.currentPosition] == 'u')) {
 
3525             //                                                  isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
 
3527             if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
 
3528               if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
 
3529                 // only record line positions we have not
 
3531                 scanner.pushLineSeparator();
 
3534             isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
 
3536           } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
 
3537           // -------consume token until } is found---------
 
3538           switch (scanner.currentCharacter) {
 
3540               int index = leftCount[CurlyBracket]++;
 
3541               if (index == leftPositions[CurlyBracket].length) {
 
3542                 System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
 
3543                 System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
 
3545               leftPositions[CurlyBracket][index] = scanner.startPosition;
 
3546               leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
 
3550               int index = rightCount[CurlyBracket]++;
 
3551               if (index == rightPositions[CurlyBracket].length) {
 
3552                 System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
 
3553                 System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
 
3555               rightPositions[CurlyBracket][index] = scanner.startPosition;
 
3556               rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
 
3560               int index = leftCount[RoundBracket]++;
 
3561               if (index == leftPositions[RoundBracket].length) {
 
3562                 System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
 
3563                 System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
 
3565               leftPositions[RoundBracket][index] = scanner.startPosition;
 
3566               leftDepths[RoundBracket][index] = depths[RoundBracket]++;
 
3570               int index = rightCount[RoundBracket]++;
 
3571               if (index == rightPositions[RoundBracket].length) {
 
3572                 System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
 
3573                 System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
 
3575               rightPositions[RoundBracket][index] = scanner.startPosition;
 
3576               rightDepths[RoundBracket][index] = --depths[RoundBracket];
 
3580               int index = leftCount[SquareBracket]++;
 
3581               if (index == leftPositions[SquareBracket].length) {
 
3582                 System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
 
3583                 System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
 
3585               leftPositions[SquareBracket][index] = scanner.startPosition;
 
3586               leftDepths[SquareBracket][index] = depths[SquareBracket]++;
 
3590               int index = rightCount[SquareBracket]++;
 
3591               if (index == rightPositions[SquareBracket].length) {
 
3592                 System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
 
3593                 System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
 
3595               rightPositions[SquareBracket][index] = scanner.startPosition;
 
3596               rightDepths[SquareBracket][index] = --depths[SquareBracket];
 
3600               if (scanner.getNextChar('\\')) {
 
3601                 scanner.scanEscapeCharacter();
 
3602               } else { // consume next character
 
3603                 scanner.unicodeAsBackSlash = false;
 
3604                 //                                                                      if (((scanner.currentCharacter =
 
3605                 // source[scanner.currentPosition++]) ==
 
3607                 // (source[scanner.currentPosition] ==
 
3609                 //                                                                              scanner.getNextUnicodeChar();
 
3611                 if (scanner.withoutUnicodePtr != 0) {
 
3612                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
3616               scanner.getNextChar('\'');
 
3620               // consume next character
 
3621               scanner.unicodeAsBackSlash = false;
 
3622               //                                                        if (((scanner.currentCharacter =
 
3623               // source[scanner.currentPosition++]) == '\\') &&
 
3624               // (source[scanner.currentPosition] == 'u')) {
 
3625               //                                                                scanner.getNextUnicodeChar();
 
3627               if (scanner.withoutUnicodePtr != 0) {
 
3628                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
3631               while (scanner.currentCharacter != '"') {
 
3632                 if (scanner.currentCharacter == '\r') {
 
3633                   if (source[scanner.currentPosition] == '\n')
 
3634                     scanner.currentPosition++;
 
3635                   break; // the string cannot go further that
 
3638                 if (scanner.currentCharacter == '\n') {
 
3639                   break; // the string cannot go further that
 
3642                 if (scanner.currentCharacter == '\\') {
 
3643                   scanner.scanEscapeCharacter();
 
3645                 // consume next character
 
3646                 scanner.unicodeAsBackSlash = false;
 
3647                 //                                                              if (((scanner.currentCharacter =
 
3648                 // source[scanner.currentPosition++]) == '\\')
 
3649                 // && (source[scanner.currentPosition] == 'u'))
 
3651                 //                                                                      scanner.getNextUnicodeChar();
 
3653                 if (scanner.withoutUnicodePtr != 0) {
 
3654                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
3661               if ((test = scanner.getNextChar('/', '*')) == 0) { //line
 
3664                 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
3665                     && (source[scanner.currentPosition] == 'u')) {
 
3666                   //-------------unicode traitement
 
3668                   int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
3669                   scanner.currentPosition++;
 
3670                   while (source[scanner.currentPosition] == 'u') {
 
3671                     scanner.currentPosition++;
 
3673                   if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
 
3674                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
 
3675                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
 
3676                       || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
 
3680                     scanner.currentCharacter = 'A';
 
3681                   } //something different from \n and \r
 
3683                     scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3686                 while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
 
3688                   scanner.startPosition = scanner.currentPosition;
 
3689                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
3690                       && (source[scanner.currentPosition] == 'u')) {
 
3691                     //-------------unicode traitement
 
3693                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
3694                     scanner.currentPosition++;
 
3695                     while (source[scanner.currentPosition] == 'u') {
 
3696                       scanner.currentPosition++;
 
3698                     if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
 
3699                         || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
 
3700                         || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
 
3701                         || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
 
3705                       scanner.currentCharacter = 'A';
 
3706                     } //something different from \n
 
3709                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3713                 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
 
3714                   if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
 
3715                     // only record line positions we
 
3716                     // have not recorded yet
 
3717                     scanner.pushLineSeparator();
 
3718                     if (this.scanner.taskTags != null) {
 
3719                       this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner
 
3720                           .getCurrentTokenEndPosition());
 
3726               if (test > 0) { //traditional and annotation
 
3728                 boolean star = false;
 
3729                 // consume next character
 
3730                 scanner.unicodeAsBackSlash = false;
 
3731                 //                                                                      if (((scanner.currentCharacter =
 
3732                 // source[scanner.currentPosition++]) ==
 
3734                 // (source[scanner.currentPosition] ==
 
3736                 //                                                                              scanner.getNextUnicodeChar();
 
3738                 if (scanner.withoutUnicodePtr != 0) {
 
3739                   scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
3742                 if (scanner.currentCharacter == '*') {
 
3746                 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
3747                     && (source[scanner.currentPosition] == 'u')) {
 
3748                   //-------------unicode traitement
 
3750                   int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
3751                   scanner.currentPosition++;
 
3752                   while (source[scanner.currentPosition] == 'u') {
 
3753                     scanner.currentPosition++;
 
3755                   if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
 
3756                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
 
3757                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
 
3758                       || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
 
3762                     scanner.currentCharacter = 'A';
 
3763                   } //something different from * and /
 
3765                     scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3768                 //loop until end of comment */
 
3769                 while ((scanner.currentCharacter != '/') || (!star)) {
 
3770                   star = scanner.currentCharacter == '*';
 
3772                   if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
3773                       && (source[scanner.currentPosition] == 'u')) {
 
3774                     //-------------unicode traitement
 
3776                     int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
3777                     scanner.currentPosition++;
 
3778                     while (source[scanner.currentPosition] == 'u') {
 
3779                       scanner.currentPosition++;
 
3781                     if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
 
3782                         || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
 
3783                         || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
 
3784                         || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
 
3788                       scanner.currentCharacter = 'A';
 
3789                     } //something different from * and
 
3792                       scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
3796                 if (this.scanner.taskTags != null) {
 
3797                   this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
 
3804               if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
 
3805                 scanner.scanIdentifierOrKeyword(false);
 
3808               if (Character.isDigit(scanner.currentCharacter)) {
 
3809                 scanner.scanNumber(false);
 
3813           //-----------------end switch while
 
3814           // try--------------------
 
3815         } catch (IndexOutOfBoundsException e) {
 
3816           break; // read until EOF
 
3817         } catch (InvalidInputException e) {
 
3818           return false; // no clue
 
3821       if (scanner.recordLineSeparator) {
 
3822         //                              compilationUnit.compilationResult.lineSeparatorPositions =
 
3823         // scanner.getLineEnds();
 
3825       // check placement anomalies against other kinds of brackets
 
3826       for (int kind = 0; kind < BracketKinds; kind++) {
 
3827         for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
 
3828           int start = leftPositions[kind][leftIndex]; // deepest
 
3830           // find matching closing bracket
 
3831           int depth = leftDepths[kind][leftIndex];
 
3833           for (int i = 0; i < rightCount[kind]; i++) {
 
3834             int pos = rightPositions[kind][i];
 
3835             // want matching bracket further in source with same
 
3837             if ((pos > start) && (depth == rightDepths[kind][i])) {
 
3842           if (end < 0) { // did not find a good closing match
 
3843             problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
 
3846           // check if even number of opening/closing other brackets
 
3847           // in between this pair of brackets
 
3849           for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
 
3850             for (int i = 0; i < leftCount[otherKind]; i++) {
 
3851               int pos = leftPositions[otherKind][i];
 
3852               if ((pos > start) && (pos < end))
 
3855             for (int i = 0; i < rightCount[otherKind]; i++) {
 
3856               int pos = rightPositions[otherKind][i];
 
3857               if ((pos > start) && (pos < end))
 
3861               problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket
 
3867         // too many opening brackets ?
 
3868         for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
 
3869           anomaliesDetected = true;
 
3870           problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext,
 
3871               compilationUnit.compilationResult);
 
3873         // too many closing brackets ?
 
3874         for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
 
3875           anomaliesDetected = true;
 
3876           problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
 
3878         if (anomaliesDetected)
 
3881       return anomaliesDetected;
 
3882     } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
 
3883       return anomaliesDetected;
 
3884     } catch (NullPointerException e) { // jdk1.2.2 jit bug
 
3885       return anomaliesDetected;
 
3888   protected void pushOnAstLengthStack(int pos) {
 
3890       astLengthStack[++astLengthPtr] = pos;
 
3891     } catch (IndexOutOfBoundsException e) {
 
3892       int oldStackLength = astLengthStack.length;
 
3893       int[] oldPos = astLengthStack;
 
3894       astLengthStack = new int[oldStackLength + StackIncrement];
 
3895       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
 
3896       astLengthStack[astLengthPtr] = pos;
 
3899   protected void pushOnAstStack(AstNode node) {
 
3901      * add a new obj on top of the ast stack
 
3904       astStack[++astPtr] = node;
 
3905     } catch (IndexOutOfBoundsException e) {
 
3906       int oldStackLength = astStack.length;
 
3907       AstNode[] oldStack = astStack;
 
3908       astStack = new AstNode[oldStackLength + AstStackIncrement];
 
3909       System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
 
3910       astPtr = oldStackLength;
 
3911       astStack[astPtr] = node;
 
3914       astLengthStack[++astLengthPtr] = 1;
 
3915     } catch (IndexOutOfBoundsException e) {
 
3916       int oldStackLength = astLengthStack.length;
 
3917       int[] oldPos = astLengthStack;
 
3918       astLengthStack = new int[oldStackLength + AstStackIncrement];
 
3919       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
 
3920       astLengthStack[astLengthPtr] = 1;
 
3924   protected void resetModifiers() {
 
3925     this.modifiers = AccDefault;
 
3926     this.modifiersSourceStart = -1; // <-- see comment into
 
3927     // modifiersFlag(int)
 
3928     this.scanner.commentPtr = -1;