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