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