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