1 /***********************************************************************************************************************************
 
   2  * Copyright (c) 2002 www.phpeclipse.de All rights reserved. This program and the accompanying material are made available under the
 
   3  * terms of the Common Public License v1.0 which accompanies this distribution, and is available at
 
   4  * http://www.eclipse.org/legal/cpl-v10.html
 
   6  * Contributors: www.phpeclipse.de
 
   7  **********************************************************************************************************************************/
 
   8 package net.sourceforge.phpdt.internal.compiler.parser;
 
  10 import java.util.ArrayList;
 
  11 import java.util.HashMap;
 
  13 import net.sourceforge.phpdt.core.compiler.CharOperation;
 
  14 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
 
  15 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
 
  16 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
 
  17 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
 
  18 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
 
  19 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
 
  20 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
 
  21 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
 
  22 import net.sourceforge.phpdt.internal.compiler.util.Util;
 
  23 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
 
  24 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
 
  25 import net.sourceforge.phpeclipse.internal.compiler.ast.AND_AND_Expression;
 
  26 import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
 
  27 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
 
  28 import net.sourceforge.phpeclipse.internal.compiler.ast.BinaryExpression;
 
  29 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
 
  30 import net.sourceforge.phpeclipse.internal.compiler.ast.ConditionalExpression;
 
  31 import net.sourceforge.phpeclipse.internal.compiler.ast.EmptyStatement;
 
  32 import net.sourceforge.phpeclipse.internal.compiler.ast.EqualExpression;
 
  33 import net.sourceforge.phpeclipse.internal.compiler.ast.Expression;
 
  34 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
 
  35 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldReference;
 
  36 import net.sourceforge.phpeclipse.internal.compiler.ast.IfStatement;
 
  37 import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
 
  38 import net.sourceforge.phpeclipse.internal.compiler.ast.InstanceOfExpression;
 
  39 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
 
  40 import net.sourceforge.phpeclipse.internal.compiler.ast.OR_OR_Expression;
 
  41 import net.sourceforge.phpeclipse.internal.compiler.ast.OperatorIds;
 
  42 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
 
  43 import net.sourceforge.phpeclipse.internal.compiler.ast.Statement;
 
  44 import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteral;
 
  45 import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralDQ;
 
  46 import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralSQ;
 
  47 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
 
  48 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
 
  49 import net.sourceforge.phpeclipse.ui.overlaypages.ProjectPrefUtil;
 
  51 import org.eclipse.core.resources.IFile;
 
  52 import org.eclipse.core.resources.IProject;
 
  53 import org.eclipse.core.resources.IResource;
 
  54 import org.eclipse.core.runtime.IPath;
 
  56 public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
 
  57   protected final static int StackIncrement = 255;
 
  59   protected int stateStackTop;
 
  61   //  protected int[] stack = new int[StackIncrement];
 
  63   public int firstToken; // handle for multiple parsing goals
 
  65   public int lastAct; //handle for multiple parsing goals
 
  67   //  protected RecoveredElement currentElement;
 
  69   public static boolean VERBOSE_RECOVERY = false;
 
  71   protected boolean diet = false; //tells the scanner to jump over some
 
  73   // parts of the code/expressions like
 
  76   public Scanner scanner;
 
  78   //  private ArrayList phpList;
 
  80   //  private int currentPHPString;
 
  82   //  private boolean phpEnd;
 
  84   // private static HashMap keywordMap = null;
 
  92   // row counter for syntax errors:
 
  94   // column counter for syntax errors:
 
  98   //    // current identifier
 
 102   //  Double doubleNumber;
 
 104   //  private String stringValue;
 
 106   /** Contains the current expression. */
 
 107   // private StringBuffer expression;
 
 108   //private boolean phpMode;
 
 109   protected int modifiers;
 
 111   protected int modifiersSourceStart;
 
 113   protected Parser(ProblemReporter problemReporter) {
 
 114     this.problemReporter = problemReporter;
 
 115     this.options = problemReporter.options;
 
 116     //    this.currentPHPString = 0;
 
 117     //          PHPParserSuperclass.fileToParse = fileToParse;
 
 118     //    this.phpList = null;
 
 119     //    this.indexManager = null;
 
 121     this.token = TokenNameEOF;
 
 123     //    this.rowCount = 1;
 
 124     //    this.columnCount = 0;
 
 125     //    this.phpEnd = false;
 
 127     this.initializeScanner();
 
 130   public void setFileToParse(IFile fileToParse) {
 
 131     //    this.currentPHPString = 0;
 
 132     //    PHPParserSuperclass.fileToParse = fileToParse;
 
 133     //    this.phpList = null;
 
 134     //    this.indexManager = null;
 
 136     this.token = TokenNameEOF;
 
 137     //    this.phpEnd = false;
 
 138     this.initializeScanner();
 
 142    * ClassDeclaration Constructor.
 
 146    *          Description of Parameter
 
 149   public Parser(IFile fileToParse) {
 
 150     //    if (keywordMap == null) {
 
 151     //      keywordMap = new HashMap();
 
 152     //      for (int i = 0; i < PHP_KEYWORS.length; i++) {
 
 153     //        keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
 
 156     //    this.currentPHPString = 0;
 
 157     //    PHPParserSuperclass.fileToParse = fileToParse;
 
 158     //    this.phpList = null;
 
 159     this.includesList = null;
 
 161     this.token = TokenNameEOF;
 
 163     //    this.rowCount = 1;
 
 164     //    this.columnCount = 0;
 
 165     //    this.phpEnd = false;
 
 167     this.initializeScanner();
 
 170   public void initializeScanner() {
 
 171     this.scanner = new Scanner(false /* comment */, false /* whitespace */, this.options
 
 172         .getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /* nls */, false, false,
 
 173         this.options.taskTags/* taskTags */, this.options.taskPriorites/* taskPriorities */, true/* isTaskCaseSensitive */);
 
 177    * Create marker for the parse error
 
 179   //  private void setMarker(String message, int charStart, int charEnd, int
 
 181   //    setMarker(fileToParse, message, charStart, charEnd, errorLevel);
 
 184    * This method will throw the SyntaxError. It will add the good lines and columns to the Error
 
 188    * @throws SyntaxError
 
 191   private void throwSyntaxError(String error) {
 
 192     int problemStartPosition = scanner.getCurrentTokenStartPosition();
 
 193     int problemEndPosition = scanner.getCurrentTokenEndPosition();
 
 194     throwSyntaxError(error, problemStartPosition, problemEndPosition + 1);
 
 198    * This method will throw the SyntaxError. It will add the good lines and columns to the Error
 
 202    * @throws SyntaxError
 
 205   //  private void throwSyntaxError(String error, int startRow) {
 
 206   //    throw new SyntaxError(startRow, 0, " ", error);
 
 208   private void throwSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
 
 209     if (referenceContext != null) {
 
 210       problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
 
 211           compilationUnit.compilationResult);
 
 213     throw new SyntaxError(1, 0, " ", error);
 
 216   private void reportSyntaxError(String error) {
 
 217     int problemStartPosition = scanner.getCurrentTokenStartPosition();
 
 218     int problemEndPosition = scanner.getCurrentTokenEndPosition();
 
 219     reportSyntaxError(error, problemStartPosition, problemEndPosition + 1);
 
 222   private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
 
 223     if (referenceContext != null) {
 
 224       problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
 
 225           compilationUnit.compilationResult);
 
 229   private void reportSyntaxWarning(String error, int problemStartPosition, int problemEndPosition) {
 
 230     if (referenceContext != null) {
 
 231       problemReporter.phpParsingWarning(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
 
 232           compilationUnit.compilationResult);
 
 237    * gets the next token from input
 
 239   private void getNextToken() {
 
 241       token = scanner.getNextToken();
 
 243         int currentEndPosition = scanner.getCurrentTokenEndPosition();
 
 244         int currentStartPosition = scanner.getCurrentTokenStartPosition();
 
 245         System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
 
 246         System.out.println(scanner.toStringAction(token));
 
 248     } catch (InvalidInputException e) {
 
 249       token = TokenNameERROR;
 
 250       String detailedMessage = e.getMessage();
 
 252       if (detailedMessage == Scanner.UNTERMINATED_STRING) {
 
 253         throwSyntaxError("Unterminated string.");
 
 254       } else if (detailedMessage == Scanner.UNTERMINATED_COMMENT) {
 
 255         throwSyntaxError("Unterminated commment.");
 
 261   public void init(String s) {
 
 263     this.token = TokenNameEOF;
 
 264     this.includesList = new ArrayList();
 
 266     //    this.rowCount = 1;
 
 267     //    this.columnCount = 0;
 
 268     //    this.phpEnd = false;
 
 269     //    this.phpMode = false;
 
 270     /* scanner initialization */
 
 271     scanner.setSource(s.toCharArray());
 
 272     scanner.setPHPMode(false);
 
 276   protected void initialize(boolean phpMode) {
 
 277     initialize(phpMode, null);
 
 280   protected void initialize(boolean phpMode, IdentifierIndexManager indexManager) {
 
 281     compilationUnit = null;
 
 282     referenceContext = null;
 
 283     this.includesList = new ArrayList();
 
 284     //    this.indexManager = indexManager;
 
 286     this.token = TokenNameEOF;
 
 288     //    this.rowCount = 1;
 
 289     //    this.columnCount = 0;
 
 290     //    this.phpEnd = false;
 
 291     //    this.phpMode = phpMode;
 
 292     scanner.setPHPMode(phpMode);
 
 297    * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>'
 
 299   public void parse(String s) {
 
 304    * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>'
 
 306   public void parse(String s, HashMap variables) {
 
 307     fMethodVariables = variables;
 
 313    * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>'
 
 315   protected void parse() {
 
 316     if (scanner.compilationUnit != null) {
 
 317       IResource resource = scanner.compilationUnit.getResource();
 
 318       if (resource != null && resource instanceof IFile) {
 
 319         // set the package name
 
 320         consumePackageDeclarationName((IFile) resource);
 
 326         if (token != TokenNameEOF && token != TokenNameERROR) {
 
 329         if (token != TokenNameEOF) {
 
 330           if (token == TokenNameERROR) {
 
 331             throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
 
 333           if (token == TokenNameRPAREN) {
 
 334             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
 
 336           if (token == TokenNameRBRACE) {
 
 337             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
 
 339           if (token == TokenNameRBRACKET) {
 
 340             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
 
 342           if (token == TokenNameLPAREN) {
 
 343             throwSyntaxError("Read character '('; end-of-file not reached.");
 
 345           if (token == TokenNameLBRACE) {
 
 346             throwSyntaxError("Read character '{';  end-of-file not reached.");
 
 348           if (token == TokenNameLBRACKET) {
 
 349             throwSyntaxError("Read character '[';  end-of-file not reached.");
 
 351           throwSyntaxError("End-of-file not reached.");
 
 354       } catch (SyntaxError sytaxErr1) {
 
 356         //        // if an error occured,
 
 357         //        // try to find keywords 'abstract' 'final' 'class' or 'function'
 
 358         //        // to parse the rest of the string
 
 359         //        boolean tokenize = scanner.tokenizeStrings;
 
 361         //          scanner.tokenizeStrings = true;
 
 364         //          while (token != TokenNameEOF) {
 
 365         //            if (token == TokenNameabstract || token == TokenNamefinal || token == TokenNameclass || token == TokenNamefunction) {
 
 370         //          if (token == TokenNameEOF) {
 
 373         //        } catch (SyntaxError sytaxErr2) {
 
 376         //          scanner.tokenizeStrings = tokenize;
 
 385    * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>'
 
 387   public void parseFunction(String s, HashMap variables) {
 
 389     scanner.phpMode = true;
 
 390     parseFunction(variables);
 
 394    * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>'
 
 396   protected void parseFunction(HashMap variables) {
 
 398     boolean hasModifiers = member_modifiers();
 
 399     if (token == TokenNamefunction) {
 
 401         checkAndSetModifiers(AccPublic);
 
 403       this.fMethodVariables = variables;
 
 405       MethodDeclaration methodDecl = new MethodDeclaration(null);
 
 406       methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
 407       methodDecl.modifiers = this.modifiers;
 
 408       methodDecl.type = MethodDeclaration.METHOD_DEFINITION;
 
 411         functionDefinition(methodDecl);
 
 412       } catch (SyntaxError sytaxErr1) {
 
 415         int sourceEnd = scanner.getCurrentTokenStartPosition();
 
 416         if (sourceEnd <= 0 || methodDecl.declarationSourceStart > sourceEnd) {
 
 417           sourceEnd = methodDecl.declarationSourceStart + 1;
 
 419         methodDecl.declarationSourceEnd = sourceEnd;
 
 424   protected CompilationUnitDeclaration endParse(int act) {
 
 428     //    if (currentElement != null) {
 
 429     //      currentElement.topElement().updateParseTree();
 
 430     //      if (VERBOSE_RECOVERY) {
 
 431     //        System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
 
 432     //        System.out.println("--------------------------"); //$NON-NLS-1$
 
 433     //        System.out.println(compilationUnit);
 
 434     //        System.out.println("----------------------------------"); //$NON-NLS-1$
 
 437     if (diet & VERBOSE_RECOVERY) {
 
 438       System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
 
 439       System.out.println("--------------------------"); //$NON-NLS-1$
 
 440       System.out.println(compilationUnit);
 
 441       System.out.println("----------------------------------"); //$NON-NLS-1$
 
 444     if (scanner.recordLineSeparator) {
 
 445       compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
 
 447     if (scanner.taskTags != null) {
 
 448       for (int i = 0; i < scanner.foundTaskCount; i++) {
 
 449         problemReporter().task(new String(scanner.foundTaskTags[i]), new String(scanner.foundTaskMessages[i]),
 
 450             scanner.foundTaskPriorities[i] == null ? null : new String(scanner.foundTaskPriorities[i]),
 
 451             scanner.foundTaskPositions[i][0], scanner.foundTaskPositions[i][1]);
 
 454     compilationUnit.imports = new ImportReference[includesList.size()];
 
 455     for (int i = 0; i < includesList.size(); i++) {
 
 456       compilationUnit.imports[i] = (ImportReference) includesList.get(i);
 
 458     return compilationUnit;
 
 461   private boolean isVariable() {
 
 462     return token == TokenNameVariable; //  || token == TokenNamethis;
 
 465   private void statementList() {
 
 468         statement(TokenNameEOF);
 
 469         if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse)
 
 470             || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor)
 
 471             || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch)
 
 472             || (token == TokenNameenddeclare) || (token == TokenNameEOF) || (token == TokenNameERROR)) {
 
 475       } catch (SyntaxError sytaxErr1) {
 
 476         // if an error occured,
 
 477         // try to find keywords
 
 478         // to parse the rest of the string
 
 479         boolean tokenize = scanner.tokenizeStrings;
 
 481           scanner.tokenizeStrings = true;
 
 484           while (token != TokenNameEOF) {
 
 485             if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse)
 
 486                 || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor)
 
 487                 || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch)
 
 488                 || (token == TokenNameenddeclare) || (token == TokenNameEOF) || (token == TokenNameERROR)) {
 
 491             if (token == TokenNameif || token == TokenNameswitch || token == TokenNamefor || token == TokenNamewhile
 
 492                 || token == TokenNamedo || token == TokenNameforeach || token == TokenNamecontinue || token == TokenNamebreak
 
 493                 || token == TokenNamereturn || token == TokenNameexit || token == TokenNameecho || token == TokenNameglobal
 
 494                 || token == TokenNamestatic || token == TokenNameunset || token == TokenNamefunction || token == TokenNamedeclare
 
 495                 || token == TokenNametry || token == TokenNamecatch || token == TokenNamethrow || token == TokenNamefinal
 
 496                 || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) {
 
 499             //            System.out.println(scanner.toStringAction(token));
 
 501             //            System.out.println(scanner.toStringAction(token));
 
 503           if (token == TokenNameEOF) {
 
 507           scanner.tokenizeStrings = tokenize;
 
 513   private void functionBody(MethodDeclaration methodDecl) {
 
 514     // '{' [statement-list] '}'
 
 515     if (token == TokenNameLBRACE) {
 
 518       throwSyntaxError("'{' expected in compound-statement.");
 
 520     if (token != TokenNameRBRACE) {
 
 523     if (token == TokenNameRBRACE) {
 
 524       //      methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
 527       throwSyntaxError("'}' expected in compound-statement.");
 
 531   private Statement statement(int previousToken) {
 
 532     Statement statement = null;
 
 533     Expression expression;
 
 534     int sourceStart = scanner.getCurrentTokenStartPosition();
 
 535     if (token == TokenNameif) {
 
 537       if (token == TokenNameLPAREN) {
 
 540         throwSyntaxError("'(' expected after 'if' keyword.");
 
 543       if (token == TokenNameRPAREN) {
 
 546         throwSyntaxError("')' expected after 'if' condition.");
 
 549       return new IfStatement(expression, statement, sourceStart, scanner.getCurrentTokenEndPosition());
 
 550     } else if (token == TokenNameswitch) {
 
 552       if (token == TokenNameLPAREN) {
 
 555         throwSyntaxError("'(' expected after 'switch' keyword.");
 
 558       if (token == TokenNameRPAREN) {
 
 561         throwSyntaxError("')' expected after 'switch' condition.");
 
 565     } else if (token == TokenNamefor) {
 
 567       if (token == TokenNameLPAREN) {
 
 570         throwSyntaxError("'(' expected after 'for' keyword.");
 
 572       if (token == TokenNameSEMICOLON) {
 
 576         if (token == TokenNameSEMICOLON) {
 
 579           throwSyntaxError("';' expected after 'for'.");
 
 582       if (token == TokenNameSEMICOLON) {
 
 586         if (token == TokenNameSEMICOLON) {
 
 589           throwSyntaxError("';' expected after 'for'.");
 
 592       if (token == TokenNameRPAREN) {
 
 596         if (token == TokenNameRPAREN) {
 
 599           throwSyntaxError("')' expected after 'for'.");
 
 604     } else if (token == TokenNamewhile) {
 
 606       if (token == TokenNameLPAREN) {
 
 609         throwSyntaxError("'(' expected after 'while' keyword.");
 
 612       if (token == TokenNameRPAREN) {
 
 615         throwSyntaxError("')' expected after 'while' condition.");
 
 619     } else if (token == TokenNamedo) {
 
 621       if (token == TokenNameLBRACE) {
 
 623         if (token != TokenNameRBRACE) {
 
 626         if (token == TokenNameRBRACE) {
 
 629           throwSyntaxError("'}' expected after 'do' keyword.");
 
 632         statement(TokenNameEOF);
 
 634       if (token == TokenNamewhile) {
 
 636         if (token == TokenNameLPAREN) {
 
 639           throwSyntaxError("'(' expected after 'while' keyword.");
 
 642         if (token == TokenNameRPAREN) {
 
 645           throwSyntaxError("')' expected after 'while' condition.");
 
 648         throwSyntaxError("'while' expected after 'do' keyword.");
 
 650       if (token == TokenNameSEMICOLON) {
 
 653         if (token != TokenNameINLINE_HTML) {
 
 654           throwSyntaxError("';' expected after do-while statement.");
 
 659     } else if (token == TokenNameforeach) {
 
 661       if (token == TokenNameLPAREN) {
 
 664         throwSyntaxError("'(' expected after 'foreach' keyword.");
 
 667       if (token == TokenNameas) {
 
 670         throwSyntaxError("'as' expected after 'foreach' exxpression.");
 
 674       foreach_optional_arg();
 
 675       if (token == TokenNameEQUAL_GREATER) {
 
 679       if (token == TokenNameRPAREN) {
 
 682         throwSyntaxError("')' expected after 'foreach' expression.");
 
 686     } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
 
 688       if (token != TokenNameSEMICOLON) {
 
 691       if (token == TokenNameSEMICOLON) {
 
 694         if (token != TokenNameINLINE_HTML) {
 
 695           throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
 
 700     } else if (token == TokenNameecho) {
 
 703       if (token == TokenNameSEMICOLON) {
 
 706         if (token != TokenNameINLINE_HTML) {
 
 707           throwSyntaxError("';' expected after 'echo' statement.");
 
 712     } else if (token == TokenNameINLINE_HTML) {
 
 715       //    } else if (token == TokenNameprint) {
 
 718       //      if (token == TokenNameSEMICOLON) {
 
 721       //        if (token != TokenNameStopPHP) {
 
 722       //          throwSyntaxError("';' expected after 'print' statement.");
 
 727     } else if (token == TokenNameglobal) {
 
 730       if (token == TokenNameSEMICOLON) {
 
 733         if (token != TokenNameINLINE_HTML) {
 
 734           throwSyntaxError("';' expected after 'global' statement.");
 
 739     } else if (token == TokenNamestatic) {
 
 742       if (token == TokenNameSEMICOLON) {
 
 745         if (token != TokenNameINLINE_HTML) {
 
 746           throwSyntaxError("';' expected after 'static' statement.");
 
 751     } else if (token == TokenNameunset) {
 
 753       if (token == TokenNameLPAREN) {
 
 756         throwSyntaxError("'(' expected after 'unset' statement.");
 
 759       if (token == TokenNameRPAREN) {
 
 762         throwSyntaxError("')' expected after 'unset' statement.");
 
 764       if (token == TokenNameSEMICOLON) {
 
 767         if (token != TokenNameINLINE_HTML) {
 
 768           throwSyntaxError("';' expected after 'unset' statement.");
 
 773     } else if (token == TokenNamefunction) {
 
 774       MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
 
 775       methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
 776       methodDecl.modifiers = AccDefault;
 
 777       methodDecl.type = MethodDeclaration.FUNCTION_DEFINITION;
 
 780         functionDefinition(methodDecl);
 
 782         int sourceEnd = scanner.getCurrentTokenStartPosition();
 
 783         if (sourceEnd <= 0 || methodDecl.declarationSourceStart > sourceEnd) {
 
 784           sourceEnd = methodDecl.declarationSourceStart + 1;
 
 786         methodDecl.declarationSourceEnd = sourceEnd;
 
 789     } else if (token == TokenNamedeclare) {
 
 790       //T_DECLARE '(' declare_list ')' declare_statement
 
 792       if (token != TokenNameLPAREN) {
 
 793         throwSyntaxError("'(' expected in 'declare' statement.");
 
 797       if (token != TokenNameRPAREN) {
 
 798         throwSyntaxError("')' expected in 'declare' statement.");
 
 803     } else if (token == TokenNametry) {
 
 805       if (token != TokenNameLBRACE) {
 
 806         throwSyntaxError("'{' expected in 'try' statement.");
 
 810       if (token != TokenNameRBRACE) {
 
 811         throwSyntaxError("'}' expected in 'try' statement.");
 
 815     } else if (token == TokenNamecatch) {
 
 817       if (token != TokenNameLPAREN) {
 
 818         throwSyntaxError("'(' expected in 'catch' statement.");
 
 821       fully_qualified_class_name();
 
 822       if (token != TokenNameVariable) {
 
 823         throwSyntaxError("Variable expected in 'catch' statement.");
 
 826       if (token != TokenNameRPAREN) {
 
 827         throwSyntaxError("')' expected in 'catch' statement.");
 
 830       if (token != TokenNameLBRACE) {
 
 831         throwSyntaxError("'{' expected in 'catch' statement.");
 
 834       if (token != TokenNameRBRACE) {
 
 836         if (token != TokenNameRBRACE) {
 
 837           throwSyntaxError("'}' expected in 'catch' statement.");
 
 841       additional_catches();
 
 843     } else if (token == TokenNamethrow) {
 
 846       if (token == TokenNameSEMICOLON) {
 
 849         throwSyntaxError("';' expected after 'throw' exxpression.");
 
 852     } else if (token == TokenNamefinal || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) {
 
 854         TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
 
 855         typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
 856         typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
 857         typeDecl.name = new char[] { ' ' };
 
 858         // default super class
 
 859         typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
 
 860         compilationUnit.types.add(typeDecl);
 
 861         pushOnAstStack(typeDecl);
 
 862         unticked_class_declaration_statement(typeDecl);
 
 870       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
 
 871     } else if (token == TokenNameLBRACE) {
 
 873       if (token != TokenNameRBRACE) {
 
 876       if (token == TokenNameRBRACE) {
 
 880         throwSyntaxError("'}' expected.");
 
 883       if (token != TokenNameSEMICOLON) {
 
 886       if (token == TokenNameSEMICOLON) {
 
 890         if (token == TokenNameRBRACE) {
 
 891           reportSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
 
 893           if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
 
 894             throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
 
 904   private void declare_statement() {
 
 906     //| ':' inner_statement_list T_ENDDECLARE ';'
 
 908     if (token == TokenNameCOLON) {
 
 910       // TODO: implement inner_statement_list();
 
 912       if (token != TokenNameenddeclare) {
 
 913         throwSyntaxError("'enddeclare' expected in 'declare' statement.");
 
 916       if (token != TokenNameSEMICOLON) {
 
 917         throwSyntaxError("';' expected after 'enddeclare' keyword.");
 
 921       statement(TokenNameRPAREN);
 
 925   private void declare_list() {
 
 926     //  T_STRING '=' static_scalar
 
 927     //| declare_list ',' T_STRING '=' static_scalar
 
 929       if (token != TokenNameIdentifier) {
 
 930         throwSyntaxError("Identifier expected in 'declare' list.");
 
 933       if (token != TokenNameEQUAL) {
 
 934         throwSyntaxError("'=' expected in 'declare' list.");
 
 938       if (token != TokenNameCOMMA) {
 
 945   private void additional_catches() {
 
 946     while (token == TokenNamecatch) {
 
 948       if (token != TokenNameLPAREN) {
 
 949         throwSyntaxError("'(' expected in 'catch' statement.");
 
 952       fully_qualified_class_name();
 
 953       if (token != TokenNameVariable) {
 
 954         throwSyntaxError("Variable expected in 'catch' statement.");
 
 957       if (token != TokenNameRPAREN) {
 
 958         throwSyntaxError("')' expected in 'catch' statement.");
 
 961       if (token != TokenNameLBRACE) {
 
 962         throwSyntaxError("'{' expected in 'catch' statement.");
 
 965       if (token != TokenNameRBRACE) {
 
 968       if (token != TokenNameRBRACE) {
 
 969         throwSyntaxError("'}' expected in 'catch' statement.");
 
 975   private void foreach_variable() {
 
 978     if (token == TokenNameAND) {
 
 984   private void foreach_optional_arg() {
 
 986     //| T_DOUBLE_ARROW foreach_variable
 
 987     if (token == TokenNameEQUAL_GREATER) {
 
 993   private void global_var_list() {
 
 995     //  global_var_list ',' global_var
 
 999       if (token != TokenNameCOMMA) {
 
1006   private void global_var() {
 
1010     //| '$' '{' expr '}'
 
1011     if (token == TokenNameVariable) {
 
1012       VariableInfo info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_GLOBAL_VAR);
 
1013       if (fMethodVariables != null) {
 
1014         fMethodVariables.put(new String(scanner.getCurrentIdentifierSource()), info);
 
1017     } else if (token == TokenNameDOLLAR) {
 
1019       if (token == TokenNameLBRACE) {
 
1022         if (token != TokenNameRBRACE) {
 
1023           throwSyntaxError("'}' expected in global variable.");
 
1032   private void static_var_list() {
 
1034     //  static_var_list ',' T_VARIABLE
 
1035     //| static_var_list ',' T_VARIABLE '=' static_scalar
 
1037     //| T_VARIABLE '=' static_scalar
 
1039       if (token == TokenNameVariable) {
 
1040         VariableInfo info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_STATIC_VAR);
 
1041         if (fMethodVariables != null) {
 
1042           fMethodVariables.put(new String(scanner.getCurrentIdentifierSource()), info);
 
1045         if (token == TokenNameEQUAL) {
 
1049         if (token != TokenNameCOMMA) {
 
1059   private void unset_variables() {
 
1062     //          | unset_variables ',' unset_variable
 
1067       if (token != TokenNameCOMMA) {
 
1074   private final void initializeModifiers() {
 
1076     this.modifiersSourceStart = -1;
 
1079   private final void checkAndSetModifiers(int flag) {
 
1080     this.modifiers |= flag;
 
1081     if (this.modifiersSourceStart < 0)
 
1082       this.modifiersSourceStart = this.scanner.startPosition;
 
1085   private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
 
1086     initializeModifiers();
 
1087     if (token == TokenNameinterface) {
 
1088       //      interface_entry T_STRING
 
1089       //                interface_extends_list
 
1090       //                '{' class_statement_list '}'
 
1091       checkAndSetModifiers(AccInterface);
 
1093       typeDecl.modifiers = this.modifiers;
 
1094       typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1095       typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1096       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
 
1097         typeDecl.name = scanner.getCurrentIdentifierSource();
 
1098         if (token > TokenNameKEYWORD) {
 
1099           problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
 
1100               scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
 
1101           //          throwSyntaxError("Don't use a keyword for interface declaration [" + scanner.toStringAction(token) + "].",
 
1102           //              typeDecl.sourceStart, typeDecl.sourceEnd);
 
1105         interface_extends_list(typeDecl);
 
1107         typeDecl.name = new char[] { ' ' };
 
1108         throwSyntaxError("Interface name expected after keyword 'interface'.", typeDecl.sourceStart, typeDecl.sourceEnd);
 
1112       //      class_entry_type T_STRING extends_from
 
1114       //                '{' class_statement_list'}'
 
1116       typeDecl.modifiers = this.modifiers;
 
1117       typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1118       typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1120       //identifier 'extends' identifier
 
1121       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
 
1122         typeDecl.name = scanner.getCurrentIdentifierSource();
 
1123         if (token > TokenNameKEYWORD) {
 
1124           problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
 
1125               scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
 
1126           //          throwSyntaxError("Don't use a keyword for class declaration [" + scanner.toStringAction(token) + "].",
 
1127           //              typeDecl.sourceStart, typeDecl.sourceEnd);
 
1132         //      | T_EXTENDS fully_qualified_class_name
 
1133         if (token == TokenNameextends) {
 
1134           interface_extends_list(typeDecl);
 
1136           //          if (token != TokenNameIdentifier) {
 
1137           //            throwSyntaxError("Class name expected after keyword
 
1139           //                scanner.getCurrentTokenStartPosition(), scanner
 
1140           //                    .getCurrentTokenEndPosition());
 
1143         implements_list(typeDecl);
 
1145         typeDecl.name = new char[] { ' ' };
 
1146         throwSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
 
1150     //  '{' class_statement_list '}'
 
1151     if (token == TokenNameLBRACE) {
 
1153       if (token != TokenNameRBRACE) {
 
1154         ArrayList list = new ArrayList();
 
1155         class_statement_list(list);
 
1156         typeDecl.fields = new FieldDeclaration[list.size()];
 
1157         for (int i = 0; i < list.size(); i++) {
 
1158           typeDecl.fields[i] = (FieldDeclaration) list.get(i);
 
1161       if (token == TokenNameRBRACE) {
 
1162         typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1165         throwSyntaxError("'}' expected at end of class body.");
 
1168       throwSyntaxError("'{' expected at start of class body.");
 
1172   private void class_entry_type() {
 
1174     //  | T_ABSTRACT T_CLASS
 
1175     //  | T_FINAL T_CLASS
 
1176     if (token == TokenNameclass) {
 
1178     } else if (token == TokenNameabstract) {
 
1179       checkAndSetModifiers(AccAbstract);
 
1181       if (token != TokenNameclass) {
 
1182         throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
 
1185     } else if (token == TokenNamefinal) {
 
1186       checkAndSetModifiers(AccFinal);
 
1188       if (token != TokenNameclass) {
 
1189         throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
 
1193       throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
 
1197   private void class_extends(TypeDeclaration typeDecl) {
 
1199     //  | T_EXTENDS interface_list
 
1200     if (token == TokenNameextends) {
 
1203       if (token == TokenNameIdentifier) {
 
1206         throwSyntaxError("Class name expected after keyword 'extends'.");
 
1211   private void interface_extends_list(TypeDeclaration typeDecl) {
 
1213     //  | T_EXTENDS interface_list
 
1214     if (token == TokenNameextends) {
 
1220   private void implements_list(TypeDeclaration typeDecl) {
 
1222     //  | T_IMPLEMENTS interface_list
 
1223     if (token == TokenNameimplements) {
 
1229   private void interface_list() {
 
1231     //  fully_qualified_class_name
 
1232     //| interface_list ',' fully_qualified_class_name
 
1234       if (token == TokenNameIdentifier) {
 
1237         throwSyntaxError("Interface name expected after keyword 'implements'.");
 
1239       if (token != TokenNameCOMMA) {
 
1246   //  private void classBody(TypeDeclaration typeDecl) {
 
1247   //    //'{' [class-element-list] '}'
 
1248   //    if (token == TokenNameLBRACE) {
 
1250   //      if (token != TokenNameRBRACE) {
 
1251   //        class_statement_list();
 
1253   //      if (token == TokenNameRBRACE) {
 
1254   //        typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1257   //        throwSyntaxError("'}' expected at end of class body.");
 
1260   //      throwSyntaxError("'{' expected at start of class body.");
 
1263   private void class_statement_list(ArrayList list) {
 
1266         class_statement(list);
 
1267         if (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic
 
1268             || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar
 
1269             || token == TokenNameconst) {
 
1272         if (token == TokenNameRBRACE) {
 
1275         throwSyntaxError("'}' at end of class statement.");
 
1276       } catch (SyntaxError sytaxErr1) {
 
1277         boolean tokenize = scanner.tokenizeStrings;
 
1279           scanner.tokenizeStrings = true;
 
1282           // if an error occured,
 
1283           // try to find keywords
 
1284           // to parse the rest of the string
 
1285           while (token != TokenNameEOF) {
 
1286             if (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic
 
1287                 || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar
 
1288                 || token == TokenNameconst) {
 
1291             //            System.out.println(scanner.toStringAction(token));
 
1294           if (token == TokenNameEOF) {
 
1298           scanner.tokenizeStrings = tokenize;
 
1304   private void class_statement(ArrayList list) {
 
1306     //          variable_modifiers class_variable_declaration ';'
 
1307     //  | class_constant_declaration ';'
 
1308     //  | method_modifiers T_FUNCTION is_reference T_STRING
 
1309     //    '(' parameter_list ')' method_body
 
1310     initializeModifiers();
 
1311     int declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
1313     if (token == TokenNamevar) {
 
1314       checkAndSetModifiers(AccPublic);
 
1315       problemReporter.phpVarDeprecatedWarning(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
 
1316           referenceContext, compilationUnit.compilationResult);
 
1318       class_variable_declaration(declarationSourceStart, list);
 
1319     } else if (token == TokenNameconst) {
 
1320       checkAndSetModifiers(AccFinal | AccPublic);
 
1321       class_constant_declaration(declarationSourceStart, list);
 
1322       if (token != TokenNameSEMICOLON) {
 
1323         throwSyntaxError("';' expected after class const declaration.");
 
1327       boolean hasModifiers = member_modifiers();
 
1328       if (token == TokenNamefunction) {
 
1329         if (!hasModifiers) {
 
1330           checkAndSetModifiers(AccPublic);
 
1332         MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
 
1333         methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
 
1334         methodDecl.modifiers = this.modifiers;
 
1335         methodDecl.type = MethodDeclaration.METHOD_DEFINITION;
 
1338           functionDefinition(methodDecl);
 
1340           int sourceEnd = scanner.getCurrentTokenStartPosition();
 
1341           if (sourceEnd <= 0 || methodDecl.declarationSourceStart > sourceEnd) {
 
1342             sourceEnd = methodDecl.declarationSourceStart + 1;
 
1344           methodDecl.declarationSourceEnd = sourceEnd;
 
1347         if (!hasModifiers) {
 
1348           throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
 
1350         class_variable_declaration(declarationSourceStart, list);
 
1355   private void class_constant_declaration(int declarationSourceStart, ArrayList list) {
 
1356     //  class_constant_declaration ',' T_STRING '=' static_scalar
 
1357     //  | T_CONST T_STRING '=' static_scalar
 
1358     if (token != TokenNameconst) {
 
1359       throwSyntaxError("'const' keyword expected in class declaration.");
 
1364       if (token != TokenNameIdentifier) {
 
1365         throwSyntaxError("Identifier expected in class const declaration.");
 
1367       FieldDeclaration fieldDeclaration = new FieldDeclaration(scanner.getCurrentIdentifierSource(), scanner
 
1368           .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
 
1369       fieldDeclaration.modifiers = this.modifiers;
 
1370       fieldDeclaration.declarationSourceStart = declarationSourceStart;
 
1371       fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1372       fieldDeclaration.modifiersSourceStart = declarationSourceStart;
 
1373       //        fieldDeclaration.type
 
1374       list.add(fieldDeclaration);
 
1376       if (token != TokenNameEQUAL) {
 
1377         throwSyntaxError("'=' expected in class const declaration.");
 
1381       if (token != TokenNameCOMMA) {
 
1382         break; // while(true)-loop
 
1388   //  private void variable_modifiers() {
 
1389   //    // variable_modifiers:
 
1390   //    // non_empty_member_modifiers
 
1392   //    initializeModifiers();
 
1393   //    if (token == TokenNamevar) {
 
1394   //      checkAndSetModifiers(AccPublic);
 
1395   //      reportSyntaxError(
 
1396   //          "Keyword 'var' is deprecated. Please use 'public' 'private' or
 
1398   // modifier for field declarations.",
 
1399   //          scanner.getCurrentTokenStartPosition(), scanner
 
1400   //              .getCurrentTokenEndPosition());
 
1403   //      if (!member_modifiers()) {
 
1404   //        throwSyntaxError("'public' 'private' or 'protected' modifier expected for
 
1405   // field declarations.");
 
1409   //  private void method_modifiers() {
 
1410   //    //method_modifiers:
 
1412   //    //| non_empty_member_modifiers
 
1413   //    initializeModifiers();
 
1414   //    if (!member_modifiers()) {
 
1415   //      checkAndSetModifiers(AccPublic);
 
1418   private boolean member_modifiers() {
 
1425     boolean foundToken = false;
 
1427       if (token == TokenNamepublic) {
 
1428         checkAndSetModifiers(AccPublic);
 
1431       } else if (token == TokenNameprotected) {
 
1432         checkAndSetModifiers(AccProtected);
 
1435       } else if (token == TokenNameprivate) {
 
1436         checkAndSetModifiers(AccPrivate);
 
1439       } else if (token == TokenNamestatic) {
 
1440         checkAndSetModifiers(AccStatic);
 
1443       } else if (token == TokenNameabstract) {
 
1444         checkAndSetModifiers(AccAbstract);
 
1447       } else if (token == TokenNamefinal) {
 
1448         checkAndSetModifiers(AccFinal);
 
1458   private void class_variable_declaration(int declarationSourceStart, ArrayList list) {
 
1459     //    class_variable_declaration:
 
1460     //          class_variable_declaration ',' T_VARIABLE
 
1461     //  | class_variable_declaration ',' T_VARIABLE '=' static_scalar
 
1463     //  | T_VARIABLE '=' static_scalar
 
1464     char[] classVariable;
 
1466       if (token == TokenNameVariable) {
 
1467         classVariable = scanner.getCurrentIdentifierSource();
 
1468         //  indexManager.addIdentifierInformation('v', classVariable, buf, -1, -1);
 
1469         FieldDeclaration fieldDeclaration = new FieldDeclaration(classVariable, scanner.getCurrentTokenStartPosition(), scanner
 
1470             .getCurrentTokenEndPosition());
 
1471         fieldDeclaration.modifiers = this.modifiers;
 
1472         fieldDeclaration.declarationSourceStart = declarationSourceStart;
 
1473         fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
 
1474         fieldDeclaration.modifiersSourceStart = declarationSourceStart;
 
1475         list.add(fieldDeclaration);
 
1476         if (fTypeVariables != null) {
 
1477           VariableInfo info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_CLASS_UNIT);
 
1478           fTypeVariables.put(new String(scanner.getCurrentIdentifierSource()), info);
 
1481         if (token == TokenNameEQUAL) {
 
1486         //        if (token == TokenNamethis) {
 
1487         //          throwSyntaxError("'$this' not allowed after keyword 'public'
 
1488         // 'protected' 'private' 'var'.");
 
1490         throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
 
1492       if (token != TokenNameCOMMA) {
 
1497     if (token != TokenNameSEMICOLON) {
 
1498       throwSyntaxError("';' expected after field declaration.");
 
1503   private void functionDefinition(MethodDeclaration methodDecl) {
 
1504     boolean isAbstract = false;
 
1506       if (compilationUnit != null) {
 
1507         compilationUnit.types.add(methodDecl);
 
1510       ASTNode node = astStack[astPtr];
 
1511       if (node instanceof TypeDeclaration) {
 
1512         TypeDeclaration typeDecl = ((TypeDeclaration) node);
 
1513         if (typeDecl.methods == null) {
 
1514           typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
 
1516           AbstractMethodDeclaration[] newMethods;
 
1517           System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 0,
 
1518               typeDecl.methods.length);
 
1519           newMethods[typeDecl.methods.length] = methodDecl;
 
1520           typeDecl.methods = newMethods;
 
1522         if ((typeDecl.modifiers & AccAbstract) == AccAbstract) {
 
1524         } else if ((typeDecl.modifiers & AccInterface) == AccInterface) {
 
1529     functionDeclarator(methodDecl);
 
1530     if (token == TokenNameSEMICOLON) {
 
1532         throwSyntaxError("Body declaration expected for method: " + new String(methodDecl.selector));
 
1537     functionBody(methodDecl);
 
1540   private void functionDeclarator(MethodDeclaration methodDecl) {
 
1541     //identifier '(' [parameter-list] ')'
 
1542     if (token == TokenNameAND) {
 
1545     methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
 
1546     methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
 
1547     if (Scanner.isIdentifierOrKeyword(token)) {
 
1548       methodDecl.selector = scanner.getCurrentIdentifierSource();
 
1549       if (token > TokenNameKEYWORD) {
 
1550         problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
 
1551             scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
 
1554       if (token == TokenNameLPAREN) {
 
1557         throwSyntaxError("'(' expected in function declaration.");
 
1559       if (token != TokenNameRPAREN) {
 
1560         parameter_list(methodDecl);
 
1562       if (token != TokenNameRPAREN) {
 
1563         throwSyntaxError("')' expected in function declaration.");
 
1565         methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
 
1569       methodDecl.selector = "<undefined>".toCharArray();
 
1570       throwSyntaxError("Function name expected after keyword 'function'.");
 
1575   private void parameter_list(MethodDeclaration methodDecl) {
 
1576     //  non_empty_parameter_list
 
1578     non_empty_parameter_list(methodDecl, true);
 
1581   private void non_empty_parameter_list(MethodDeclaration methodDecl, boolean empty_allowed) {
 
1582     //  optional_class_type T_VARIABLE
 
1583     //  | optional_class_type '&' T_VARIABLE
 
1584     //  | optional_class_type '&' T_VARIABLE '=' static_scalar
 
1585     //  | optional_class_type T_VARIABLE '=' static_scalar
 
1586     //  | non_empty_parameter_list ',' optional_class_type T_VARIABLE
 
1587     //  | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
 
1588     //  | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
 
1590     //  | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
 
1592     char[] typeIdentifier = null;
 
1593     if (token == TokenNameIdentifier || token == TokenNameVariable || token == TokenNameAND) {
 
1595         if (token == TokenNameIdentifier) {
 
1596           typeIdentifier = scanner.getCurrentIdentifierSource();
 
1599         if (token == TokenNameAND) {
 
1602         if (token == TokenNameVariable) {
 
1603           if (fMethodVariables != null) {
 
1605             if (methodDecl.type == MethodDeclaration.FUNCTION_DEFINITION) {
 
1606               info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_FUNCTION_DEFINITION);
 
1608               info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_METHOD_DEFINITION);
 
1610             info.typeIdentifier = typeIdentifier;
 
1611             fMethodVariables.put(new String(scanner.getCurrentIdentifierSource()), info);
 
1614           if (token == TokenNameEQUAL) {
 
1619           throwSyntaxError("Variable expected in parameter list.");
 
1621         if (token != TokenNameCOMMA) {
 
1628     if (!empty_allowed) {
 
1629       throwSyntaxError("Identifier expected in parameter list.");
 
1633   private void optional_class_type() {
 
1638   //  private void parameterDeclaration() {
 
1640   //    //variable-reference
 
1641   //    if (token == TokenNameAND) {
 
1643   //      if (isVariable()) {
 
1646   //        throwSyntaxError("Variable expected after reference operator '&'.");
 
1649   //    //variable '=' constant
 
1650   //    if (token == TokenNameVariable) {
 
1652   //      if (token == TokenNameEQUAL) {
 
1658   //    // if (token == TokenNamethis) {
 
1659   //    // throwSyntaxError("Reserved word '$this' not allowed in parameter
 
1660   //    // declaration.");
 
1664   private void labeledStatementList() {
 
1665     if (token != TokenNamecase && token != TokenNamedefault) {
 
1666       throwSyntaxError("'case' or 'default' expected.");
 
1669       if (token == TokenNamecase) {
 
1671         expr(); //constant();
 
1672         if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
 
1674           if (token == TokenNamecase || token == TokenNamedefault) {
 
1675             // empty case statement ?
 
1680         //        else if (token == TokenNameSEMICOLON) {
 
1682         //            "':' expected after 'case' keyword (Found token: " +
 
1683         // scanner.toStringAction(token) + ")",
 
1684         //            scanner.getCurrentTokenStartPosition(),
 
1685         //            scanner.getCurrentTokenEndPosition(),
 
1688         //          if (token == TokenNamecase) { // empty case statement ?
 
1694           throwSyntaxError("':' character expected after 'case' constant (Found token: " + scanner.toStringAction(token) + ")");
 
1696       } else { // TokenNamedefault
 
1698         if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
 
1700           if (token == TokenNameRBRACE) {
 
1701             // empty default case
 
1704           if (token != TokenNamecase) {
 
1708           throwSyntaxError("':' character expected after 'default'.");
 
1711     } while (token == TokenNamecase || token == TokenNamedefault);
 
1714   //  public void labeledStatement() {
 
1715   //    if (token == TokenNamecase) {
 
1718   //      if (token == TokenNameDDOT) {
 
1722   //        throwSyntaxError("':' character after 'case' constant expected.");
 
1725   //    } else if (token == TokenNamedefault) {
 
1727   //      if (token == TokenNameDDOT) {
 
1731   //        throwSyntaxError("':' character after 'default' expected.");
 
1736   //  public void expressionStatement() {
 
1738   //  private void inclusionStatement() {
 
1740   //  public void compoundStatement() {
 
1742   //  public void selectionStatement() {
 
1745   //  public void iterationStatement() {
 
1748   //  public void jumpStatement() {
 
1751   //  public void outputStatement() {
 
1754   //  public void scopeStatement() {
 
1757   //  public void flowStatement() {
 
1760   //  public void definitionStatement() {
 
1762   private void ifStatement() {
 
1763     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
 
1764     if (token == TokenNameCOLON) {
 
1766       if (token != TokenNameendif) {
 
1771           if (token == TokenNameCOLON) {
 
1773             if (token != TokenNameendif) {
 
1777             if (token == TokenNameif) { //'else if'
 
1779               elseifStatementList();
 
1781               throwSyntaxError("':' expected after 'else'.");
 
1785         case TokenNameelseif:
 
1787           elseifStatementList();
 
1791       if (token != TokenNameendif) {
 
1792         throwSyntaxError("'endif' expected.");
 
1795       if (token != TokenNameSEMICOLON) {
 
1796         throwSyntaxError("';' expected after if-statement.");
 
1800       // statement [else-statement]
 
1801       statement(TokenNameEOF);
 
1802       if (token == TokenNameelseif) {
 
1804         if (token == TokenNameLPAREN) {
 
1807           throwSyntaxError("'(' expected after 'elseif' keyword.");
 
1810         if (token == TokenNameRPAREN) {
 
1813           throwSyntaxError("')' expected after 'elseif' condition.");
 
1816       } else if (token == TokenNameelse) {
 
1818         statement(TokenNameEOF);
 
1823   private void elseifStatementList() {
 
1829         if (token == TokenNameCOLON) {
 
1831           if (token != TokenNameendif) {
 
1836           if (token == TokenNameif) { //'else if'
 
1839             throwSyntaxError("':' expected after 'else'.");
 
1843       case TokenNameelseif:
 
1852   private void elseifStatement() {
 
1853     if (token == TokenNameLPAREN) {
 
1856       if (token != TokenNameRPAREN) {
 
1857         throwSyntaxError("')' expected in else-if-statement.");
 
1860       if (token != TokenNameCOLON) {
 
1861         throwSyntaxError("':' expected in else-if-statement.");
 
1864       if (token != TokenNameendif) {
 
1870   private void switchStatement() {
 
1871     if (token == TokenNameCOLON) {
 
1872       // ':' [labeled-statement-list] 'endswitch' ';'
 
1874       labeledStatementList();
 
1875       if (token != TokenNameendswitch) {
 
1876         throwSyntaxError("'endswitch' expected.");
 
1879       if (token != TokenNameSEMICOLON) {
 
1880         throwSyntaxError("';' expected after switch-statement.");
 
1884       // '{' [labeled-statement-list] '}'
 
1885       if (token != TokenNameLBRACE) {
 
1886         throwSyntaxError("'{' expected in switch statement.");
 
1889       if (token != TokenNameRBRACE) {
 
1890         labeledStatementList();
 
1892       if (token != TokenNameRBRACE) {
 
1893         throwSyntaxError("'}' expected in switch statement.");
 
1899   private void forStatement() {
 
1900     if (token == TokenNameCOLON) {
 
1903       if (token != TokenNameendfor) {
 
1904         throwSyntaxError("'endfor' expected.");
 
1907       if (token != TokenNameSEMICOLON) {
 
1908         throwSyntaxError("';' expected after for-statement.");
 
1912       statement(TokenNameEOF);
 
1916   private void whileStatement() {
 
1917     // ':' statement-list 'endwhile' ';'
 
1918     if (token == TokenNameCOLON) {
 
1921       if (token != TokenNameendwhile) {
 
1922         throwSyntaxError("'endwhile' expected.");
 
1925       if (token != TokenNameSEMICOLON) {
 
1926         throwSyntaxError("';' expected after while-statement.");
 
1930       statement(TokenNameEOF);
 
1934   private void foreachStatement() {
 
1935     if (token == TokenNameCOLON) {
 
1938       if (token != TokenNameendforeach) {
 
1939         throwSyntaxError("'endforeach' expected.");
 
1942       if (token != TokenNameSEMICOLON) {
 
1943         throwSyntaxError("';' expected after foreach-statement.");
 
1947       statement(TokenNameEOF);
 
1951   //  private void exitStatus() {
 
1952   //    if (token == TokenNameLPAREN) {
 
1955   //      throwSyntaxError("'(' expected in 'exit-status'.");
 
1957   //    if (token != TokenNameRPAREN) {
 
1960   //    if (token == TokenNameRPAREN) {
 
1963   //      throwSyntaxError("')' expected after 'exit-status'.");
 
1966   private void expressionList() {
 
1969       if (token == TokenNameCOMMA) {
 
1977   private Expression expr() {
 
1979     //  | expr_without_variable
 
1980     //    if (token!=TokenNameEOF) {
 
1981     if (Scanner.TRACE) {
 
1982       System.out.println("TRACE: expr()");
 
1984     return expr_without_variable(true);
 
1988   private Expression expr_without_variable(boolean only_variable) {
 
1989     int exprSourceStart = scanner.getCurrentTokenStartPosition();
 
1990     int exprSourceEnd = scanner.getCurrentTokenEndPosition();
 
1991     Expression expression = new Expression();
 
1992     expression.sourceStart = exprSourceStart;
 
1993     // default, may be overwritten
 
1994     expression.sourceEnd = exprSourceEnd;
 
1996       //                internal_functions_in_yacc
 
2005       //        | T_INC rw_variable
 
2006       //        | T_DEC rw_variable
 
2007       //        | T_INT_CAST expr
 
2008       //        | T_DOUBLE_CAST expr
 
2009       //        | T_STRING_CAST expr
 
2010       //        | T_ARRAY_CAST expr
 
2011       //        | T_OBJECT_CAST expr
 
2012       //        | T_BOOL_CAST expr
 
2013       //        | T_UNSET_CAST expr
 
2014       //        | T_EXIT exit_expr
 
2016       //        | T_ARRAY '(' array_pair_list ')'
 
2017       //        | '`' encaps_list '`'
 
2018       //        | T_LIST '(' assignment_list ')' '=' expr
 
2019       //        | T_NEW class_name_reference ctor_arguments
 
2020       //        | variable '=' expr
 
2021       //        | variable '=' '&' variable
 
2022       //        | variable '=' '&' T_NEW class_name_reference ctor_arguments
 
2023       //        | variable T_PLUS_EQUAL expr
 
2024       //        | variable T_MINUS_EQUAL expr
 
2025       //        | variable T_MUL_EQUAL expr
 
2026       //        | variable T_DIV_EQUAL expr
 
2027       //        | variable T_CONCAT_EQUAL expr
 
2028       //        | variable T_MOD_EQUAL expr
 
2029       //        | variable T_AND_EQUAL expr
 
2030       //        | variable T_OR_EQUAL expr
 
2031       //        | variable T_XOR_EQUAL expr
 
2032       //        | variable T_SL_EQUAL expr
 
2033       //        | variable T_SR_EQUAL expr
 
2034       //        | rw_variable T_INC
 
2035       //        | rw_variable T_DEC
 
2036       //        | expr T_BOOLEAN_OR expr
 
2037       //        | expr T_BOOLEAN_AND expr
 
2038       //        | expr T_LOGICAL_OR expr
 
2039       //        | expr T_LOGICAL_AND expr
 
2040       //        | expr T_LOGICAL_XOR expr
 
2052       //        | expr T_IS_IDENTICAL expr
 
2053       //        | expr T_IS_NOT_IDENTICAL expr
 
2054       //        | expr T_IS_EQUAL expr
 
2055       //        | expr T_IS_NOT_EQUAL expr
 
2057       //        | expr T_IS_SMALLER_OR_EQUAL expr
 
2059       //        | expr T_IS_GREATER_OR_EQUAL expr
 
2060       //        | expr T_INSTANCEOF class_name_reference
 
2061       //        | expr '?' expr ':' expr
 
2062       if (Scanner.TRACE) {
 
2063         System.out.println("TRACE: expr_without_variable() PART 1");
 
2066       case TokenNameisset:
 
2067       case TokenNameempty:
 
2069       case TokenNameinclude:
 
2070       case TokenNameinclude_once:
 
2071       case TokenNamerequire:
 
2072       case TokenNamerequire_once:
 
2073         internal_functions_in_yacc();
 
2076       case TokenNameLPAREN:
 
2079         if (token == TokenNameRPAREN) {
 
2082           throwSyntaxError("')' expected in expression.");
 
2092       //    | T_INT_CAST expr
 
2093       //        | T_DOUBLE_CAST expr
 
2094       //        | T_STRING_CAST expr
 
2095       //        | T_ARRAY_CAST expr
 
2096       //        | T_OBJECT_CAST expr
 
2097       //        | T_BOOL_CAST expr
 
2098       //        | T_UNSET_CAST expr
 
2099       case TokenNameclone:
 
2100       case TokenNameprint:
 
2103       case TokenNameMINUS:
 
2105       case TokenNameTWIDDLE:
 
2106       case TokenNameintCAST:
 
2107       case TokenNamedoubleCAST:
 
2108       case TokenNamestringCAST:
 
2109       case TokenNamearrayCAST:
 
2110       case TokenNameobjectCAST:
 
2111       case TokenNameboolCAST:
 
2112       case TokenNameunsetCAST:
 
2122       //| T_STRING_VARNAME
 
2124       //| T_START_HEREDOC encaps_list T_END_HEREDOC
 
2125       //        | '`' encaps_list '`'
 
2127       //        | '`' encaps_list '`'
 
2128       case TokenNameEncapsedString0:
 
2129         scanner.encapsedStringStack.push(new Character('`'));
 
2132           if (token == TokenNameEncapsedString0) {
 
2135             if (token != TokenNameEncapsedString0) {
 
2136               throwSyntaxError("\'`\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
 
2140           scanner.encapsedStringStack.pop();
 
2144       //      | '\'' encaps_list '\''
 
2145       case TokenNameEncapsedString1:
 
2146         scanner.encapsedStringStack.push(new Character('\''));
 
2149           exprSourceStart = scanner.getCurrentTokenStartPosition();
 
2150           if (token == TokenNameEncapsedString1) {
 
2151             expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
 
2152                 .getCurrentTokenEndPosition());
 
2155             if (token != TokenNameEncapsedString1) {
 
2156               throwSyntaxError("\'\'\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
 
2158               expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
 
2159                   .getCurrentTokenEndPosition());
 
2163           scanner.encapsedStringStack.pop();
 
2167       //| '"' encaps_list '"'
 
2168       case TokenNameEncapsedString2:
 
2169         scanner.encapsedStringStack.push(new Character('"'));
 
2172           exprSourceStart = scanner.getCurrentTokenStartPosition();
 
2173           if (token == TokenNameEncapsedString2) {
 
2174             expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
 
2175                 .getCurrentTokenEndPosition());
 
2178             if (token != TokenNameEncapsedString2) {
 
2179               throwSyntaxError("'\"' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
 
2181               expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
 
2182                   .getCurrentTokenEndPosition());
 
2186           scanner.encapsedStringStack.pop();
 
2190       case TokenNameStringDoubleQuote:
 
2191         expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(), scanner.getCurrentTokenStartPosition(), scanner
 
2192             .getCurrentTokenEndPosition());
 
2195       case TokenNameStringSingleQuote:
 
2196         expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(), scanner.getCurrentTokenStartPosition(), scanner
 
2197             .getCurrentTokenEndPosition());
 
2200       case TokenNameIntegerLiteral:
 
2201       case TokenNameDoubleLiteral:
 
2202       case TokenNameStringInterpolated:
 
2205       case TokenNameCLASS_C:
 
2206       case TokenNameMETHOD_C:
 
2207       case TokenNameFUNC_C:
 
2210       case TokenNameHEREDOC:
 
2213       case TokenNamearray:
 
2214         //    T_ARRAY '(' array_pair_list ')'
 
2216         if (token == TokenNameLPAREN) {
 
2218           if (token == TokenNameRPAREN) {
 
2223           if (token != TokenNameRPAREN) {
 
2224             throwSyntaxError("')' or ',' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
 
2228           throwSyntaxError("'(' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
 
2232         //    | T_LIST '(' assignment_list ')' '=' expr
 
2234         if (token == TokenNameLPAREN) {
 
2237           if (token != TokenNameRPAREN) {
 
2238             throwSyntaxError("')' expected after 'list' keyword.");
 
2241           if (token != TokenNameEQUAL) {
 
2242             throwSyntaxError("'=' expected after 'list' keyword.");
 
2247           throwSyntaxError("'(' expected after 'list' keyword.");
 
2251         //      | T_NEW class_name_reference ctor_arguments
 
2253         Expression typeRef = class_name_reference();
 
2255         if (typeRef != null) {
 
2256           expression = typeRef;
 
2259       //        | T_INC rw_variable
 
2260       //        | T_DEC rw_variable
 
2261       case TokenNamePLUS_PLUS:
 
2262       case TokenNameMINUS_MINUS:
 
2266       //        | variable '=' expr
 
2267       //        | variable '=' '&' variable
 
2268       //        | variable '=' '&' T_NEW class_name_reference ctor_arguments
 
2269       //        | variable T_PLUS_EQUAL expr
 
2270       //        | variable T_MINUS_EQUAL expr
 
2271       //        | variable T_MUL_EQUAL expr
 
2272       //        | variable T_DIV_EQUAL expr
 
2273       //        | variable T_CONCAT_EQUAL expr
 
2274       //        | variable T_MOD_EQUAL expr
 
2275       //        | variable T_AND_EQUAL expr
 
2276       //        | variable T_OR_EQUAL expr
 
2277       //        | variable T_XOR_EQUAL expr
 
2278       //        | variable T_SL_EQUAL expr
 
2279       //        | variable T_SR_EQUAL expr
 
2280       //        | rw_variable T_INC
 
2281       //        | rw_variable T_DEC
 
2282       case TokenNameIdentifier:
 
2283       case TokenNameVariable:
 
2284       case TokenNameDOLLAR:
 
2285         boolean rememberedVar = false;
 
2286         Expression lhs = variable();
 
2288         case TokenNameEQUAL:
 
2290           if (token == TokenNameAND) {
 
2292             if (token == TokenNamenew) {
 
2293               // | variable '=' '&' T_NEW class_name_reference
 
2296               SingleTypeReference classRef = class_name_reference();
 
2298               if (classRef != null) {
 
2299                 if (lhs != null && lhs instanceof FieldReference) {
 
2301                   // $var = & new Object();
 
2302                   if (fMethodVariables != null) {
 
2303                     VariableInfo lhsInfo = new VariableInfo(((FieldReference) lhs).sourceStart());
 
2304                     lhsInfo.reference = classRef;
 
2305                     lhsInfo.typeIdentifier = classRef.token;
 
2306                     fMethodVariables.put(new String(((FieldReference) lhs).token), lhsInfo);
 
2307                     rememberedVar = true;
 
2312               Expression rhs = variable();
 
2313               if (rhs != null && rhs instanceof FieldReference && lhs != null && lhs instanceof FieldReference) {
 
2316                 if (fMethodVariables != null) {
 
2317                   VariableInfo rhsInfo = (VariableInfo) fMethodVariables.get(((FieldReference) rhs).token);
 
2318                   if (rhsInfo != null && rhsInfo.reference != null) {
 
2319                     VariableInfo lhsInfo = new VariableInfo(((FieldReference) lhs).sourceStart());
 
2320                     lhsInfo.reference = rhsInfo.reference;
 
2321                     lhsInfo.typeIdentifier = rhsInfo.typeIdentifier;
 
2322                     fMethodVariables.put(new String(((FieldReference) lhs).token), lhsInfo);
 
2323                     rememberedVar = true;
 
2329             Expression rhs = expr();
 
2330             if (lhs != null && lhs instanceof FieldReference) {
 
2331               if (rhs != null && rhs instanceof FieldReference) {
 
2334                 if (fMethodVariables != null) {
 
2335                   VariableInfo rhsInfo = (VariableInfo) fMethodVariables.get(((FieldReference) rhs).token);
 
2336                   if (rhsInfo != null && rhsInfo.reference != null) {
 
2337                     VariableInfo lhsInfo = new VariableInfo(((FieldReference) lhs).sourceStart());
 
2338                     lhsInfo.reference = rhsInfo.reference;
 
2339                     lhsInfo.typeIdentifier = rhsInfo.typeIdentifier;
 
2340                     fMethodVariables.put(new String(((FieldReference) lhs).token), lhsInfo);
 
2341                     rememberedVar = true;
 
2344               } else if (rhs != null && rhs instanceof SingleTypeReference) {
 
2346                 // $var = new Object();
 
2347                 if (fMethodVariables != null) {
 
2348                   VariableInfo lhsInfo = new VariableInfo(((FieldReference) lhs).sourceStart());
 
2349                   lhsInfo.reference = (SingleTypeReference) rhs;
 
2350                   lhsInfo.typeIdentifier = ((SingleTypeReference) rhs).token;
 
2351                   fMethodVariables.put(new String(((FieldReference) lhs).token), lhsInfo);
 
2352                   rememberedVar = true;
 
2357           if (rememberedVar == false && lhs != null && lhs instanceof FieldReference) {
 
2358             if (fMethodVariables != null) {
 
2359               VariableInfo lhsInfo = new VariableInfo(((FieldReference) lhs).sourceStart());
 
2360               fMethodVariables.put(new String(((FieldReference) lhs).token), lhsInfo);
 
2364         case TokenNamePLUS_EQUAL:
 
2365         case TokenNameMINUS_EQUAL:
 
2366         case TokenNameMULTIPLY_EQUAL:
 
2367         case TokenNameDIVIDE_EQUAL:
 
2368         case TokenNameDOT_EQUAL:
 
2369         case TokenNameREMAINDER_EQUAL:
 
2370         case TokenNameAND_EQUAL:
 
2371         case TokenNameOR_EQUAL:
 
2372         case TokenNameXOR_EQUAL:
 
2373         case TokenNameRIGHT_SHIFT_EQUAL:
 
2374         case TokenNameLEFT_SHIFT_EQUAL:
 
2378         case TokenNamePLUS_PLUS:
 
2379         case TokenNameMINUS_MINUS:
 
2383           if (!only_variable) {
 
2384             throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "').");
 
2392         if (token != TokenNameINLINE_HTML) {
 
2393           if (token > TokenNameKEYWORD) {
 
2397             throwSyntaxError("Error in expression (found token '" + scanner.toStringAction(token) + "').");
 
2402       if (Scanner.TRACE) {
 
2403         System.out.println("TRACE: expr_without_variable() PART 2");
 
2405       //        | expr T_BOOLEAN_OR expr
 
2406       //        | expr T_BOOLEAN_AND expr
 
2407       //        | expr T_LOGICAL_OR expr
 
2408       //        | expr T_LOGICAL_AND expr
 
2409       //        | expr T_LOGICAL_XOR expr
 
2421       //        | expr T_IS_IDENTICAL expr
 
2422       //        | expr T_IS_NOT_IDENTICAL expr
 
2423       //        | expr T_IS_EQUAL expr
 
2424       //        | expr T_IS_NOT_EQUAL expr
 
2426       //        | expr T_IS_SMALLER_OR_EQUAL expr
 
2428       //        | expr T_IS_GREATER_OR_EQUAL expr
 
2431         case TokenNameOR_OR:
 
2433           expression = new OR_OR_Expression(expression, expr(), token);
 
2435         case TokenNameAND_AND:
 
2437           expression = new AND_AND_Expression(expression, expr(), token);
 
2439         case TokenNameEQUAL_EQUAL:
 
2441           expression = new EqualExpression(expression, expr(), token);
 
2451         case TokenNameMINUS:
 
2452         case TokenNameMULTIPLY:
 
2453         case TokenNameDIVIDE:
 
2454         case TokenNameREMAINDER:
 
2455         case TokenNameLEFT_SHIFT:
 
2456         case TokenNameRIGHT_SHIFT:
 
2457         case TokenNameEQUAL_EQUAL_EQUAL:
 
2458         case TokenNameNOT_EQUAL_EQUAL:
 
2459         case TokenNameNOT_EQUAL:
 
2461         case TokenNameLESS_EQUAL:
 
2462         case TokenNameGREATER:
 
2463         case TokenNameGREATER_EQUAL:
 
2465           expression = new BinaryExpression(expression, expr(), token);
 
2467         //  | expr T_INSTANCEOF class_name_reference
 
2468         //      | expr '?' expr ':' expr
 
2469         case TokenNameinstanceof:
 
2471           TypeReference classRef = class_name_reference();
 
2472           expression = new InstanceOfExpression(expression, classRef, OperatorIds.INSTANCEOF);
 
2473           expression.sourceStart = exprSourceStart;
 
2474           expression.sourceEnd = scanner.getCurrentTokenEndPosition();
 
2476         case TokenNameQUESTION:
 
2478           Expression valueIfTrue = expr();
 
2479           if (token != TokenNameCOLON) {
 
2480             throwSyntaxError("':' expected in conditional expression.");
 
2483           Expression valueIfFalse = expr();
 
2485           expression = new ConditionalExpression(expression, valueIfTrue, valueIfFalse);
 
2491     } catch (SyntaxError e) {
 
2492       // try to find next token after expression with errors:
 
2493       if (token == TokenNameSEMICOLON) {
 
2497       if (token == TokenNameRBRACE || token == TokenNameRPAREN || token == TokenNameRBRACKET) {
 
2505   private SingleTypeReference class_name_reference() {
 
2506     //  class_name_reference:
 
2508     //| dynamic_class_name_reference
 
2509     SingleTypeReference ref = null;
 
2510     if (Scanner.TRACE) {
 
2511       System.out.println("TRACE: class_name_reference()");
 
2513     if (token == TokenNameIdentifier) {
 
2514       ref = new SingleTypeReference(scanner.getCurrentIdentifierSource(), scanner.getCurrentTokenStartPosition());
 
2518       dynamic_class_name_reference();
 
2523   private void dynamic_class_name_reference() {
 
2524     //dynamic_class_name_reference:
 
2525     //  base_variable T_OBJECT_OPERATOR object_property
 
2526     // dynamic_class_name_variable_properties
 
2528     if (Scanner.TRACE) {
 
2529       System.out.println("TRACE: dynamic_class_name_reference()");
 
2532     if (token == TokenNameMINUS_GREATER) {
 
2535       dynamic_class_name_variable_properties();
 
2539   private void dynamic_class_name_variable_properties() {
 
2540     //  dynamic_class_name_variable_properties:
 
2541     //                  dynamic_class_name_variable_properties
 
2542     // dynamic_class_name_variable_property
 
2544     if (Scanner.TRACE) {
 
2545       System.out.println("TRACE: dynamic_class_name_variable_properties()");
 
2547     while (token == TokenNameMINUS_GREATER) {
 
2548       dynamic_class_name_variable_property();
 
2552   private void dynamic_class_name_variable_property() {
 
2553     //  dynamic_class_name_variable_property:
 
2554     //  T_OBJECT_OPERATOR object_property
 
2555     if (Scanner.TRACE) {
 
2556       System.out.println("TRACE: dynamic_class_name_variable_property()");
 
2558     if (token == TokenNameMINUS_GREATER) {
 
2564   private void ctor_arguments() {
 
2567     //| '(' function_call_parameter_list ')'
 
2568     if (token == TokenNameLPAREN) {
 
2570       if (token == TokenNameRPAREN) {
 
2574       non_empty_function_call_parameter_list();
 
2575       if (token != TokenNameRPAREN) {
 
2576         throwSyntaxError("')' expected in ctor_arguments.");
 
2582   private void assignment_list() {
 
2584     //  assignment_list ',' assignment_list_element
 
2585     //| assignment_list_element
 
2587       assignment_list_element();
 
2588       if (token != TokenNameCOMMA) {
 
2595   private void assignment_list_element() {
 
2596     //assignment_list_element:
 
2598     //| T_LIST '(' assignment_list ')'
 
2600     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
 
2603       if (token == TokenNamelist) {
 
2605         if (token == TokenNameLPAREN) {
 
2608           if (token != TokenNameRPAREN) {
 
2609             throwSyntaxError("')' expected after 'list' keyword.");
 
2613           throwSyntaxError("'(' expected after 'list' keyword.");
 
2619   private void array_pair_list() {
 
2622     //| non_empty_array_pair_list possible_comma
 
2623     non_empty_array_pair_list();
 
2624     if (token == TokenNameCOMMA) {
 
2629   private void non_empty_array_pair_list() {
 
2630     //non_empty_array_pair_list:
 
2631     //  non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
 
2632     //| non_empty_array_pair_list ',' expr
 
2633     //| expr T_DOUBLE_ARROW expr
 
2635     //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
 
2636     //| non_empty_array_pair_list ',' '&' w_variable
 
2637     //| expr T_DOUBLE_ARROW '&' w_variable
 
2640       if (token == TokenNameAND) {
 
2645         if (token == TokenNameAND) {
 
2648         } else if (token == TokenNameEQUAL_GREATER) {
 
2650           if (token == TokenNameAND) {
 
2658       if (token != TokenNameCOMMA) {
 
2662       if (token == TokenNameRPAREN) {
 
2668   //  private void variableList() {
 
2671   //      if (token == TokenNameCOMMA) {
 
2678   private Expression variable_without_objects() {
 
2679     //  variable_without_objects:
 
2680     //                  reference_variable
 
2681     //          | simple_indirect_reference reference_variable
 
2682     if (Scanner.TRACE) {
 
2683       System.out.println("TRACE: variable_without_objects()");
 
2685     while (token == TokenNameDOLLAR) {
 
2688     return reference_variable();
 
2691   private Expression function_call() {
 
2693     //  T_STRING '(' function_call_parameter_list ')'
 
2694     //| class_constant '(' function_call_parameter_list ')'
 
2695     //| static_member '(' function_call_parameter_list ')'
 
2696     //| variable_without_objects '(' function_call_parameter_list ')'
 
2697     char[] defineName = null;
 
2698     char[] ident = null;
 
2701     Expression ref = null;
 
2702     if (Scanner.TRACE) {
 
2703       System.out.println("TRACE: function_call()");
 
2705     if (token == TokenNameIdentifier) {
 
2706       ident = scanner.getCurrentIdentifierSource();
 
2708       startPos = scanner.getCurrentTokenStartPosition();
 
2709       endPos = scanner.getCurrentTokenEndPosition();
 
2712       case TokenNamePAAMAYIM_NEKUDOTAYIM:
 
2716         if (token == TokenNameIdentifier) {
 
2721           variable_without_objects();
 
2726       ref = variable_without_objects();
 
2728     if (token != TokenNameLPAREN) {
 
2729       if (defineName != null) {
 
2730         // does this identifier contain only uppercase characters?
 
2731         if (defineName.length == 3) {
 
2732           if (defineName[0] == 'd' && defineName[1] == 'i' && defineName[2] == 'e') {
 
2735         } else if (defineName.length == 4) {
 
2736           if (defineName[0] == 't' && defineName[1] == 'r' && defineName[2] == 'u' && defineName[3] == 'e') {
 
2738           } else if (defineName[0] == 'n' && defineName[1] == 'u' && defineName[2] == 'l' && defineName[3] == 'l') {
 
2741         } else if (defineName.length == 5) {
 
2742           if (defineName[0] == 'f' && defineName[1] == 'a' && defineName[2] == 'l' && defineName[3] == 's' && defineName[4] == 'e') {
 
2746         if (defineName != null) {
 
2747           for (int i = 0; i < defineName.length; i++) {
 
2748             if (Character.isLowerCase(defineName[i])) {
 
2749               problemReporter.phpUppercaseIdentifierWarning(startPos, endPos, referenceContext, compilationUnit.compilationResult);
 
2755       // TODO is this ok ?
 
2757       //      throwSyntaxError("'(' expected in function call.");
 
2760     if (token == TokenNameRPAREN) {
 
2764     non_empty_function_call_parameter_list();
 
2765     if (token != TokenNameRPAREN) {
 
2766       String functionName;
 
2767       if (ident == null) {
 
2768         functionName = new String(" ");
 
2770         functionName = new String(ident);
 
2772       throwSyntaxError("')' expected in function call (" + functionName + ").");
 
2778   //  private void function_call_parameter_list() {
 
2779   //    function_call_parameter_list:
 
2780   //            non_empty_function_call_parameter_list { $$ = $1; }
 
2783   private void non_empty_function_call_parameter_list() {
 
2784     //non_empty_function_call_parameter_list:
 
2785     //          expr_without_variable
 
2788     //  | non_empty_function_call_parameter_list ',' expr_without_variable
 
2789     //  | non_empty_function_call_parameter_list ',' variable
 
2790     //  | non_empty_function_call_parameter_list ',' '&' w_variable
 
2791     if (Scanner.TRACE) {
 
2792       System.out.println("TRACE: non_empty_function_call_parameter_list()");
 
2795       if (token == TokenNameAND) {
 
2799         //        if (token == TokenNameIdentifier || token ==
 
2800         // TokenNameVariable
 
2801         //            || token == TokenNameDOLLAR) {
 
2804         expr_without_variable(true);
 
2807       if (token != TokenNameCOMMA) {
 
2814   private void fully_qualified_class_name() {
 
2815     if (token == TokenNameIdentifier) {
 
2818       throwSyntaxError("Class name expected.");
 
2822   private void static_member() {
 
2824     //  fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
 
2825     // variable_without_objects
 
2826     if (Scanner.TRACE) {
 
2827       System.out.println("TRACE: static_member()");
 
2829     fully_qualified_class_name();
 
2830     if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
 
2831       throwSyntaxError("'::' expected after class name (static_member).");
 
2834     variable_without_objects();
 
2837   private Expression base_variable_with_function_calls() {
 
2838     //  base_variable_with_function_calls:
 
2841     boolean functionCall = false;
 
2842     if (Scanner.TRACE) {
 
2843       System.out.println("TRACE: base_variable_with_function_calls()");
 
2845     //    if (token == TokenNameIdentifier) {
 
2846     //      functionCall = true;
 
2847     //    } else if (token == TokenNameVariable) {
 
2848     //      int tempToken = token;
 
2849     //      int tempPosition = scanner.currentPosition;
 
2851     //      if (token == TokenNameLPAREN) {
 
2852     //        functionCall = true;
 
2854     //      token = tempToken;
 
2855     //      scanner.currentPosition = tempPosition;
 
2856     //      scanner.phpMode = true;
 
2858     //    if (functionCall) {
 
2859     return function_call();
 
2865   private Expression base_variable() {
 
2867     //                  reference_variable
 
2868     //          | simple_indirect_reference reference_variable
 
2870     Expression ref = null;
 
2871     if (Scanner.TRACE) {
 
2872       System.out.println("TRACE: base_variable()");
 
2874     if (token == TokenNameIdentifier) {
 
2877       while (token == TokenNameDOLLAR) {
 
2880       reference_variable();
 
2885   //  private void simple_indirect_reference() {
 
2886   //    // simple_indirect_reference:
 
2888   //    //| simple_indirect_reference '$'
 
2890   private Expression reference_variable() {
 
2891     //  reference_variable:
 
2892     //                  reference_variable '[' dim_offset ']'
 
2893     //          | reference_variable '{' expr '}'
 
2894     //          | compound_variable
 
2895     Expression ref = null;
 
2896     if (Scanner.TRACE) {
 
2897       System.out.println("TRACE: reference_variable()");
 
2899     ref = compound_variable();
 
2901       if (token == TokenNameLBRACE) {
 
2905         if (token != TokenNameRBRACE) {
 
2906           throwSyntaxError("'}' expected in reference variable.");
 
2909       } else if (token == TokenNameLBRACKET) {
 
2912         if (token != TokenNameRBRACKET) {
 
2915           if (token != TokenNameRBRACKET) {
 
2916             throwSyntaxError("']' expected in reference variable.");
 
2927   private Expression compound_variable() {
 
2928     //  compound_variable:
 
2930     //          | '$' '{' expr '}'
 
2931     if (Scanner.TRACE) {
 
2932       System.out.println("TRACE: compound_variable()");
 
2934     if (token == TokenNameVariable) {
 
2935       FieldReference ref = new FieldReference(scanner.getCurrentIdentifierSource(), scanner.getCurrentTokenStartPosition());
 
2939       // because of simple_indirect_reference
 
2940       while (token == TokenNameDOLLAR) {
 
2943       if (token != TokenNameLBRACE) {
 
2944         reportSyntaxError("'{' expected after compound variable token '$'.");
 
2949       if (token != TokenNameRBRACE) {
 
2950         throwSyntaxError("'}' expected after compound variable token '$'.");
 
2957   //  private void dim_offset() {
 
2963   private void object_property() {
 
2966     //| variable_without_objects
 
2967     if (Scanner.TRACE) {
 
2968       System.out.println("TRACE: object_property()");
 
2970     if (token == TokenNameVariable || token == TokenNameDOLLAR) {
 
2971       variable_without_objects();
 
2977   private void object_dim_list() {
 
2979     //  object_dim_list '[' dim_offset ']'
 
2980     //| object_dim_list '{' expr '}'
 
2982     if (Scanner.TRACE) {
 
2983       System.out.println("TRACE: object_dim_list()");
 
2987       if (token == TokenNameLBRACE) {
 
2990         if (token != TokenNameRBRACE) {
 
2991           throwSyntaxError("'}' expected in object_dim_list.");
 
2994       } else if (token == TokenNameLBRACKET) {
 
2996         if (token == TokenNameRBRACKET) {
 
3001         if (token != TokenNameRBRACKET) {
 
3002           throwSyntaxError("']' expected in object_dim_list.");
 
3011   private void variable_name() {
 
3015     if (Scanner.TRACE) {
 
3016       System.out.println("TRACE: variable_name()");
 
3018     if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
 
3019       if (token > TokenNameKEYWORD) {
 
3020         // TODO show a warning "Keyword used as variable" ?
 
3024       if (token != TokenNameLBRACE) {
 
3025         throwSyntaxError("'{' expected in variable name.");
 
3029       if (token != TokenNameRBRACE) {
 
3030         throwSyntaxError("'}' expected in variable name.");
 
3036   private void r_variable() {
 
3040   private void w_variable() {
 
3044   private void rw_variable() {
 
3048   private Expression variable() {
 
3050     //          base_variable_with_function_calls T_OBJECT_OPERATOR
 
3051     //                  object_property method_or_not variable_properties
 
3052     //  | base_variable_with_function_calls
 
3053     Expression ref = base_variable_with_function_calls();
 
3054     if (token == TokenNameMINUS_GREATER) {
 
3059       variable_properties();
 
3064   private void variable_properties() {
 
3065     //  variable_properties:
 
3066     //                  variable_properties variable_property
 
3068     while (token == TokenNameMINUS_GREATER) {
 
3069       variable_property();
 
3073   private void variable_property() {
 
3074     //  variable_property:
 
3075     //                  T_OBJECT_OPERATOR object_property method_or_not
 
3076     if (Scanner.TRACE) {
 
3077       System.out.println("TRACE: variable_property()");
 
3079     if (token == TokenNameMINUS_GREATER) {
 
3084       throwSyntaxError("'->' expected in variable_property.");
 
3088   private void method_or_not() {
 
3090     //                  '(' function_call_parameter_list ')'
 
3092     if (Scanner.TRACE) {
 
3093       System.out.println("TRACE: method_or_not()");
 
3095     if (token == TokenNameLPAREN) {
 
3097       if (token == TokenNameRPAREN) {
 
3101       non_empty_function_call_parameter_list();
 
3102       if (token != TokenNameRPAREN) {
 
3103         throwSyntaxError("')' expected in method_or_not.");
 
3109   private void exit_expr() {
 
3113     if (token != TokenNameLPAREN) {
 
3117     if (token == TokenNameRPAREN) {
 
3122     if (token != TokenNameRPAREN) {
 
3123       throwSyntaxError("')' expected after keyword 'exit'");
 
3128   private void encaps_list() {
 
3129     //                  encaps_list encaps_var
 
3130     //          | encaps_list T_STRING
 
3131     //          | encaps_list T_NUM_STRING
 
3132     //          | encaps_list T_ENCAPSED_AND_WHITESPACE
 
3133     //          | encaps_list T_CHARACTER
 
3134     //          | encaps_list T_BAD_CHARACTER
 
3135     //          | encaps_list '['
 
3136     //          | encaps_list ']'
 
3137     //          | encaps_list '{'
 
3138     //          | encaps_list '}'
 
3139     //          | encaps_list T_OBJECT_OPERATOR
 
3143       case TokenNameSTRING:
 
3146       case TokenNameLBRACE:
 
3147         //          scanner.encapsedStringStack.pop();
 
3150       case TokenNameRBRACE:
 
3151         //          scanner.encapsedStringStack.pop();
 
3154       case TokenNameLBRACKET:
 
3155         //          scanner.encapsedStringStack.pop();
 
3158       case TokenNameRBRACKET:
 
3159         //          scanner.encapsedStringStack.pop();
 
3162       case TokenNameMINUS_GREATER:
 
3163         //          scanner.encapsedStringStack.pop();
 
3166       case TokenNameVariable:
 
3167       case TokenNameDOLLAR_LBRACE:
 
3168       case TokenNameLBRACE_DOLLAR:
 
3172         char encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
 
3173         if (encapsedChar == '$') {
 
3174           scanner.encapsedStringStack.pop();
 
3175           encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
 
3176           switch (encapsedChar) {
 
3178             if (token == TokenNameEncapsedString0) {
 
3181             token = TokenNameSTRING;
 
3184             if (token == TokenNameEncapsedString1) {
 
3187             token = TokenNameSTRING;
 
3190             if (token == TokenNameEncapsedString2) {
 
3193             token = TokenNameSTRING;
 
3202   private void encaps_var() {
 
3204     //          | T_VARIABLE '[' encaps_var_offset ']'
 
3205     //          | T_VARIABLE T_OBJECT_OPERATOR T_STRING
 
3206     //          | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
 
3207     //          | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
 
3208     //          | T_CURLY_OPEN variable '}'
 
3210     case TokenNameVariable:
 
3212       if (token == TokenNameLBRACKET) {
 
3214         expr(); //encaps_var_offset();
 
3215         if (token != TokenNameRBRACKET) {
 
3216           throwSyntaxError("']' expected after variable.");
 
3218         //          scanner.encapsedStringStack.pop();
 
3221       } else if (token == TokenNameMINUS_GREATER) {
 
3223         if (token != TokenNameIdentifier) {
 
3224           throwSyntaxError("Identifier expected after '->'.");
 
3226         //          scanner.encapsedStringStack.pop();
 
3230       //          // scanner.encapsedStringStack.pop();
 
3231       //          int tempToken = TokenNameSTRING;
 
3232       //          if (!scanner.encapsedStringStack.isEmpty()
 
3233       //              && (token == TokenNameEncapsedString0
 
3234       //                  || token == TokenNameEncapsedString1
 
3235       //                  || token == TokenNameEncapsedString2 || token ==
 
3236       // TokenNameERROR)) {
 
3237       //            char encapsedChar = ((Character)
 
3238       // scanner.encapsedStringStack.peek())
 
3241       //              case TokenNameEncapsedString0 :
 
3242       //                if (encapsedChar == '`') {
 
3243       //                  tempToken = TokenNameEncapsedString0;
 
3246       //              case TokenNameEncapsedString1 :
 
3247       //                if (encapsedChar == '\'') {
 
3248       //                  tempToken = TokenNameEncapsedString1;
 
3251       //              case TokenNameEncapsedString2 :
 
3252       //                if (encapsedChar == '"') {
 
3253       //                  tempToken = TokenNameEncapsedString2;
 
3256       //              case TokenNameERROR :
 
3257       //                if (scanner.source[scanner.currentPosition - 1] == '\\') {
 
3258       //                  scanner.currentPosition--;
 
3264       //          token = tempToken;
 
3267     case TokenNameDOLLAR_LBRACE:
 
3269       if (token == TokenNameDOLLAR_LBRACE) {
 
3271       } else if (token == TokenNameIdentifier) {
 
3273         if (token == TokenNameLBRACKET) {
 
3275           //            if (token == TokenNameRBRACKET) {
 
3279           if (token != TokenNameRBRACKET) {
 
3280             throwSyntaxError("']' expected after '${'.");
 
3288       if (token != TokenNameRBRACE) {
 
3289         throwSyntaxError("'}' expected.");
 
3293     case TokenNameLBRACE_DOLLAR:
 
3295       if (token == TokenNameLBRACE_DOLLAR) {
 
3297       } else if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
 
3299         if (token == TokenNameLBRACKET) {
 
3301           //            if (token == TokenNameRBRACKET) {
 
3305           if (token != TokenNameRBRACKET) {
 
3306             throwSyntaxError("']' expected.");
 
3310         } else if (token == TokenNameMINUS_GREATER) {
 
3312           if (token != TokenNameIdentifier && token != TokenNameVariable) {
 
3313             throwSyntaxError("String or Variable token expected.");
 
3316           if (token == TokenNameLBRACKET) {
 
3318             //            if (token == TokenNameRBRACKET) {
 
3322             if (token != TokenNameRBRACKET) {
 
3323               throwSyntaxError("']' expected after '${'.");
 
3329         //          if (token != TokenNameRBRACE) {
 
3330         //            throwSyntaxError("'}' expected after '{$'.");
 
3332         //          // scanner.encapsedStringStack.pop();
 
3336         if (token != TokenNameRBRACE) {
 
3337           throwSyntaxError("'}' expected.");
 
3339         //          scanner.encapsedStringStack.pop();
 
3346   private void encaps_var_offset() {
 
3351     case TokenNameSTRING:
 
3354     case TokenNameIntegerLiteral:
 
3357     case TokenNameVariable:
 
3360     case TokenNameIdentifier:
 
3364       throwSyntaxError("Variable or String token expected.");
 
3369   private void internal_functions_in_yacc() {
 
3372     case TokenNameisset:
 
3373       //        T_ISSET '(' isset_variables ')'
 
3375       if (token != TokenNameLPAREN) {
 
3376         throwSyntaxError("'(' expected after keyword 'isset'");
 
3380       if (token != TokenNameRPAREN) {
 
3381         throwSyntaxError("')' expected after keyword 'isset'");
 
3385     case TokenNameempty:
 
3386       //        T_EMPTY '(' variable ')'
 
3388       if (token != TokenNameLPAREN) {
 
3389         throwSyntaxError("'(' expected after keyword 'empty'");
 
3393       if (token != TokenNameRPAREN) {
 
3394         throwSyntaxError("')' expected after keyword 'empty'");
 
3398     case TokenNameinclude:
 
3400       checkFileName(token);
 
3402     case TokenNameinclude_once:
 
3403       //        T_INCLUDE_ONCE expr
 
3404       checkFileName(token);
 
3407       //        T_EVAL '(' expr ')'
 
3409       if (token != TokenNameLPAREN) {
 
3410         throwSyntaxError("'(' expected after keyword 'eval'");
 
3414       if (token != TokenNameRPAREN) {
 
3415         throwSyntaxError("')' expected after keyword 'eval'");
 
3419     case TokenNamerequire:
 
3421       checkFileName(token);
 
3423     case TokenNamerequire_once:
 
3424       //        T_REQUIRE_ONCE expr
 
3425       checkFileName(token);
 
3430   private void checkFileName(int includeToken) {
 
3431     //<include-token> expr
 
3432     int start = scanner.getCurrentTokenStartPosition();
 
3433     boolean hasLPAREN = false;
 
3435     if (token == TokenNameLPAREN) {
 
3439     Expression expression = expr();
 
3441       if (token == TokenNameRPAREN) {
 
3444         throwSyntaxError("')' expected for keyword '" + scanner.toStringAction(includeToken) + "'");
 
3447     char[] currTokenSource = scanner.getCurrentTokenSource(start);
 
3449     if (scanner.compilationUnit != null) {
 
3450       IResource resource = scanner.compilationUnit.getResource();
 
3451       if (resource != null && resource instanceof IFile) {
 
3452         file = (IFile) resource;
 
3456     tokens = new char[1][];
 
3457     tokens[0] = currTokenSource;
 
3459     ImportReference impt = new ImportReference(tokens, currTokenSource, start, scanner.getCurrentTokenEndPosition(), false);
 
3460     impt.declarationSourceEnd = impt.sourceEnd;
 
3461     impt.declarationEnd = impt.declarationSourceEnd;
 
3462     //endPosition is just before the ;
 
3463     impt.declarationSourceStart = start;
 
3464     includesList.add(impt);
 
3466     if (expression instanceof StringLiteral) {
 
3467       StringLiteral literal = (StringLiteral) expression;
 
3468       char[] includeName = literal.source();
 
3469       if (includeName.length == 0) {
 
3470         reportSyntaxError("Empty filename after keyword '" + scanner.toStringAction(includeToken) + "'", literal.sourceStart,
 
3471             literal.sourceStart + 1);
 
3473       String includeNameString = new String(includeName);
 
3474       if (literal instanceof StringLiteralDQ) {
 
3475         if (includeNameString.indexOf('$') >= 0) {
 
3476           // assuming that the filename contains a variable => no filename check
 
3480       if (includeNameString.startsWith("http://")) {
 
3481         // assuming external include location
 
3485         // check the filename:
 
3486         //      System.out.println(new String(compilationUnit.getFileName())+" - "+ expression.toStringExpression());
 
3487         IProject project = file.getProject();
 
3488         if (project != null) {
 
3489           IPath path = PHPFileUtil.determineFilePath(includeNameString, file, project);
 
3492             //              reportSyntaxError("File: " + expression.toStringExpression() + " doesn't exist in project: "
 
3493             //                  + project.getLocation().toString(), literal.sourceStart, literal.sourceEnd);
 
3494             String[] args = { expression.toStringExpression(), project.getLocation().toString() };
 
3495             problemReporter.phpIncludeNotExistWarning(args, literal.sourceStart, literal.sourceEnd, referenceContext,
 
3496                 compilationUnit.compilationResult);
 
3499               //              String projectPath = ProjectPrefUtil.getDocumentRoot(file.getProject()).toString();
 
3500               //              String filePath = file.getRawLocation().toString();
 
3501               String filePath = path.toString();
 
3502               String ext = file.getRawLocation().getFileExtension();
 
3503               int fileExtensionLength = ext == null ? 0 : ext.length() + 1;
 
3506               impt.tokens = CharOperation.splitOn('/', filePath.toCharArray(), 0, filePath.length() - fileExtensionLength);
 
3507               impt.setFile(PHPFileUtil.createFile(path, project));
 
3508             } catch (Exception e) {
 
3509               // the file is outside of the workspace
 
3517   private void isset_variables() {
 
3519     //  | isset_variables ','
 
3520     if (token == TokenNameRPAREN) {
 
3521       throwSyntaxError("Variable expected after keyword 'isset'");
 
3525       if (token == TokenNameCOMMA) {
 
3533   private boolean common_scalar() {
 
3537     //  | T_CONSTANT_ENCAPSED_STRING
 
3544     case TokenNameIntegerLiteral:
 
3547     case TokenNameDoubleLiteral:
 
3550     case TokenNameStringDoubleQuote:
 
3553     case TokenNameStringSingleQuote:
 
3556     case TokenNameStringInterpolated:
 
3565     case TokenNameCLASS_C:
 
3568     case TokenNameMETHOD_C:
 
3571     case TokenNameFUNC_C:
 
3578   private void scalar() {
 
3581     //| T_STRING_VARNAME
 
3584     //| '"' encaps_list '"'
 
3585     //| '\'' encaps_list '\''
 
3586     //| T_START_HEREDOC encaps_list T_END_HEREDOC
 
3587     throwSyntaxError("Not yet implemented (scalar).");
 
3590   private void static_scalar() {
 
3591     //    static_scalar: /* compile-time evaluated scalars */
 
3594     //  | '+' static_scalar
 
3595     //  | '-' static_scalar
 
3596     //  | T_ARRAY '(' static_array_pair_list ')'
 
3597     //  | static_class_constant
 
3598     if (common_scalar()) {
 
3602     case TokenNameIdentifier:
 
3604       //        static_class_constant:
 
3605       //                T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
 
3606       if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
 
3608         if (token == TokenNameIdentifier) {
 
3611           throwSyntaxError("Identifier expected after '::' operator.");
 
3615     case TokenNameEncapsedString0:
 
3617         scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3618         while (scanner.currentCharacter != '`') {
 
3619           if (scanner.currentCharacter == '\\') {
 
3620             scanner.currentPosition++;
 
3622           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3625       } catch (IndexOutOfBoundsException e) {
 
3626         throwSyntaxError("'`' expected at end of static string.");
 
3629     case TokenNameEncapsedString1:
 
3631         scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3632         while (scanner.currentCharacter != '\'') {
 
3633           if (scanner.currentCharacter == '\\') {
 
3634             scanner.currentPosition++;
 
3636           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3639       } catch (IndexOutOfBoundsException e) {
 
3640         throwSyntaxError("'\'' expected at end of static string.");
 
3643     case TokenNameEncapsedString2:
 
3645         scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3646         while (scanner.currentCharacter != '"') {
 
3647           if (scanner.currentCharacter == '\\') {
 
3648             scanner.currentPosition++;
 
3650           scanner.currentCharacter = scanner.source[scanner.currentPosition++];
 
3653       } catch (IndexOutOfBoundsException e) {
 
3654         throwSyntaxError("'\"' expected at end of static string.");
 
3661     case TokenNameMINUS:
 
3665     case TokenNamearray:
 
3667       if (token != TokenNameLPAREN) {
 
3668         throwSyntaxError("'(' expected after keyword 'array'");
 
3671       if (token == TokenNameRPAREN) {
 
3675       non_empty_static_array_pair_list();
 
3676       if (token != TokenNameRPAREN) {
 
3677         throwSyntaxError("')' or ',' expected after keyword 'array'");
 
3681     //      case TokenNamenull :
 
3684     //      case TokenNamefalse :
 
3687     //      case TokenNametrue :
 
3691       throwSyntaxError("Static scalar/constant expected.");
 
3695   private void non_empty_static_array_pair_list() {
 
3696     //  non_empty_static_array_pair_list:
 
3697     //  non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
 
3699     //| non_empty_static_array_pair_list ',' static_scalar
 
3700     //| static_scalar T_DOUBLE_ARROW static_scalar
 
3704       if (token == TokenNameEQUAL_GREATER) {
 
3708       if (token != TokenNameCOMMA) {
 
3712       if (token == TokenNameRPAREN) {
 
3718   public void reportSyntaxError() { //int act, int currentKind, int
 
3720     /* remember current scanner position */
 
3721     int startPos = scanner.startPosition;
 
3722     int currentPos = scanner.currentPosition;
 
3723     //          String[] expectings;
 
3724     //          String tokenName = name[symbol_index[currentKind]];
 
3725     //fetch all "accurate" possible terminals that could recover the error
 
3726     //          int start, end = start = asi(stack[stateStackTop]);
 
3727     //          while (asr[end] != 0)
 
3729     //          int length = end - start;
 
3730     //          expectings = new String[length];
 
3731     //          if (length != 0) {
 
3732     //                  char[] indexes = new char[length];
 
3733     //                  System.arraycopy(asr, start, indexes, 0, length);
 
3734     //                  for (int i = 0; i < length; i++) {
 
3735     //                          expectings[i] = name[symbol_index[indexes[i]]];
 
3738     //if the pb is an EOF, try to tell the user that they are some
 
3739     //          if (tokenName.equals(UNEXPECTED_EOF)) {
 
3740     //                  if (!this.checkAndReportBracketAnomalies(problemReporter())) {
 
3741     //                          char[] tokenSource;
 
3743     //                                  tokenSource = this.scanner.getCurrentTokenSource();
 
3744     //                          } catch (Exception e) {
 
3745     //                                  tokenSource = new char[] {};
 
3747     //                          problemReporter().parseError(
 
3748     //                                  this.scanner.startPosition,
 
3749     //                                  this.scanner.currentPosition - 1,
 
3754     //          } else { //the next test is HEAVILY grammar DEPENDENT.
 
3755     //                  if ((length == 14)
 
3756     //                          && (expectings[0] == "=") //$NON-NLS-1$
 
3757     //                          && (expectings[1] == "*=") //$NON-NLS-1$
 
3758     //                          && (expressionPtr > -1)) {
 
3759     //                                  switch(currentKind) {
 
3760     //                                          case TokenNameSEMICOLON:
 
3761     //                                          case TokenNamePLUS:
 
3762     //                                          case TokenNameMINUS:
 
3763     //                                          case TokenNameDIVIDE:
 
3764     //                                          case TokenNameREMAINDER:
 
3765     //                                          case TokenNameMULTIPLY:
 
3766     //                                          case TokenNameLEFT_SHIFT:
 
3767     //                                          case TokenNameRIGHT_SHIFT:
 
3768     //// case TokenNameUNSIGNED_RIGHT_SHIFT:
 
3769     //                                          case TokenNameLESS:
 
3770     //                                          case TokenNameGREATER:
 
3771     //                                          case TokenNameLESS_EQUAL:
 
3772     //                                          case TokenNameGREATER_EQUAL:
 
3773     //                                          case TokenNameEQUAL_EQUAL:
 
3774     //                                          case TokenNameNOT_EQUAL:
 
3775     //                                          case TokenNameXOR:
 
3776     //                                          case TokenNameAND:
 
3777     //                                          case TokenNameOR:
 
3778     //                                          case TokenNameOR_OR:
 
3779     //                                          case TokenNameAND_AND:
 
3780     //                                                  // the ; is not the expected token ==> it ends a statement when an
 
3781     // expression is not ended
 
3782     //                                                  problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
 
3784     //                                          case TokenNameRBRACE :
 
3785     //                                                  problemReporter().missingSemiColon(expressionStack[expressionPtr]);
 
3788     //                                                  char[] tokenSource;
 
3790     //                                                          tokenSource = this.scanner.getCurrentTokenSource();
 
3791     //                                                  } catch (Exception e) {
 
3792     //                                                          tokenSource = new char[] {};
 
3794     //                                                  problemReporter().parseError(
 
3795     //                                                          this.scanner.startPosition,
 
3796     //                                                          this.scanner.currentPosition - 1,
 
3800     //                                                  this.checkAndReportBracketAnomalies(problemReporter());
 
3805       tokenSource = this.scanner.getCurrentTokenSource();
 
3806     } catch (Exception e) {
 
3807       tokenSource = new char[] {};
 
3809     //                          problemReporter().parseError(
 
3810     //                                  this.scanner.startPosition,
 
3811     //                                  this.scanner.currentPosition - 1,
 
3815     this.checkAndReportBracketAnomalies(problemReporter());
 
3818     /* reset scanner where it was */
 
3819     scanner.startPosition = startPos;
 
3820     scanner.currentPosition = currentPos;
 
3823   public static final int RoundBracket = 0;
 
3825   public static final int SquareBracket = 1;
 
3827   public static final int CurlyBracket = 2;
 
3829   public static final int BracketKinds = 3;
 
3831   protected int[] nestedMethod; //the ptr is nestedType
 
3833   protected int nestedType, dimensions;
 
3835   //variable set stack
 
3836   final static int VariableStackIncrement = 10;
 
3838   HashMap fTypeVariables = null;
 
3840   HashMap fMethodVariables = null;
 
3843   final static int AstStackIncrement = 100;
 
3845   protected int astPtr;
 
3847   protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
 
3849   protected int astLengthPtr;
 
3851   protected int[] astLengthStack;
 
3853   ASTNode[] noAstNodes = new ASTNode[AstStackIncrement];
 
3855   public CompilationUnitDeclaration compilationUnit; /*
 
3856                                                       * the result from parse()
 
3859   protected ReferenceContext referenceContext;
 
3861   protected ProblemReporter problemReporter;
 
3863   protected CompilerOptions options;
 
3865   private ArrayList includesList;
 
3867   //  protected CompilationResult compilationResult;
 
3869    * Returns this parser's problem reporter initialized with its reference context. Also it is assumed that a problem is going to be
 
3870    * reported, so initializes the compilation result's line positions.
 
3872   public ProblemReporter problemReporter() {
 
3873     if (scanner.recordLineSeparator) {
 
3874       compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
 
3876     problemReporter.referenceContext = referenceContext;
 
3877     return problemReporter;
 
3881    * Reconsider the entire source looking for inconsistencies in {} () []
 
3883   public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
 
3884     scanner.wasAcr = false;
 
3885     boolean anomaliesDetected = false;
 
3887       char[] source = scanner.source;
 
3888       int[] leftCount = { 0, 0, 0 };
 
3889       int[] rightCount = { 0, 0, 0 };
 
3890       int[] depths = { 0, 0, 0 };
 
3891       int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] };
 
3892       int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] };
 
3893       int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] };
 
3894       int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] };
 
3895       scanner.currentPosition = scanner.initialPosition; //starting
 
3897       // (first-zero-based
 
3899       while (scanner.currentPosition < scanner.eofPosition) { //loop for
 
3904           // ---------Consume white space and handles
 
3905           // startPosition---------
 
3906           boolean isWhiteSpace;
 
3908             scanner.startPosition = scanner.currentPosition;
 
3909             //                                          if (((scanner.currentCharacter =
 
3910             // source[scanner.currentPosition++]) == '\\') &&
 
3911             // (source[scanner.currentPosition] == 'u')) {
 
3912             //                                                  isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
 
3914             if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
 
3915               if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
 
3916                 // only record line positions we have not
 
3918                 scanner.pushLineSeparator();
 
3921             isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
 
3923           } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
 
3924           // -------consume token until } is found---------
 
3925           switch (scanner.currentCharacter) {
 
3927             int index = leftCount[CurlyBracket]++;
 
3928             if (index == leftPositions[CurlyBracket].length) {
 
3929               System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
 
3930               System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
 
3932             leftPositions[CurlyBracket][index] = scanner.startPosition;
 
3933             leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
 
3937             int index = rightCount[CurlyBracket]++;
 
3938             if (index == rightPositions[CurlyBracket].length) {
 
3939               System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
 
3940               System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
 
3942             rightPositions[CurlyBracket][index] = scanner.startPosition;
 
3943             rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
 
3947             int index = leftCount[RoundBracket]++;
 
3948             if (index == leftPositions[RoundBracket].length) {
 
3949               System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
 
3950               System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
 
3952             leftPositions[RoundBracket][index] = scanner.startPosition;
 
3953             leftDepths[RoundBracket][index] = depths[RoundBracket]++;
 
3957             int index = rightCount[RoundBracket]++;
 
3958             if (index == rightPositions[RoundBracket].length) {
 
3959               System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
 
3960               System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
 
3962             rightPositions[RoundBracket][index] = scanner.startPosition;
 
3963             rightDepths[RoundBracket][index] = --depths[RoundBracket];
 
3967             int index = leftCount[SquareBracket]++;
 
3968             if (index == leftPositions[SquareBracket].length) {
 
3969               System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
 
3970               System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
 
3972             leftPositions[SquareBracket][index] = scanner.startPosition;
 
3973             leftDepths[SquareBracket][index] = depths[SquareBracket]++;
 
3977             int index = rightCount[SquareBracket]++;
 
3978             if (index == rightPositions[SquareBracket].length) {
 
3979               System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
 
3980               System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
 
3982             rightPositions[SquareBracket][index] = scanner.startPosition;
 
3983             rightDepths[SquareBracket][index] = --depths[SquareBracket];
 
3987             if (scanner.getNextChar('\\')) {
 
3988               scanner.scanEscapeCharacter();
 
3989             } else { // consume next character
 
3990               scanner.unicodeAsBackSlash = false;
 
3991               //                                                                        if (((scanner.currentCharacter =
 
3992               // source[scanner.currentPosition++]) ==
 
3994               // (source[scanner.currentPosition] ==
 
3996               //                                                                                scanner.getNextUnicodeChar();
 
3998               if (scanner.withoutUnicodePtr != 0) {
 
3999                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
4003             scanner.getNextChar('\'');
 
4007             // consume next character
 
4008             scanner.unicodeAsBackSlash = false;
 
4009             //                                                  if (((scanner.currentCharacter =
 
4010             // source[scanner.currentPosition++]) == '\\') &&
 
4011             // (source[scanner.currentPosition] == 'u')) {
 
4012             //                                                          scanner.getNextUnicodeChar();
 
4014             if (scanner.withoutUnicodePtr != 0) {
 
4015               scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
4018             while (scanner.currentCharacter != '"') {
 
4019               if (scanner.currentCharacter == '\r') {
 
4020                 if (source[scanner.currentPosition] == '\n')
 
4021                   scanner.currentPosition++;
 
4022                 break; // the string cannot go further that
 
4025               if (scanner.currentCharacter == '\n') {
 
4026                 break; // the string cannot go further that
 
4029               if (scanner.currentCharacter == '\\') {
 
4030                 scanner.scanEscapeCharacter();
 
4032               // consume next character
 
4033               scanner.unicodeAsBackSlash = false;
 
4034               //                                                                if (((scanner.currentCharacter =
 
4035               // source[scanner.currentPosition++]) == '\\')
 
4036               // && (source[scanner.currentPosition] == 'u'))
 
4038               //                                                                        scanner.getNextUnicodeChar();
 
4040               if (scanner.withoutUnicodePtr != 0) {
 
4041                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
4048             if ((test = scanner.getNextChar('/', '*')) == 0) { //line
 
4051               if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
4052                   && (source[scanner.currentPosition] == 'u')) {
 
4053                 //-------------unicode traitement
 
4055                 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
4056                 scanner.currentPosition++;
 
4057                 while (source[scanner.currentPosition] == 'u') {
 
4058                   scanner.currentPosition++;
 
4060                 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
 
4061                     || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
 
4062                     || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
 
4063                     || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
 
4067                   scanner.currentCharacter = 'A';
 
4068                 } //something different from \n and \r
 
4070                   scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
4073               while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
 
4075                 scanner.startPosition = scanner.currentPosition;
 
4076                 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
4077                     && (source[scanner.currentPosition] == 'u')) {
 
4078                   //-------------unicode traitement
 
4080                   int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
4081                   scanner.currentPosition++;
 
4082                   while (source[scanner.currentPosition] == 'u') {
 
4083                     scanner.currentPosition++;
 
4085                   if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
 
4086                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
 
4087                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
 
4088                       || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
 
4092                     scanner.currentCharacter = 'A';
 
4093                   } //something different from \n
 
4096                     scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
4100               if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
 
4101                 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
 
4102                   // only record line positions we
 
4103                   // have not recorded yet
 
4104                   scanner.pushLineSeparator();
 
4105                   if (this.scanner.taskTags != null) {
 
4106                     this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner
 
4107                         .getCurrentTokenEndPosition());
 
4113             if (test > 0) { //traditional and annotation
 
4115               boolean star = false;
 
4116               // consume next character
 
4117               scanner.unicodeAsBackSlash = false;
 
4118               //                                                                        if (((scanner.currentCharacter =
 
4119               // source[scanner.currentPosition++]) ==
 
4121               // (source[scanner.currentPosition] ==
 
4123               //                                                                                scanner.getNextUnicodeChar();
 
4125               if (scanner.withoutUnicodePtr != 0) {
 
4126                 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
 
4129               if (scanner.currentCharacter == '*') {
 
4133               if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
4134                   && (source[scanner.currentPosition] == 'u')) {
 
4135                 //-------------unicode traitement
 
4137                 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
4138                 scanner.currentPosition++;
 
4139                 while (source[scanner.currentPosition] == 'u') {
 
4140                   scanner.currentPosition++;
 
4142                 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
 
4143                     || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
 
4144                     || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
 
4145                     || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
 
4149                   scanner.currentCharacter = 'A';
 
4150                 } //something different from * and /
 
4152                   scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
4155               //loop until end of comment */
 
4156               while ((scanner.currentCharacter != '/') || (!star)) {
 
4157                 star = scanner.currentCharacter == '*';
 
4159                 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
 
4160                     && (source[scanner.currentPosition] == 'u')) {
 
4161                   //-------------unicode traitement
 
4163                   int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
4164                   scanner.currentPosition++;
 
4165                   while (source[scanner.currentPosition] == 'u') {
 
4166                     scanner.currentPosition++;
 
4168                   if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
 
4169                       || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
 
4170                       || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
 
4171                       || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
 
4175                     scanner.currentCharacter = 'A';
 
4176                   } //something different from * and
 
4179                     scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
4183               if (this.scanner.taskTags != null) {
 
4184                 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
 
4191             if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
 
4192               scanner.scanIdentifierOrKeyword(false);
 
4195             if (Character.isDigit(scanner.currentCharacter)) {
 
4196               scanner.scanNumber(false);
 
4200           //-----------------end switch while
 
4201           // try--------------------
 
4202         } catch (IndexOutOfBoundsException e) {
 
4203           break; // read until EOF
 
4204         } catch (InvalidInputException e) {
 
4205           return false; // no clue
 
4208       if (scanner.recordLineSeparator) {
 
4209         //                              compilationUnit.compilationResult.lineSeparatorPositions =
 
4210         // scanner.getLineEnds();
 
4212       // check placement anomalies against other kinds of brackets
 
4213       for (int kind = 0; kind < BracketKinds; kind++) {
 
4214         for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
 
4215           int start = leftPositions[kind][leftIndex]; // deepest
 
4217           // find matching closing bracket
 
4218           int depth = leftDepths[kind][leftIndex];
 
4220           for (int i = 0; i < rightCount[kind]; i++) {
 
4221             int pos = rightPositions[kind][i];
 
4222             // want matching bracket further in source with same
 
4224             if ((pos > start) && (depth == rightDepths[kind][i])) {
 
4229           if (end < 0) { // did not find a good closing match
 
4230             problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
 
4233           // check if even number of opening/closing other brackets
 
4234           // in between this pair of brackets
 
4236           for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
 
4237             for (int i = 0; i < leftCount[otherKind]; i++) {
 
4238               int pos = leftPositions[otherKind][i];
 
4239               if ((pos > start) && (pos < end))
 
4242             for (int i = 0; i < rightCount[otherKind]; i++) {
 
4243               int pos = rightPositions[otherKind][i];
 
4244               if ((pos > start) && (pos < end))
 
4248               problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket
 
4254         // too many opening brackets ?
 
4255         for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
 
4256           anomaliesDetected = true;
 
4257           problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext,
 
4258               compilationUnit.compilationResult);
 
4260         // too many closing brackets ?
 
4261         for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
 
4262           anomaliesDetected = true;
 
4263           problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
 
4265         if (anomaliesDetected)
 
4268       return anomaliesDetected;
 
4269     } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
 
4270       return anomaliesDetected;
 
4271     } catch (NullPointerException e) { // jdk1.2.2 jit bug
 
4272       return anomaliesDetected;
 
4276   protected void pushOnAstLengthStack(int pos) {
 
4278       astLengthStack[++astLengthPtr] = pos;
 
4279     } catch (IndexOutOfBoundsException e) {
 
4280       int oldStackLength = astLengthStack.length;
 
4281       int[] oldPos = astLengthStack;
 
4282       astLengthStack = new int[oldStackLength + StackIncrement];
 
4283       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
 
4284       astLengthStack[astLengthPtr] = pos;
 
4288   protected void pushOnAstStack(ASTNode node) {
 
4290      * add a new obj on top of the ast stack
 
4293       astStack[++astPtr] = node;
 
4294     } catch (IndexOutOfBoundsException e) {
 
4295       int oldStackLength = astStack.length;
 
4296       ASTNode[] oldStack = astStack;
 
4297       astStack = new ASTNode[oldStackLength + AstStackIncrement];
 
4298       System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
 
4299       astPtr = oldStackLength;
 
4300       astStack[astPtr] = node;
 
4303       astLengthStack[++astLengthPtr] = 1;
 
4304     } catch (IndexOutOfBoundsException e) {
 
4305       int oldStackLength = astLengthStack.length;
 
4306       int[] oldPos = astLengthStack;
 
4307       astLengthStack = new int[oldStackLength + AstStackIncrement];
 
4308       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
 
4309       astLengthStack[astLengthPtr] = 1;
 
4313   protected void resetModifiers() {
 
4314     this.modifiers = AccDefault;
 
4315     this.modifiersSourceStart = -1; // <-- see comment into
 
4316     // modifiersFlag(int)
 
4317     this.scanner.commentPtr = -1;
 
4320   protected void consumePackageDeclarationName(IFile file) {
 
4321     // create a package name similar to java package names
 
4322     String projectPath = ProjectPrefUtil.getDocumentRoot(file.getProject()).toString();
 
4323     String filePath = file.getRawLocation().toString();
 
4324     String ext = file.getRawLocation().getFileExtension();
 
4325     int fileExtensionLength = ext == null ? 0 : ext.length() + 1;
 
4326     ImportReference impt;
 
4329     if (filePath.startsWith(projectPath)) {
 
4330       tokens = CharOperation
 
4331           .splitOn('/', filePath.toCharArray(), projectPath.length() + 1, filePath.length() - fileExtensionLength);
 
4333       String name = file.getName();
 
4334       tokens = new char[1][];
 
4335       tokens[0] = name.substring(0, name.length() - fileExtensionLength).toCharArray();
 
4338     this.compilationUnit.currentPackage = impt = new ImportReference(tokens, new char[0], 0, 0, true);
 
4340     impt.declarationSourceStart = 0;
 
4341     impt.declarationSourceEnd = 0;
 
4342     impt.declarationEnd = 0;
 
4343     //endPosition is just before the ;