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