1 /***********************************************************************************************************************************
2 * Copyright (c) 2002 www.phpeclipse.de All rights reserved. This program and the accompanying material are made available under the
3 * terms of the Common Public License v1.0 which accompanies this distribution, and is available at
4 * http://www.eclipse.org/legal/cpl-v10.html
6 * Contributors: www.phpeclipse.de
7 **********************************************************************************************************************************/
8 package net.sourceforge.phpdt.internal.compiler.parser;
10 import java.util.ArrayList;
11 import java.util.HashMap;
12 import java.util.HashSet;
14 import net.sourceforge.phpdt.core.compiler.CharOperation;
15 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
16 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
17 import net.sourceforge.phpdt.internal.compiler.ast.AND_AND_Expression;
18 import net.sourceforge.phpdt.internal.compiler.ast.ASTNode;
19 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
20 import net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression;
21 import net.sourceforge.phpdt.internal.compiler.ast.Block;
22 import net.sourceforge.phpdt.internal.compiler.ast.BreakStatement;
23 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
24 import net.sourceforge.phpdt.internal.compiler.ast.ConditionalExpression;
25 import net.sourceforge.phpdt.internal.compiler.ast.ContinueStatement;
26 import net.sourceforge.phpdt.internal.compiler.ast.EqualExpression;
27 import net.sourceforge.phpdt.internal.compiler.ast.Expression;
28 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
29 import net.sourceforge.phpdt.internal.compiler.ast.FieldReference;
30 import net.sourceforge.phpdt.internal.compiler.ast.IfStatement;
31 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
32 import net.sourceforge.phpdt.internal.compiler.ast.InstanceOfExpression;
33 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
34 import net.sourceforge.phpdt.internal.compiler.ast.OR_OR_Expression;
35 import net.sourceforge.phpdt.internal.compiler.ast.OperatorIds;
36 import net.sourceforge.phpdt.internal.compiler.ast.ReturnStatement;
37 import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
38 import net.sourceforge.phpdt.internal.compiler.ast.Statement;
39 import net.sourceforge.phpdt.internal.compiler.ast.StringLiteral;
40 import net.sourceforge.phpdt.internal.compiler.ast.StringLiteralDQ;
41 import net.sourceforge.phpdt.internal.compiler.ast.StringLiteralSQ;
42 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
43 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
44 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
45 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
46 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
47 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
48 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
49 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
50 import net.sourceforge.phpdt.internal.compiler.util.Util;
51 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
52 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
53 import net.sourceforge.phpeclipse.ui.overlaypages.ProjectPrefUtil;
55 import org.eclipse.core.resources.IFile;
56 import org.eclipse.core.resources.IProject;
57 import org.eclipse.core.resources.IResource;
58 import org.eclipse.core.runtime.IPath;
60 public class Parser implements ITerminalSymbols, CompilerModifiers,
61 ParserBasicInformation {
62 protected final static int StackIncrement = 255;
64 protected int stateStackTop;
66 // protected int[] stack = new int[StackIncrement];
68 public int firstToken; // handle for multiple parsing goals
70 public int lastAct; // handle for multiple parsing goals
72 // protected RecoveredElement currentElement;
74 public static boolean VERBOSE_RECOVERY = false;
76 protected boolean diet = false; // tells the scanner to jump over some
79 * the PHP token scanner
81 public Scanner scanner;
85 protected int modifiers;
87 protected int modifiersSourceStart;
89 protected Parser(ProblemReporter problemReporter) {
90 this.problemReporter = problemReporter;
91 this.options = problemReporter.options;
92 this.token = TokenNameEOF;
93 this.initializeScanner();
96 public void setFileToParse(IFile fileToParse) {
97 this.token = TokenNameEOF;
98 this.initializeScanner();
102 * ClassDeclaration Constructor.
106 * Description of Parameter
109 public Parser(IFile fileToParse) {
110 // if (keywordMap == null) {
111 // keywordMap = new HashMap();
112 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
113 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
116 // this.currentPHPString = 0;
117 // PHPParserSuperclass.fileToParse = fileToParse;
118 // this.phpList = null;
119 this.includesList = null;
121 this.token = TokenNameEOF;
123 // this.rowCount = 1;
124 // this.columnCount = 0;
125 // this.phpEnd = false;
127 this.initializeScanner();
130 public void initializeScanner() {
131 this.scanner = new Scanner(
133 false /* whitespace */,
134 this.options.getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /* nls */,
135 false, false, this.options.taskTags/* taskTags */,
136 this.options.taskPriorites/* taskPriorities */, true/* isTaskCaseSensitive */);
140 * Create marker for the parse error
142 // private void setMarker(String message, int charStart, int charEnd, int
144 // setMarker(fileToParse, message, charStart, charEnd, errorLevel);
147 * This method will throw the SyntaxError. It will add the good lines and
148 * columns to the Error
152 * @throws SyntaxError
155 private void throwSyntaxError(String error) {
156 int problemStartPosition = scanner.getCurrentTokenStartPosition();
157 int problemEndPosition = scanner.getCurrentTokenEndPosition() + 1;
158 if (scanner.source.length <= problemEndPosition
159 && problemEndPosition > 0) {
160 problemEndPosition = scanner.source.length - 1;
161 if (problemStartPosition > 0
162 && problemStartPosition >= problemEndPosition
163 && problemEndPosition > 0) {
164 problemStartPosition = problemEndPosition - 1;
167 throwSyntaxError(error, problemStartPosition, problemEndPosition);
171 * This method will throw the SyntaxError. It will add the good lines and
172 * columns to the Error
176 * @throws SyntaxError
179 // private void throwSyntaxError(String error, int startRow) {
180 // throw new SyntaxError(startRow, 0, " ", error);
182 private void throwSyntaxError(String error, int problemStartPosition,
183 int problemEndPosition) {
184 if (referenceContext != null) {
185 problemReporter.phpParsingError(new String[] { error },
186 problemStartPosition, problemEndPosition, referenceContext,
187 compilationUnit.compilationResult);
189 throw new SyntaxError(1, 0, " ", error);
192 private void reportSyntaxError(String error) {
193 int problemStartPosition = scanner.getCurrentTokenStartPosition();
194 int problemEndPosition = scanner.getCurrentTokenEndPosition();
195 reportSyntaxError(error, problemStartPosition, problemEndPosition + 1);
198 private void reportSyntaxError(String error, int problemStartPosition,
199 int problemEndPosition) {
200 if (referenceContext != null) {
201 problemReporter.phpParsingError(new String[] { error },
202 problemStartPosition, problemEndPosition, referenceContext,
203 compilationUnit.compilationResult);
207 // private void reportSyntaxWarning(String error, int problemStartPosition,
208 // int problemEndPosition) {
209 // if (referenceContext != null) {
210 // problemReporter.phpParsingWarning(new String[] { error },
211 // problemStartPosition, problemEndPosition, referenceContext,
212 // compilationUnit.compilationResult);
217 * gets the next token from input
219 private void getNextToken() {
221 token = scanner.getNextToken();
223 int currentEndPosition = scanner.getCurrentTokenEndPosition();
224 int currentStartPosition = scanner
225 .getCurrentTokenStartPosition();
226 System.out.print(currentStartPosition + ","
227 + currentEndPosition + ": ");
228 System.out.println(scanner.toStringAction(token));
230 } catch (InvalidInputException e) {
231 token = TokenNameERROR;
232 String detailedMessage = e.getMessage();
234 if (detailedMessage == Scanner.UNTERMINATED_STRING) {
235 throwSyntaxError("Unterminated string.");
236 } else if (detailedMessage == Scanner.UNTERMINATED_COMMENT) {
237 throwSyntaxError("Unterminated commment.");
243 public void init(String s) {
245 this.token = TokenNameEOF;
246 this.includesList = new ArrayList();
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);
258 protected void initialize(boolean phpMode) {
259 initialize(phpMode, null);
262 protected void initialize(boolean phpMode,
263 IdentifierIndexManager indexManager) {
264 compilationUnit = null;
265 referenceContext = null;
266 this.includesList = new ArrayList();
267 // this.indexManager = indexManager;
269 this.token = TokenNameEOF;
271 // this.rowCount = 1;
272 // this.columnCount = 0;
273 // this.phpEnd = false;
274 // this.phpMode = phpMode;
275 scanner.setPHPMode(phpMode);
280 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
283 public void parse(String s) {
288 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
291 public void parse(String s, HashMap variables) {
292 fMethodVariables = variables;
293 fStackUnassigned = new ArrayList();
299 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
302 protected void parse() {
303 if (scanner.compilationUnit != null) {
304 IResource resource = scanner.compilationUnit.getResource();
305 if (resource != null && resource instanceof IFile) {
306 // set the package name
307 consumePackageDeclarationName((IFile) resource);
313 if (token != TokenNameEOF && token != TokenNameERROR) {
316 if (token != TokenNameEOF) {
317 if (token == TokenNameERROR) {
318 throwSyntaxError("Scanner error (Found unknown token: "
319 + scanner.toStringAction(token) + ")");
321 if (token == TokenNameRPAREN) {
322 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
324 if (token == TokenNameRBRACE) {
325 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
327 if (token == TokenNameRBRACKET) {
328 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
330 if (token == TokenNameLPAREN) {
331 throwSyntaxError("Read character '('; end-of-file not reached.");
333 if (token == TokenNameLBRACE) {
334 throwSyntaxError("Read character '{'; end-of-file not reached.");
336 if (token == TokenNameLBRACKET) {
337 throwSyntaxError("Read character '['; end-of-file not reached.");
339 throwSyntaxError("End-of-file not reached.");
342 } catch (SyntaxError syntaxError) {
343 // syntaxError.printStackTrace();
352 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
355 public void parseFunction(String s, HashMap variables) {
357 scanner.phpMode = true;
358 parseFunction(variables);
362 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
365 protected void parseFunction(HashMap variables) {
367 boolean hasModifiers = member_modifiers();
368 if (token == TokenNamefunction) {
370 checkAndSetModifiers(AccPublic);
372 this.fMethodVariables = variables;
374 MethodDeclaration methodDecl = new MethodDeclaration(null);
375 methodDecl.declarationSourceStart = scanner
376 .getCurrentTokenStartPosition();
377 methodDecl.modifiers = this.modifiers;
378 methodDecl.type = MethodDeclaration.METHOD_DEFINITION;
381 functionDefinition(methodDecl);
382 } catch (SyntaxError sytaxErr1) {
385 int sourceEnd = methodDecl.sourceEnd;
387 || methodDecl.declarationSourceStart > sourceEnd) {
388 sourceEnd = methodDecl.declarationSourceStart + 1;
390 methodDecl.sourceEnd = sourceEnd;
391 methodDecl.declarationSourceEnd = sourceEnd;
396 protected CompilationUnitDeclaration endParse(int act) {
400 // if (currentElement != null) {
401 // currentElement.topElement().updateParseTree();
402 // if (VERBOSE_RECOVERY) {
403 // System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
404 // System.out.println("--------------------------"); //$NON-NLS-1$
405 // System.out.println(compilationUnit);
406 // System.out.println("----------------------------------");
410 if (diet & VERBOSE_RECOVERY) {
411 System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
412 System.out.println("--------------------------"); //$NON-NLS-1$
413 System.out.println(compilationUnit);
414 System.out.println("----------------------------------"); //$NON-NLS-1$
417 if (scanner.recordLineSeparator) {
418 compilationUnit.compilationResult.lineSeparatorPositions = scanner
421 if (scanner.taskTags != null) {
422 for (int i = 0; i < scanner.foundTaskCount; i++) {
423 problemReporter().task(
424 new String(scanner.foundTaskTags[i]),
425 new String(scanner.foundTaskMessages[i]),
426 scanner.foundTaskPriorities[i] == null ? null
427 : new String(scanner.foundTaskPriorities[i]),
428 scanner.foundTaskPositions[i][0],
429 scanner.foundTaskPositions[i][1]);
432 compilationUnit.imports = new ImportReference[includesList.size()];
433 for (int i = 0; i < includesList.size(); i++) {
434 compilationUnit.imports[i] = (ImportReference) includesList.get(i);
436 return compilationUnit;
439 private Block statementList() {
440 boolean branchStatement = false;
442 int blockStart = scanner.getCurrentTokenStartPosition();
443 ArrayList blockStatements = new ArrayList();
446 statement = statement();
447 blockStatements.add(statement);
448 if (token == TokenNameEOF) {
451 if (branchStatement && statement != null) {
452 // reportSyntaxError("Unreachable code",
453 // statement.sourceStart,
454 // statement.sourceEnd);
455 if (!(statement instanceof BreakStatement)) {
457 * don't give an error for break statement following
458 * return statement Technically it's unreachable code,
459 * but in switch-case it's recommended to avoid
460 * accidental fall-through later when editing the code
462 problemReporter.unreachableCode(new String(scanner
463 .getCurrentIdentifierSource()),
464 statement.sourceStart, statement.sourceEnd,
466 compilationUnit.compilationResult);
469 if ((token == TokenNameRBRACE) || (token == TokenNamecase)
470 || (token == TokenNamedefault)
471 || (token == TokenNameelse)
472 || (token == TokenNameelseif)
473 || (token == TokenNameendif)
474 || (token == TokenNameendfor)
475 || (token == TokenNameendforeach)
476 || (token == TokenNameendwhile)
477 || (token == TokenNameendswitch)
478 || (token == TokenNameenddeclare)
479 || (token == TokenNameEOF) || (token == TokenNameERROR)) {
480 return createBlock(blockStart, blockStatements);
482 branchStatement = checkUnreachableStatements(statement);
483 } catch (SyntaxError sytaxErr1) {
484 // if an error occured,
485 // try to find keywords
486 // to parse the rest of the string
487 boolean tokenize = scanner.tokenizeStrings;
489 scanner.tokenizeStrings = true;
492 while (token != TokenNameEOF) {
493 if ((token == TokenNameRBRACE)
494 || (token == TokenNamecase)
495 || (token == TokenNamedefault)
496 || (token == TokenNameelse)
497 || (token == TokenNameelseif)
498 || (token == TokenNameendif)
499 || (token == TokenNameendfor)
500 || (token == TokenNameendforeach)
501 || (token == TokenNameendwhile)
502 || (token == TokenNameendswitch)
503 || (token == TokenNameenddeclare)
504 || (token == TokenNameEOF)
505 || (token == TokenNameERROR)) {
506 return createBlock(blockStart, blockStatements);
508 if (token == TokenNameif || token == TokenNameswitch
509 || token == TokenNamefor
510 || token == TokenNamewhile
511 || token == TokenNamedo
512 || token == TokenNameforeach
513 || token == TokenNamecontinue
514 || token == TokenNamebreak
515 || token == TokenNamereturn
516 || token == TokenNameexit
517 || token == TokenNameecho
518 || token == TokenNameECHO_INVISIBLE
519 || token == TokenNameglobal
520 || token == TokenNamestatic
521 || token == TokenNameunset
522 || token == TokenNamefunction
523 || token == TokenNamedeclare
524 || token == TokenNametry
525 || token == TokenNamecatch
526 || token == TokenNamethrow
527 || token == TokenNamefinal
528 || token == TokenNameabstract
529 || token == TokenNameclass
530 || token == TokenNameinterface) {
533 // System.out.println(scanner.toStringAction(token));
535 // System.out.println(scanner.toStringAction(token));
537 if (token == TokenNameEOF) {
541 scanner.tokenizeStrings = tokenize;
551 private boolean checkUnreachableStatements(Statement statement) {
552 if (statement instanceof ReturnStatement
553 || statement instanceof ContinueStatement
554 || statement instanceof BreakStatement) {
556 } else if (statement instanceof IfStatement
557 && ((IfStatement) statement).checkUnreachable) {
565 * @param blockStatements
568 private Block createBlock(int blockStart, ArrayList blockStatements) {
569 int blockEnd = scanner.getCurrentTokenEndPosition();
570 Block b = Block.EmptyWith(blockStart, blockEnd);
571 b.statements = new Statement[blockStatements.size()];
572 blockStatements.toArray(b.statements);
576 private void functionBody(MethodDeclaration methodDecl) {
577 // '{' [statement-list] '}'
578 if (token == TokenNameLBRACE) {
581 methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
582 throwSyntaxError("'{' expected in compound-statement.");
584 if (token != TokenNameRBRACE) {
587 if (token == TokenNameRBRACE) {
588 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
591 methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
592 throwSyntaxError("'}' expected in compound-statement.");
596 private Statement statement() {
597 Statement statement = null;
598 Expression expression;
599 int sourceStart = scanner.getCurrentTokenStartPosition();
601 if (token == TokenNameif) {
602 // T_IF '(' expr ')' statement elseif_list else_single
603 // T_IF '(' expr ')' ':' inner_statement_list new_elseif_list
604 // new_else_single T_ENDIF ';'
606 if (token == TokenNameLPAREN) {
609 throwSyntaxError("'(' expected after 'if' keyword.");
612 if (token == TokenNameRPAREN) {
615 throwSyntaxError("')' expected after 'if' condition.");
617 // create basic IfStatement
618 IfStatement ifStatement = new IfStatement(expression, null, null,
620 if (token == TokenNameCOLON) {
622 ifStatementColon(ifStatement);
624 ifStatement(ifStatement);
627 } else if (token == TokenNameswitch) {
629 if (token == TokenNameLPAREN) {
632 throwSyntaxError("'(' expected after 'switch' keyword.");
635 if (token == TokenNameRPAREN) {
638 throwSyntaxError("')' expected after 'switch' condition.");
642 } else if (token == TokenNamefor) {
644 if (token == TokenNameLPAREN) {
647 throwSyntaxError("'(' expected after 'for' keyword.");
649 if (token == TokenNameSEMICOLON) {
653 if (token == TokenNameSEMICOLON) {
656 throwSyntaxError("';' expected after 'for'.");
659 if (token == TokenNameSEMICOLON) {
663 if (token == TokenNameSEMICOLON) {
666 throwSyntaxError("';' expected after 'for'.");
669 if (token == TokenNameRPAREN) {
673 if (token == TokenNameRPAREN) {
676 throwSyntaxError("')' expected after 'for'.");
681 } else if (token == TokenNamewhile) {
683 if (token == TokenNameLPAREN) {
686 throwSyntaxError("'(' expected after 'while' keyword.");
689 if (token == TokenNameRPAREN) {
692 throwSyntaxError("')' expected after 'while' condition.");
696 } else if (token == TokenNamedo) {
698 if (token == TokenNameLBRACE) {
700 if (token != TokenNameRBRACE) {
703 if (token == TokenNameRBRACE) {
706 throwSyntaxError("'}' expected after 'do' keyword.");
711 if (token == TokenNamewhile) {
713 if (token == TokenNameLPAREN) {
716 throwSyntaxError("'(' expected after 'while' keyword.");
719 if (token == TokenNameRPAREN) {
722 throwSyntaxError("')' expected after 'while' condition.");
725 throwSyntaxError("'while' expected after 'do' keyword.");
727 if (token == TokenNameSEMICOLON) {
730 if (token != TokenNameINLINE_HTML) {
731 throwSyntaxError("';' expected after do-while statement.");
736 } else if (token == TokenNameforeach) {
738 if (token == TokenNameLPAREN) {
741 throwSyntaxError("'(' expected after 'foreach' keyword.");
744 if (token == TokenNameas) {
747 throwSyntaxError("'as' expected after 'foreach' exxpression.");
751 foreach_optional_arg();
752 if (token == TokenNameEQUAL_GREATER) {
754 variable(false, false);
756 if (token == TokenNameRPAREN) {
759 throwSyntaxError("')' expected after 'foreach' expression.");
763 } else if (token == TokenNamebreak) {
766 if (token != TokenNameSEMICOLON) {
769 if (token == TokenNameSEMICOLON) {
770 sourceEnd = scanner.getCurrentTokenEndPosition();
773 if (token != TokenNameINLINE_HTML) {
774 throwSyntaxError("';' expected after 'break'.");
776 sourceEnd = scanner.getCurrentTokenEndPosition();
779 return new BreakStatement(null, sourceStart, sourceEnd);
780 } else if (token == TokenNamecontinue) {
783 if (token != TokenNameSEMICOLON) {
786 if (token == TokenNameSEMICOLON) {
787 sourceEnd = scanner.getCurrentTokenEndPosition();
790 if (token != TokenNameINLINE_HTML) {
791 throwSyntaxError("';' expected after 'continue'.");
793 sourceEnd = scanner.getCurrentTokenEndPosition();
796 return new ContinueStatement(null, sourceStart, sourceEnd);
797 } else if (token == TokenNamereturn) {
800 if (token != TokenNameSEMICOLON) {
803 if (token == TokenNameSEMICOLON) {
804 sourceEnd = scanner.getCurrentTokenEndPosition();
807 if (token != TokenNameINLINE_HTML) {
808 throwSyntaxError("';' expected after 'return'.");
810 sourceEnd = scanner.getCurrentTokenEndPosition();
813 return new ReturnStatement(expression, sourceStart, sourceEnd);
814 } else if (token == TokenNameecho) {
817 if (token == TokenNameSEMICOLON) {
820 if (token != TokenNameINLINE_HTML) {
821 throwSyntaxError("';' expected after 'echo' statement.");
826 } else if (token == TokenNameECHO_INVISIBLE) {
827 // 0-length token directly after PHP short tag <?=
830 if (token == TokenNameSEMICOLON) {
832 // if (token != TokenNameINLINE_HTML) {
833 // // TODO should this become a configurable warning?
834 // reportSyntaxError("Probably '?>' expected after PHP short tag
835 // expression (only the first expression will be echoed).");
838 if (token != TokenNameINLINE_HTML) {
839 throwSyntaxError("';' expected after PHP short tag '<?=' expression.");
844 } else if (token == TokenNameINLINE_HTML) {
847 } else if (token == TokenNameglobal) {
850 if (token == TokenNameSEMICOLON) {
853 if (token != TokenNameINLINE_HTML) {
854 throwSyntaxError("';' expected after 'global' statement.");
859 } else if(token == TokenNameconst){
861 if(token == TokenNameIdentifier){
863 if(token == TokenNameEQUAL){
866 //throwSyntaxError("'Ed i know your here");
868 } else if (token == TokenNamestatic) {
871 if (token == TokenNameSEMICOLON) {
874 if (token != TokenNameINLINE_HTML) {
875 throwSyntaxError("';' expected after 'static' statement.");
880 } else if (token == TokenNameunset) {
882 if (token == TokenNameLPAREN) {
885 throwSyntaxError("'(' expected after 'unset' statement.");
888 if (token == TokenNameRPAREN) {
891 throwSyntaxError("')' expected after 'unset' statement.");
893 if (token == TokenNameSEMICOLON) {
896 if (token != TokenNameINLINE_HTML) {
897 throwSyntaxError("';' expected after 'unset' statement.");
902 } else if (token == TokenNamefunction) {
903 MethodDeclaration methodDecl = new MethodDeclaration(
904 this.compilationUnit.compilationResult);
905 methodDecl.declarationSourceStart = scanner
906 .getCurrentTokenStartPosition();
907 methodDecl.modifiers = AccDefault;
908 methodDecl.type = MethodDeclaration.FUNCTION_DEFINITION;
911 functionDefinition(methodDecl);
913 sourceEnd = methodDecl.sourceEnd;
915 || methodDecl.declarationSourceStart > sourceEnd) {
916 sourceEnd = methodDecl.declarationSourceStart + 1;
918 methodDecl.declarationSourceEnd = sourceEnd;
919 methodDecl.sourceEnd = sourceEnd;
922 } else if (token == TokenNamedeclare) {
923 // T_DECLARE '(' declare_list ')' declare_statement
925 if (token != TokenNameLPAREN) {
926 throwSyntaxError("'(' expected in 'declare' statement.");
930 if (token != TokenNameRPAREN) {
931 throwSyntaxError("')' expected in 'declare' statement.");
936 } else if (token == TokenNametry) {
938 if (token != TokenNameLBRACE) {
939 throwSyntaxError("'{' expected in 'try' statement.");
943 if (token != TokenNameRBRACE) {
944 throwSyntaxError("'}' expected in 'try' statement.");
948 } else if (token == TokenNamecatch) {
950 if (token != TokenNameLPAREN) {
951 throwSyntaxError("'(' expected in 'catch' statement.");
954 fully_qualified_class_name();
955 if (token != TokenNameVariable) {
956 throwSyntaxError("Variable expected in 'catch' statement.");
960 if (token != TokenNameRPAREN) {
961 throwSyntaxError("')' expected in 'catch' statement.");
964 if (token != TokenNameLBRACE) {
965 throwSyntaxError("'{' expected in 'catch' statement.");
968 if (token != TokenNameRBRACE) {
970 if (token != TokenNameRBRACE) {
971 throwSyntaxError("'}' expected in 'catch' statement.");
975 additional_catches();
977 } else if (token == TokenNamethrow) {
980 if (token == TokenNameSEMICOLON) {
983 throwSyntaxError("';' expected after 'throw' exxpression.");
986 } else if (token == TokenNamefinal || token == TokenNameabstract
987 || token == TokenNameclass || token == TokenNameinterface) {
989 TypeDeclaration typeDecl = new TypeDeclaration(
990 this.compilationUnit.compilationResult);
991 typeDecl.declarationSourceStart = scanner
992 .getCurrentTokenStartPosition();
993 typeDecl.declarationSourceEnd = scanner
994 .getCurrentTokenEndPosition();
995 typeDecl.name = new char[] { ' ' };
996 // default super class
997 typeDecl.superclass = new SingleTypeReference(
998 TypeConstants.OBJECT, 0);
999 compilationUnit.types.add(typeDecl);
1000 pushOnAstStack(typeDecl);
1001 unticked_class_declaration_statement(typeDecl);
1009 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
1010 } else if (token == TokenNameLBRACE) {
1012 if (token != TokenNameRBRACE) {
1013 statement = statementList();
1015 if (token == TokenNameRBRACE) {
1019 throwSyntaxError("'}' expected.");
1022 if (token != TokenNameSEMICOLON) {
1025 if (token == TokenNameSEMICOLON) {
1029 if (token == TokenNameRBRACE) {
1030 reportSyntaxError("';' expected after expression (Found token: "
1031 + scanner.toStringAction(token) + ")");
1033 if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
1034 throwSyntaxError("';' expected after expression (Found token: "
1035 + scanner.toStringAction(token) + ")");
1045 private void declare_statement() {
1047 // | ':' inner_statement_list T_ENDDECLARE ';'
1049 if (token == TokenNameCOLON) {
1051 // TODO: implement inner_statement_list();
1053 if (token != TokenNameenddeclare) {
1054 throwSyntaxError("'enddeclare' expected in 'declare' statement.");
1057 if (token != TokenNameSEMICOLON) {
1058 throwSyntaxError("';' expected after 'enddeclare' keyword.");
1066 private void declare_list() {
1067 // T_STRING '=' static_scalar
1068 // | declare_list ',' T_STRING '=' static_scalar
1070 if (token != TokenNameIdentifier) {
1071 throwSyntaxError("Identifier expected in 'declare' list.");
1074 if (token != TokenNameEQUAL) {
1075 throwSyntaxError("'=' expected in 'declare' list.");
1079 if (token != TokenNameCOMMA) {
1086 private void additional_catches() {
1087 while (token == TokenNamecatch) {
1089 if (token != TokenNameLPAREN) {
1090 throwSyntaxError("'(' expected in 'catch' statement.");
1093 fully_qualified_class_name();
1094 if (token != TokenNameVariable) {
1095 throwSyntaxError("Variable expected in 'catch' statement.");
1099 if (token != TokenNameRPAREN) {
1100 throwSyntaxError("')' expected in 'catch' statement.");
1103 if (token != TokenNameLBRACE) {
1104 throwSyntaxError("'{' expected in 'catch' statement.");
1107 if (token != TokenNameRBRACE) {
1110 if (token != TokenNameRBRACE) {
1111 throwSyntaxError("'}' expected in 'catch' statement.");
1117 private void foreach_variable() {
1120 if (token == TokenNameAND) {
1126 private void foreach_optional_arg() {
1128 // | T_DOUBLE_ARROW foreach_variable
1129 if (token == TokenNameEQUAL_GREATER) {
1135 private void global_var_list() {
1137 // global_var_list ',' global_var
1139 HashSet set = peekVariableSet();
1142 if (token != TokenNameCOMMA) {
1149 private void global_var(HashSet set) {
1153 // | '$' '{' expr '}'
1154 if (token == TokenNameVariable) {
1155 if (fMethodVariables != null) {
1156 VariableInfo info = new VariableInfo(scanner
1157 .getCurrentTokenStartPosition(),
1158 VariableInfo.LEVEL_GLOBAL_VAR);
1159 fMethodVariables.put(new String(scanner
1160 .getCurrentIdentifierSource()), info);
1162 addVariableSet(set);
1164 } else if (token == TokenNameDOLLAR) {
1166 if (token == TokenNameLBRACE) {
1169 if (token != TokenNameRBRACE) {
1170 throwSyntaxError("'}' expected in global variable.");
1179 private void static_var_list() {
1181 // static_var_list ',' T_VARIABLE
1182 // | static_var_list ',' T_VARIABLE '=' static_scalar
1184 // | T_VARIABLE '=' static_scalar,
1185 HashSet set = peekVariableSet();
1187 if (token == TokenNameVariable) {
1188 if (fMethodVariables != null) {
1189 VariableInfo info = new VariableInfo(scanner
1190 .getCurrentTokenStartPosition(),
1191 VariableInfo.LEVEL_STATIC_VAR);
1192 fMethodVariables.put(new String(scanner
1193 .getCurrentIdentifierSource()), info);
1195 addVariableSet(set);
1197 if (token == TokenNameEQUAL) {
1201 if (token != TokenNameCOMMA) {
1211 private void unset_variables() {
1214 // | unset_variables ',' unset_variable
1218 variable(false, false);
1219 if (token != TokenNameCOMMA) {
1226 private final void initializeModifiers() {
1228 this.modifiersSourceStart = -1;
1231 private final void checkAndSetModifiers(int flag) {
1232 this.modifiers |= flag;
1233 if (this.modifiersSourceStart < 0)
1234 this.modifiersSourceStart = this.scanner.startPosition;
1237 private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1238 initializeModifiers();
1239 if (token == TokenNameinterface) {
1240 // interface_entry T_STRING
1241 // interface_extends_list
1242 // '{' class_statement_list '}'
1243 checkAndSetModifiers(AccInterface);
1245 typeDecl.modifiers = this.modifiers;
1246 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1247 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1248 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1249 typeDecl.name = scanner.getCurrentIdentifierSource();
1250 if (token > TokenNameKEYWORD) {
1251 problemReporter.phpKeywordWarning(new String[] { scanner
1252 .toStringAction(token) }, scanner
1253 .getCurrentTokenStartPosition(), scanner
1254 .getCurrentTokenEndPosition(), referenceContext,
1255 compilationUnit.compilationResult);
1256 // throwSyntaxError("Don't use a keyword for interface
1258 // + scanner.toStringAction(token) + "].",
1259 // typeDecl.sourceStart, typeDecl.sourceEnd);
1262 interface_extends_list(typeDecl);
1264 typeDecl.name = new char[] { ' ' };
1266 "Interface name expected after keyword 'interface'.",
1267 typeDecl.sourceStart, typeDecl.sourceEnd);
1271 // class_entry_type T_STRING extends_from
1273 // '{' class_statement_list'}'
1275 typeDecl.modifiers = this.modifiers;
1276 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1277 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1279 // identifier 'extends' identifier
1280 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1281 typeDecl.name = scanner.getCurrentIdentifierSource();
1282 if (token > TokenNameKEYWORD) {
1283 problemReporter.phpKeywordWarning(new String[] { scanner
1284 .toStringAction(token) }, scanner
1285 .getCurrentTokenStartPosition(), scanner
1286 .getCurrentTokenEndPosition(), referenceContext,
1287 compilationUnit.compilationResult);
1288 // throwSyntaxError("Don't use a keyword for class
1290 // scanner.toStringAction(token) + "].",
1291 // typeDecl.sourceStart, typeDecl.sourceEnd);
1296 // | T_EXTENDS fully_qualified_class_name
1297 if (token == TokenNameextends) {
1298 class_extends_list(typeDecl);
1300 // if (token != TokenNameIdentifier) {
1301 // throwSyntaxError("Class name expected after keyword
1303 // scanner.getCurrentTokenStartPosition(), scanner
1304 // .getCurrentTokenEndPosition());
1307 implements_list(typeDecl);
1309 typeDecl.name = new char[] { ' ' };
1310 throwSyntaxError("Class name expected after keyword 'class'.",
1311 typeDecl.sourceStart, typeDecl.sourceEnd);
1315 // '{' class_statement_list '}'
1316 if (token == TokenNameLBRACE) {
1318 if (token != TokenNameRBRACE) {
1319 ArrayList list = new ArrayList();
1320 class_statement_list(list);
1321 typeDecl.fields = new FieldDeclaration[list.size()];
1322 for (int i = 0; i < list.size(); i++) {
1323 typeDecl.fields[i] = (FieldDeclaration) list.get(i);
1326 if (token == TokenNameRBRACE) {
1327 typeDecl.declarationSourceEnd = scanner
1328 .getCurrentTokenEndPosition();
1331 throwSyntaxError("'}' expected at end of class body.");
1334 throwSyntaxError("'{' expected at start of class body.");
1338 private void class_entry_type() {
1340 // | T_ABSTRACT T_CLASS
1341 // | T_FINAL T_CLASS
1342 if (token == TokenNameclass) {
1344 } else if (token == TokenNameabstract) {
1345 checkAndSetModifiers(AccAbstract);
1347 if (token != TokenNameclass) {
1348 throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1351 } else if (token == TokenNamefinal) {
1352 checkAndSetModifiers(AccFinal);
1354 if (token != TokenNameclass) {
1355 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1359 throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1363 // private void class_extends(TypeDeclaration typeDecl) {
1365 // // | T_EXTENDS interface_list
1366 // if (token == TokenNameextends) {
1369 // if (token == TokenNameIdentifier) {
1372 // throwSyntaxError("Class name expected after keyword 'extends'.");
1377 private void interface_extends_list(TypeDeclaration typeDecl) {
1379 // | T_EXTENDS interface_list
1380 if (token == TokenNameextends) {
1382 interface_list(typeDecl);
1386 private void class_extends_list(TypeDeclaration typeDecl) {
1388 // | T_EXTENDS interface_list
1389 if (token == TokenNameextends) {
1391 class_list(typeDecl);
1395 private void implements_list(TypeDeclaration typeDecl) {
1397 // | T_IMPLEMENTS interface_list
1398 if (token == TokenNameimplements) {
1400 interface_list(typeDecl);
1404 private void class_list(TypeDeclaration typeDecl) {
1406 // fully_qualified_class_name
1408 if (token == TokenNameIdentifier) {
1409 char[] ident = scanner.getCurrentIdentifierSource();
1410 // TODO make this code working better:
1411 // SingleTypeReference ref =
1412 // ParserUtil.getTypeReference(scanner,
1413 // includesList, ident);
1414 // if (ref != null) {
1415 // typeDecl.superclass = ref;
1419 throwSyntaxError("Classname expected after keyword 'extends'.");
1421 if (token == TokenNameCOMMA) {
1422 reportSyntaxError("No multiple inheritance allowed. Expected token 'implements' or '{'.");
1431 private void interface_list(TypeDeclaration typeDecl) {
1433 // fully_qualified_class_name
1434 // | interface_list ',' fully_qualified_class_name
1436 if (token == TokenNameIdentifier) {
1439 throwSyntaxError("Interfacename expected after keyword 'implements'.");
1441 if (token != TokenNameCOMMA) {
1448 // private void classBody(TypeDeclaration typeDecl) {
1449 // //'{' [class-element-list] '}'
1450 // if (token == TokenNameLBRACE) {
1452 // if (token != TokenNameRBRACE) {
1453 // class_statement_list();
1455 // if (token == TokenNameRBRACE) {
1456 // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1459 // throwSyntaxError("'}' expected at end of class body.");
1462 // throwSyntaxError("'{' expected at start of class body.");
1465 private void class_statement_list(ArrayList list) {
1468 class_statement(list);
1469 if (token == TokenNamepublic || token == TokenNameprotected
1470 || token == TokenNameprivate
1471 || token == TokenNamestatic
1472 || token == TokenNameabstract
1473 || token == TokenNamefinal
1474 || token == TokenNamefunction || token == TokenNamevar
1475 || token == TokenNameconst) {
1478 if (token == TokenNameRBRACE) {
1481 throwSyntaxError("'}' at end of class statement.");
1482 } catch (SyntaxError sytaxErr1) {
1483 boolean tokenize = scanner.tokenizeStrings;
1485 scanner.tokenizeStrings = true;
1488 // if an error occured,
1489 // try to find keywords
1490 // to parse the rest of the string
1491 while (token != TokenNameEOF) {
1492 if (token == TokenNamepublic
1493 || token == TokenNameprotected
1494 || token == TokenNameprivate
1495 || token == TokenNamestatic
1496 || token == TokenNameabstract
1497 || token == TokenNamefinal
1498 || token == TokenNamefunction
1499 || token == TokenNamevar
1500 || token == TokenNameconst) {
1503 // System.out.println(scanner.toStringAction(token));
1506 if (token == TokenNameEOF) {
1510 scanner.tokenizeStrings = tokenize;
1516 private void class_statement(ArrayList list) {
1518 // variable_modifiers class_variable_declaration ';'
1519 // | class_constant_declaration ';'
1520 // | method_modifiers T_FUNCTION is_reference T_STRING
1521 // '(' parameter_list ')' method_body
1522 initializeModifiers();
1523 int declarationSourceStart = scanner.getCurrentTokenStartPosition();
1525 if (token == TokenNamevar) {
1526 checkAndSetModifiers(AccPublic);
1527 problemReporter.phpVarDeprecatedWarning(scanner
1528 .getCurrentTokenStartPosition(), scanner
1529 .getCurrentTokenEndPosition(), referenceContext,
1530 compilationUnit.compilationResult);
1532 class_variable_declaration(declarationSourceStart, list);
1533 } else if (token == TokenNameconst) {
1534 checkAndSetModifiers(AccFinal | AccPublic);
1535 class_constant_declaration(declarationSourceStart, list);
1536 if (token != TokenNameSEMICOLON) {
1537 throwSyntaxError("';' expected after class const declaration.");
1541 boolean hasModifiers = member_modifiers();
1542 if (token == TokenNamefunction) {
1543 if (!hasModifiers) {
1544 checkAndSetModifiers(AccPublic);
1546 MethodDeclaration methodDecl = new MethodDeclaration(
1547 this.compilationUnit.compilationResult);
1548 methodDecl.declarationSourceStart = scanner
1549 .getCurrentTokenStartPosition();
1550 methodDecl.modifiers = this.modifiers;
1551 methodDecl.type = MethodDeclaration.METHOD_DEFINITION;
1554 functionDefinition(methodDecl);
1556 int sourceEnd = methodDecl.sourceEnd;
1558 || methodDecl.declarationSourceStart > sourceEnd) {
1559 sourceEnd = methodDecl.declarationSourceStart + 1;
1561 methodDecl.declarationSourceEnd = sourceEnd;
1562 methodDecl.sourceEnd = sourceEnd;
1565 if (!hasModifiers) {
1566 throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1568 class_variable_declaration(declarationSourceStart, list);
1573 private void class_constant_declaration(int declarationSourceStart,
1575 // class_constant_declaration ',' T_STRING '=' static_scalar
1576 // | T_CONST T_STRING '=' static_scalar
1577 if (token != TokenNameconst) {
1578 throwSyntaxError("'const' keyword expected in class declaration.");
1583 if (token != TokenNameIdentifier) {
1584 throwSyntaxError("Identifier expected in class const declaration.");
1586 FieldDeclaration fieldDeclaration = new FieldDeclaration(scanner
1587 .getCurrentIdentifierSource(), scanner
1588 .getCurrentTokenStartPosition(), scanner
1589 .getCurrentTokenEndPosition());
1590 fieldDeclaration.modifiers = this.modifiers;
1591 fieldDeclaration.declarationSourceStart = declarationSourceStart;
1592 fieldDeclaration.declarationSourceEnd = scanner
1593 .getCurrentTokenEndPosition();
1594 fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1595 // fieldDeclaration.type
1596 list.add(fieldDeclaration);
1598 if (token != TokenNameEQUAL) {
1599 throwSyntaxError("'=' expected in class const declaration.");
1603 if (token != TokenNameCOMMA) {
1604 break; // while(true)-loop
1610 // private void variable_modifiers() {
1611 // // variable_modifiers:
1612 // // non_empty_member_modifiers
1614 // initializeModifiers();
1615 // if (token == TokenNamevar) {
1616 // checkAndSetModifiers(AccPublic);
1617 // reportSyntaxError(
1618 // "Keyword 'var' is deprecated. Please use 'public' 'private' or
1620 // modifier for field declarations.",
1621 // scanner.getCurrentTokenStartPosition(), scanner
1622 // .getCurrentTokenEndPosition());
1625 // if (!member_modifiers()) {
1626 // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1627 // field declarations.");
1631 // private void method_modifiers() {
1632 // //method_modifiers:
1634 // //| non_empty_member_modifiers
1635 // initializeModifiers();
1636 // if (!member_modifiers()) {
1637 // checkAndSetModifiers(AccPublic);
1640 private boolean member_modifiers() {
1647 boolean foundToken = false;
1649 if (token == TokenNamepublic) {
1650 checkAndSetModifiers(AccPublic);
1653 } else if (token == TokenNameprotected) {
1654 checkAndSetModifiers(AccProtected);
1657 } else if (token == TokenNameprivate) {
1658 checkAndSetModifiers(AccPrivate);
1661 } else if (token == TokenNamestatic) {
1662 checkAndSetModifiers(AccStatic);
1665 } else if (token == TokenNameabstract) {
1666 checkAndSetModifiers(AccAbstract);
1669 } else if (token == TokenNamefinal) {
1670 checkAndSetModifiers(AccFinal);
1680 private void class_variable_declaration(int declarationSourceStart,
1682 // class_variable_declaration:
1683 // class_variable_declaration ',' T_VARIABLE
1684 // | class_variable_declaration ',' T_VARIABLE '=' static_scalar
1686 // | T_VARIABLE '=' static_scalar
1687 char[] classVariable;
1689 if (token == TokenNameVariable) {
1690 classVariable = scanner.getCurrentIdentifierSource();
1691 // indexManager.addIdentifierInformation('v', classVariable,
1694 FieldDeclaration fieldDeclaration = new FieldDeclaration(
1695 classVariable, scanner.getCurrentTokenStartPosition(),
1696 scanner.getCurrentTokenEndPosition());
1697 fieldDeclaration.modifiers = this.modifiers;
1698 fieldDeclaration.declarationSourceStart = declarationSourceStart;
1699 fieldDeclaration.declarationSourceEnd = scanner
1700 .getCurrentTokenEndPosition();
1701 fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1702 list.add(fieldDeclaration);
1703 if (fTypeVariables != null) {
1704 VariableInfo info = new VariableInfo(scanner
1705 .getCurrentTokenStartPosition(),
1706 VariableInfo.LEVEL_CLASS_UNIT);
1707 fTypeVariables.put(new String(scanner
1708 .getCurrentIdentifierSource()), info);
1711 if (token == TokenNameEQUAL) {
1716 // if (token == TokenNamethis) {
1717 // throwSyntaxError("'$this' not allowed after keyword 'public'
1718 // 'protected' 'private' 'var'.");
1720 throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
1722 if (token != TokenNameCOMMA) {
1727 if (token != TokenNameSEMICOLON) {
1728 throwSyntaxError("';' expected after field declaration.");
1733 private void functionDefinition(MethodDeclaration methodDecl) {
1734 boolean isAbstract = false;
1736 if (compilationUnit != null) {
1737 compilationUnit.types.add(methodDecl);
1740 ASTNode node = astStack[astPtr];
1741 if (node instanceof TypeDeclaration) {
1742 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1743 if (typeDecl.methods == null) {
1744 typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
1746 AbstractMethodDeclaration[] newMethods;
1751 newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
1752 0, typeDecl.methods.length);
1753 newMethods[typeDecl.methods.length] = methodDecl;
1754 typeDecl.methods = newMethods;
1756 if ((typeDecl.modifiers & AccAbstract) == AccAbstract) {
1758 } else if ((typeDecl.modifiers & AccInterface) == AccInterface) {
1764 pushFunctionVariableSet();
1765 functionDeclarator(methodDecl);
1766 if (token == TokenNameSEMICOLON) {
1768 methodDecl.sourceEnd = scanner
1769 .getCurrentTokenStartPosition() - 1;
1770 throwSyntaxError("Body declaration expected for method: "
1771 + new String(methodDecl.selector));
1776 functionBody(methodDecl);
1778 if (!fStackUnassigned.isEmpty()) {
1779 fStackUnassigned.remove(fStackUnassigned.size() - 1);
1784 private void functionDeclarator(MethodDeclaration methodDecl) {
1785 // identifier '(' [parameter-list] ')'
1786 if (token == TokenNameAND) {
1789 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1790 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1791 if (Scanner.isIdentifierOrKeyword(token)) {
1792 methodDecl.selector = scanner.getCurrentIdentifierSource();
1793 if (token > TokenNameKEYWORD) {
1794 problemReporter.phpKeywordWarning(new String[] { scanner
1795 .toStringAction(token) }, scanner
1796 .getCurrentTokenStartPosition(), scanner
1797 .getCurrentTokenEndPosition(), referenceContext,
1798 compilationUnit.compilationResult);
1801 if (token == TokenNameLPAREN) {
1804 methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
1805 throwSyntaxError("'(' expected in function declaration.");
1807 if (token != TokenNameRPAREN) {
1808 parameter_list(methodDecl);
1810 if (token != TokenNameRPAREN) {
1811 methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
1812 throwSyntaxError("')' expected in function declaration.");
1814 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1818 methodDecl.selector = "<undefined>".toCharArray();
1819 methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
1820 throwSyntaxError("Function name expected after keyword 'function'.");
1825 private void parameter_list(MethodDeclaration methodDecl) {
1826 // non_empty_parameter_list
1828 non_empty_parameter_list(methodDecl, true);
1831 private void non_empty_parameter_list(MethodDeclaration methodDecl,
1832 boolean empty_allowed) {
1833 // optional_class_type T_VARIABLE
1834 // | optional_class_type '&' T_VARIABLE
1835 // | optional_class_type '&' T_VARIABLE '=' static_scalar
1836 // | optional_class_type T_VARIABLE '=' static_scalar
1837 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE
1838 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
1839 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
1841 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
1843 char[] typeIdentifier = null;
1844 if (token == TokenNameIdentifier || token == TokenNamearray
1845 || token == TokenNameVariable || token == TokenNameAND) {
1846 HashSet set = peekVariableSet();
1848 if (token == TokenNameIdentifier || token == TokenNamearray) {// feature
1851 typeIdentifier = scanner.getCurrentIdentifierSource();
1854 if (token == TokenNameAND) {
1857 if (token == TokenNameVariable) {
1858 if (fMethodVariables != null) {
1860 if (methodDecl.type == MethodDeclaration.FUNCTION_DEFINITION) {
1861 info = new VariableInfo(scanner
1862 .getCurrentTokenStartPosition(),
1863 VariableInfo.LEVEL_FUNCTION_DEFINITION);
1865 info = new VariableInfo(scanner
1866 .getCurrentTokenStartPosition(),
1867 VariableInfo.LEVEL_METHOD_DEFINITION);
1869 info.typeIdentifier = typeIdentifier;
1870 fMethodVariables.put(new String(scanner
1871 .getCurrentIdentifierSource()), info);
1873 addVariableSet(set);
1875 if (token == TokenNameEQUAL) {
1880 throwSyntaxError("Variable expected in parameter list.");
1882 if (token != TokenNameCOMMA) {
1889 if (!empty_allowed) {
1890 throwSyntaxError("Identifier expected in parameter list.");
1894 private void optional_class_type() {
1899 // private void parameterDeclaration() {
1901 // //variable-reference
1902 // if (token == TokenNameAND) {
1904 // if (isVariable()) {
1907 // throwSyntaxError("Variable expected after reference operator '&'.");
1910 // //variable '=' constant
1911 // if (token == TokenNameVariable) {
1913 // if (token == TokenNameEQUAL) {
1919 // // if (token == TokenNamethis) {
1920 // // throwSyntaxError("Reserved word '$this' not allowed in parameter
1921 // // declaration.");
1925 private void labeledStatementList() {
1926 if (token != TokenNamecase && token != TokenNamedefault) {
1927 throwSyntaxError("'case' or 'default' expected.");
1930 if (token == TokenNamecase) {
1932 expr(); // constant();
1933 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1935 if (token == TokenNameRBRACE) {
1936 // empty case; assumes that the '}' token belongs to the
1938 // switch statement - #1371992
1941 if (token == TokenNamecase || token == TokenNamedefault) {
1942 // empty case statement ?
1947 // else if (token == TokenNameSEMICOLON) {
1949 // "':' expected after 'case' keyword (Found token: " +
1950 // scanner.toStringAction(token) + ")",
1951 // scanner.getCurrentTokenStartPosition(),
1952 // scanner.getCurrentTokenEndPosition(),
1955 // if (token == TokenNamecase) { // empty case statement ?
1961 throwSyntaxError("':' character expected after 'case' constant (Found token: "
1962 + scanner.toStringAction(token) + ")");
1964 } else { // TokenNamedefault
1966 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1968 if (token == TokenNameRBRACE) {
1969 // empty default case; ; assumes that the '}' token
1971 // wrapping switch statement - #1371992
1974 if (token != TokenNamecase) {
1978 throwSyntaxError("':' character expected after 'default'.");
1981 } while (token == TokenNamecase || token == TokenNamedefault);
1984 private void ifStatementColon(IfStatement iState) {
1985 // T_IF '(' expr ')' ':' inner_statement_list new_elseif_list
1986 // new_else_single T_ENDIF ';'
1987 HashSet assignedVariableSet = null;
1989 Block b = inner_statement_list();
1990 iState.thenStatement = b;
1991 checkUnreachable(iState, b);
1993 assignedVariableSet = removeIfVariableSet();
1995 if (token == TokenNameelseif) {
1997 pushIfVariableSet();
1998 new_elseif_list(iState);
2000 HashSet set = removeIfVariableSet();
2001 if (assignedVariableSet != null && set != null) {
2002 assignedVariableSet.addAll(set);
2007 pushIfVariableSet();
2008 new_else_single(iState);
2010 HashSet set = removeIfVariableSet();
2011 if (assignedVariableSet != null) {
2012 HashSet topSet = peekVariableSet();
2013 if (topSet != null) {
2017 topSet.addAll(assignedVariableSet);
2021 if (token != TokenNameendif) {
2022 throwSyntaxError("'endif' expected.");
2025 if (token != TokenNameSEMICOLON && token != TokenNameINLINE_HTML) {
2026 reportSyntaxError("';' expected after if-statement.");
2027 iState.sourceEnd = scanner.getCurrentTokenStartPosition();
2029 iState.sourceEnd = scanner.getCurrentTokenEndPosition();
2034 private void ifStatement(IfStatement iState) {
2035 // T_IF '(' expr ')' statement elseif_list else_single
2036 HashSet assignedVariableSet = null;
2038 pushIfVariableSet();
2039 Statement s = statement();
2040 iState.thenStatement = s;
2041 checkUnreachable(iState, s);
2043 assignedVariableSet = removeIfVariableSet();
2046 if (token == TokenNameelseif) {
2048 pushIfVariableSet();
2049 elseif_list(iState);
2051 HashSet set = removeIfVariableSet();
2052 if (assignedVariableSet != null && set != null) {
2053 assignedVariableSet.addAll(set);
2058 pushIfVariableSet();
2059 else_single(iState);
2061 HashSet set = removeIfVariableSet();
2062 if (assignedVariableSet != null) {
2063 HashSet topSet = peekVariableSet();
2064 if (topSet != null) {
2068 topSet.addAll(assignedVariableSet);
2074 private void elseif_list(IfStatement iState) {
2076 // | elseif_list T_ELSEIF '(' expr ')' statement
2077 ArrayList conditionList = new ArrayList();
2078 ArrayList statementList = new ArrayList();
2081 while (token == TokenNameelseif) {
2083 if (token == TokenNameLPAREN) {
2086 throwSyntaxError("'(' expected after 'elseif' keyword.");
2089 conditionList.add(e);
2090 if (token == TokenNameRPAREN) {
2093 throwSyntaxError("')' expected after 'elseif' condition.");
2096 statementList.add(s);
2097 checkUnreachable(iState, s);
2099 iState.elseifConditions = new Expression[conditionList.size()];
2100 iState.elseifStatements = new Statement[statementList.size()];
2101 conditionList.toArray(iState.elseifConditions);
2102 statementList.toArray(iState.elseifStatements);
2105 private void new_elseif_list(IfStatement iState) {
2107 // | new_elseif_list T_ELSEIF '(' expr ')' ':' inner_statement_list
2108 ArrayList conditionList = new ArrayList();
2109 ArrayList statementList = new ArrayList();
2112 while (token == TokenNameelseif) {
2114 if (token == TokenNameLPAREN) {
2117 throwSyntaxError("'(' expected after 'elseif' keyword.");
2120 conditionList.add(e);
2121 if (token == TokenNameRPAREN) {
2124 throwSyntaxError("')' expected after 'elseif' condition.");
2126 if (token == TokenNameCOLON) {
2129 throwSyntaxError("':' expected after 'elseif' keyword.");
2131 b = inner_statement_list();
2132 statementList.add(b);
2133 checkUnreachable(iState, b);
2135 iState.elseifConditions = new Expression[conditionList.size()];
2136 iState.elseifStatements = new Statement[statementList.size()];
2137 conditionList.toArray(iState.elseifConditions);
2138 statementList.toArray(iState.elseifStatements);
2141 private void else_single(IfStatement iState) {
2144 if (token == TokenNameelse) {
2146 Statement s = statement();
2147 iState.elseStatement = s;
2148 checkUnreachable(iState, s);
2150 iState.checkUnreachable = false;
2152 iState.sourceEnd = scanner.getCurrentTokenStartPosition();
2155 private void new_else_single(IfStatement iState) {
2157 // | T_ELSE ':' inner_statement_list
2158 if (token == TokenNameelse) {
2160 if (token == TokenNameCOLON) {
2163 throwSyntaxError("':' expected after 'else' keyword.");
2165 Block b = inner_statement_list();
2166 iState.elseStatement = b;
2167 checkUnreachable(iState, b);
2169 iState.checkUnreachable = false;
2173 private Block inner_statement_list() {
2174 // inner_statement_list inner_statement
2176 return statementList();
2183 private void checkUnreachable(IfStatement iState, Statement s) {
2184 if (s instanceof Block) {
2185 Block b = (Block) s;
2186 if (b.statements == null || b.statements.length == 0) {
2187 iState.checkUnreachable = false;
2189 int off = b.statements.length - 1;
2190 if (!(b.statements[off] instanceof ReturnStatement)
2191 && !(b.statements[off] instanceof ContinueStatement)
2192 && !(b.statements[off] instanceof BreakStatement)) {
2193 if (!(b.statements[off] instanceof IfStatement)
2194 || !((IfStatement) b.statements[off]).checkUnreachable) {
2195 iState.checkUnreachable = false;
2200 if (!(s instanceof ReturnStatement)
2201 && !(s instanceof ContinueStatement)
2202 && !(s instanceof BreakStatement)) {
2203 if (!(s instanceof IfStatement)
2204 || !((IfStatement) s).checkUnreachable) {
2205 iState.checkUnreachable = false;
2211 // private void elseifStatementList() {
2213 // elseifStatement();
2215 // case TokenNameelse:
2217 // if (token == TokenNameCOLON) {
2219 // if (token != TokenNameendif) {
2224 // if (token == TokenNameif) { //'else if'
2227 // throwSyntaxError("':' expected after 'else'.");
2231 // case TokenNameelseif:
2240 // private void elseifStatement() {
2241 // if (token == TokenNameLPAREN) {
2244 // if (token != TokenNameRPAREN) {
2245 // throwSyntaxError("')' expected in else-if-statement.");
2248 // if (token != TokenNameCOLON) {
2249 // throwSyntaxError("':' expected in else-if-statement.");
2252 // if (token != TokenNameendif) {
2258 private void switchStatement() {
2259 if (token == TokenNameCOLON) {
2260 // ':' [labeled-statement-list] 'endswitch' ';'
2262 labeledStatementList();
2263 if (token != TokenNameendswitch) {
2264 throwSyntaxError("'endswitch' expected.");
2267 if (token != TokenNameSEMICOLON && token != TokenNameINLINE_HTML) {
2268 throwSyntaxError("';' expected after switch-statement.");
2272 // '{' [labeled-statement-list] '}'
2273 if (token != TokenNameLBRACE) {
2274 throwSyntaxError("'{' expected in switch statement.");
2277 if (token != TokenNameRBRACE) {
2278 labeledStatementList();
2280 if (token != TokenNameRBRACE) {
2281 throwSyntaxError("'}' expected in switch statement.");
2287 private void forStatement() {
2288 if (token == TokenNameCOLON) {
2291 if (token != TokenNameendfor) {
2292 throwSyntaxError("'endfor' expected.");
2295 if (token != TokenNameSEMICOLON && token != TokenNameINLINE_HTML) {
2296 throwSyntaxError("';' expected after for-statement.");
2304 private void whileStatement() {
2305 // ':' statement-list 'endwhile' ';'
2306 if (token == TokenNameCOLON) {
2309 if (token != TokenNameendwhile) {
2310 throwSyntaxError("'endwhile' expected.");
2313 if (token != TokenNameSEMICOLON && token != TokenNameINLINE_HTML) {
2314 throwSyntaxError("';' expected after while-statement.");
2322 private void foreachStatement() {
2323 if (token == TokenNameCOLON) {
2326 if (token != TokenNameendforeach) {
2327 throwSyntaxError("'endforeach' expected.");
2330 if (token != TokenNameSEMICOLON && token != TokenNameINLINE_HTML) {
2331 throwSyntaxError("';' expected after foreach-statement.");
2339 // private void exitStatus() {
2340 // if (token == TokenNameLPAREN) {
2343 // throwSyntaxError("'(' expected in 'exit-status'.");
2345 // if (token != TokenNameRPAREN) {
2348 // if (token == TokenNameRPAREN) {
2351 // throwSyntaxError("')' expected after 'exit-status'.");
2354 private void expressionList() {
2357 if (token == TokenNameCOMMA) {
2365 private Expression expr() {
2367 // | expr_without_variable
2368 // if (token!=TokenNameEOF) {
2369 if (Scanner.TRACE) {
2370 System.out.println("TRACE: expr()");
2372 return expr_without_variable(true, null);
2376 private Expression expr_without_variable(boolean only_variable,
2377 UninitializedVariableHandler initHandler) {
2378 int exprSourceStart = scanner.getCurrentTokenStartPosition();
2379 int exprSourceEnd = scanner.getCurrentTokenEndPosition();
2380 Expression expression = new Expression();
2381 expression.sourceStart = exprSourceStart;
2382 // default, may be overwritten
2383 expression.sourceEnd = exprSourceEnd;
2385 // internal_functions_in_yacc
2394 // | T_INC rw_variable
2395 // | T_DEC rw_variable
2396 // | T_INT_CAST expr
2397 // | T_DOUBLE_CAST expr
2398 // | T_STRING_CAST expr
2399 // | T_ARRAY_CAST expr
2400 // | T_OBJECT_CAST expr
2401 // | T_BOOL_CAST expr
2402 // | T_UNSET_CAST expr
2403 // | T_EXIT exit_expr
2405 // | T_ARRAY '(' array_pair_list ')'
2406 // | '`' encaps_list '`'
2407 // | T_LIST '(' assignment_list ')' '=' expr
2408 // | T_NEW class_name_reference ctor_arguments
2409 // | variable '=' expr
2410 // | variable '=' '&' variable
2411 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2412 // | variable T_PLUS_EQUAL expr
2413 // | variable T_MINUS_EQUAL expr
2414 // | variable T_MUL_EQUAL expr
2415 // | variable T_DIV_EQUAL expr
2416 // | variable T_CONCAT_EQUAL expr
2417 // | variable T_MOD_EQUAL expr
2418 // | variable T_AND_EQUAL expr
2419 // | variable T_OR_EQUAL expr
2420 // | variable T_XOR_EQUAL expr
2421 // | variable T_SL_EQUAL expr
2422 // | variable T_SR_EQUAL expr
2423 // | rw_variable T_INC
2424 // | rw_variable T_DEC
2425 // | expr T_BOOLEAN_OR expr
2426 // | expr T_BOOLEAN_AND expr
2427 // | expr T_LOGICAL_OR expr
2428 // | expr T_LOGICAL_AND expr
2429 // | expr T_LOGICAL_XOR expr
2441 // | expr T_IS_IDENTICAL expr
2442 // | expr T_IS_NOT_IDENTICAL expr
2443 // | expr T_IS_EQUAL expr
2444 // | expr T_IS_NOT_EQUAL expr
2446 // | expr T_IS_SMALLER_OR_EQUAL expr
2448 // | expr T_IS_GREATER_OR_EQUAL expr
2449 // | expr T_INSTANCEOF class_name_reference
2450 // | expr '?' expr ':' expr
2451 if (Scanner.TRACE) {
2452 System.out.println("TRACE: expr_without_variable() PART 1");
2455 case TokenNameisset:
2456 // T_ISSET '(' isset_variables ')'
2458 if (token != TokenNameLPAREN) {
2459 throwSyntaxError("'(' expected after keyword 'isset'");
2463 if (token != TokenNameRPAREN) {
2464 throwSyntaxError("')' expected after keyword 'isset'");
2468 case TokenNameempty:
2470 if (token != TokenNameLPAREN) {
2471 throwSyntaxError("'(' expected after keyword 'empty'");
2474 variable(true, false);
2475 if (token != TokenNameRPAREN) {
2476 throwSyntaxError("')' expected after keyword 'empty'");
2481 case TokenNameinclude:
2482 case TokenNameinclude_once:
2483 case TokenNamerequire:
2484 case TokenNamerequire_once:
2485 case TokenNameNamespace:
2486 case TokenNameconst:
2487 internal_functions_in_yacc();
2490 case TokenNameLPAREN:
2493 if (token == TokenNameRPAREN) {
2496 throwSyntaxError("')' expected in expression.");
2506 // | T_INT_CAST expr
2507 // | T_DOUBLE_CAST expr
2508 // | T_STRING_CAST expr
2509 // | T_ARRAY_CAST expr
2510 // | T_OBJECT_CAST expr
2511 // | T_BOOL_CAST expr
2512 // | T_UNSET_CAST expr
2513 case TokenNameclone:
2514 case TokenNameprint:
2517 case TokenNameMINUS:
2519 case TokenNameTWIDDLE:
2520 case TokenNameintCAST:
2521 case TokenNamedoubleCAST:
2522 case TokenNamestringCAST:
2523 case TokenNamearrayCAST:
2524 case TokenNameobjectCAST:
2525 case TokenNameboolCAST:
2526 case TokenNameunsetCAST:
2536 // | T_STRING_VARNAME
2538 // | T_START_HEREDOC encaps_list T_END_HEREDOC
2539 // | '`' encaps_list '`'
2541 // | '`' encaps_list '`'
2542 // case TokenNameEncapsedString0:
2543 // scanner.encapsedStringStack.push(new Character('`'));
2546 // if (token == TokenNameEncapsedString0) {
2549 // if (token != TokenNameEncapsedString0) {
2550 // throwSyntaxError("\'`\' expected at end of string" + "(Found
2552 // scanner.toStringAction(token) + " )");
2556 // scanner.encapsedStringStack.pop();
2560 // // | '\'' encaps_list '\''
2561 // case TokenNameEncapsedString1:
2562 // scanner.encapsedStringStack.push(new Character('\''));
2565 // exprSourceStart = scanner.getCurrentTokenStartPosition();
2566 // if (token == TokenNameEncapsedString1) {
2568 // StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
2569 // exprSourceStart, scanner
2570 // .getCurrentTokenEndPosition());
2573 // if (token != TokenNameEncapsedString1) {
2574 // throwSyntaxError("\'\'\' expected at end of string" + "(Found
2576 // + scanner.toStringAction(token) + " )");
2579 // StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
2580 // exprSourceStart, scanner
2581 // .getCurrentTokenEndPosition());
2585 // scanner.encapsedStringStack.pop();
2589 // //| '"' encaps_list '"'
2590 // case TokenNameEncapsedString2:
2591 // scanner.encapsedStringStack.push(new Character('"'));
2594 // exprSourceStart = scanner.getCurrentTokenStartPosition();
2595 // if (token == TokenNameEncapsedString2) {
2597 // StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
2598 // exprSourceStart, scanner
2599 // .getCurrentTokenEndPosition());
2602 // if (token != TokenNameEncapsedString2) {
2603 // throwSyntaxError("'\"' expected at end of string" + "(Found
2605 // scanner.toStringAction(token) + " )");
2608 // StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
2609 // exprSourceStart, scanner
2610 // .getCurrentTokenEndPosition());
2614 // scanner.encapsedStringStack.pop();
2618 case TokenNameStringDoubleQuote:
2619 expression = new StringLiteralDQ(scanner
2620 .getCurrentStringLiteralSource(), scanner
2621 .getCurrentTokenStartPosition(), scanner
2622 .getCurrentTokenEndPosition());
2625 case TokenNameStringSingleQuote:
2626 expression = new StringLiteralSQ(scanner
2627 .getCurrentStringLiteralSource(), scanner
2628 .getCurrentTokenStartPosition(), scanner
2629 .getCurrentTokenEndPosition());
2632 case TokenNameIntegerLiteral:
2633 case TokenNameDoubleLiteral:
2634 case TokenNameStringInterpolated:
2637 case TokenNameCLASS_C:
2638 case TokenNameMETHOD_C:
2639 case TokenNameFUNC_C:
2642 case TokenNameHEREDOC:
2645 case TokenNamearray:
2646 // T_ARRAY '(' array_pair_list ')'
2648 if (token == TokenNameLPAREN) {
2650 if (token == TokenNameRPAREN) {
2655 if (token != TokenNameRPAREN) {
2656 throwSyntaxError("')' or ',' expected after keyword 'array'"
2658 + scanner.toStringAction(token) + ")");
2662 throwSyntaxError("'(' expected after keyword 'array'"
2663 + "(Found token: " + scanner.toStringAction(token)
2668 // | T_LIST '(' assignment_list ')' '=' expr
2670 if (token == TokenNameLPAREN) {
2673 if (token != TokenNameRPAREN) {
2674 throwSyntaxError("')' expected after 'list' keyword.");
2677 if (token != TokenNameEQUAL) {
2678 throwSyntaxError("'=' expected after 'list' keyword.");
2683 throwSyntaxError("'(' expected after 'list' keyword.");
2687 // | T_NEW class_name_reference ctor_arguments
2689 Expression typeRef = class_name_reference();
2691 if (typeRef != null) {
2692 expression = typeRef;
2695 // | T_INC rw_variable
2696 // | T_DEC rw_variable
2697 case TokenNamePLUS_PLUS:
2698 case TokenNameMINUS_MINUS:
2702 // | variable '=' expr
2703 // | variable '=' '&' variable
2704 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2705 // | variable T_PLUS_EQUAL expr
2706 // | variable T_MINUS_EQUAL expr
2707 // | variable T_MUL_EQUAL expr
2708 // | variable T_DIV_EQUAL expr
2709 // | variable T_CONCAT_EQUAL expr
2710 // | variable T_MOD_EQUAL expr
2711 // | variable T_AND_EQUAL expr
2712 // | variable T_OR_EQUAL expr
2713 // | variable T_XOR_EQUAL expr
2714 // | variable T_SL_EQUAL expr
2715 // | variable T_SR_EQUAL expr
2716 // | rw_variable T_INC
2717 // | rw_variable T_DEC
2718 case TokenNameIdentifier:
2719 case TokenNameVariable:
2720 case TokenNameDOLLAR:
2721 Expression lhs = null;
2722 boolean rememberedVar = false;
2723 if (token == TokenNameIdentifier) {
2724 lhs = identifier(true, true);
2729 lhs = variable(true, true);
2733 if (lhs != null && lhs instanceof FieldReference
2734 && token != TokenNameEQUAL
2735 && token != TokenNamePLUS_EQUAL
2736 && token != TokenNameMINUS_EQUAL
2737 && token != TokenNameMULTIPLY_EQUAL
2738 && token != TokenNameDIVIDE_EQUAL
2739 && token != TokenNameDOT_EQUAL
2740 && token != TokenNameREMAINDER_EQUAL
2741 && token != TokenNameAND_EQUAL
2742 && token != TokenNameOR_EQUAL
2743 && token != TokenNameXOR_EQUAL
2744 && token != TokenNameRIGHT_SHIFT_EQUAL
2745 && token != TokenNameLEFT_SHIFT_EQUAL) {
2746 FieldReference ref = (FieldReference) lhs;
2747 if (!containsVariableSet(ref.token)) {
2748 if (null == initHandler
2749 || initHandler.reportError()) {
2750 problemReporter.uninitializedLocalVariable(
2751 new String(ref.token), ref.sourceStart,
2752 ref.sourceEnd, referenceContext,
2753 compilationUnit.compilationResult);
2755 addVariableSet(ref.token);
2760 case TokenNameEQUAL:
2761 if (lhs != null && lhs instanceof FieldReference) {
2762 addVariableSet(((FieldReference) lhs).token);
2765 if (token == TokenNameAND) {
2767 if (token == TokenNamenew) {
2768 // | variable '=' '&' T_NEW class_name_reference
2771 SingleTypeReference classRef = class_name_reference();
2773 if (classRef != null) {
2775 && lhs instanceof FieldReference) {
2777 // $var = & new Object();
2778 if (fMethodVariables != null) {
2779 VariableInfo lhsInfo = new VariableInfo(
2780 ((FieldReference) lhs).sourceStart);
2781 lhsInfo.reference = classRef;
2782 lhsInfo.typeIdentifier = classRef.token;
2783 fMethodVariables.put(new String(
2784 ((FieldReference) lhs).token),
2786 rememberedVar = true;
2791 Expression rhs = variable(false, false);
2792 if (rhs != null && rhs instanceof FieldReference
2794 && lhs instanceof FieldReference) {
2797 if (fMethodVariables != null) {
2798 VariableInfo rhsInfo = (VariableInfo) fMethodVariables
2799 .get(((FieldReference) rhs).token);
2801 && rhsInfo.reference != null) {
2802 VariableInfo lhsInfo = new VariableInfo(
2803 ((FieldReference) lhs).sourceStart);
2804 lhsInfo.reference = rhsInfo.reference;
2805 lhsInfo.typeIdentifier = rhsInfo.typeIdentifier;
2806 fMethodVariables.put(new String(
2807 ((FieldReference) lhs).token),
2809 rememberedVar = true;
2815 Expression rhs = expr();
2816 if (lhs != null && lhs instanceof FieldReference) {
2817 if (rhs != null && rhs instanceof FieldReference) {
2820 if (fMethodVariables != null) {
2821 VariableInfo rhsInfo = (VariableInfo) fMethodVariables
2822 .get(((FieldReference) rhs).token);
2824 && rhsInfo.reference != null) {
2825 VariableInfo lhsInfo = new VariableInfo(
2826 ((FieldReference) lhs).sourceStart);
2827 lhsInfo.reference = rhsInfo.reference;
2828 lhsInfo.typeIdentifier = rhsInfo.typeIdentifier;
2829 fMethodVariables.put(new String(
2830 ((FieldReference) lhs).token),
2832 rememberedVar = true;
2835 } else if (rhs != null
2836 && rhs instanceof SingleTypeReference) {
2838 // $var = new Object();
2839 if (fMethodVariables != null) {
2840 VariableInfo lhsInfo = new VariableInfo(
2841 ((FieldReference) lhs).sourceStart);
2842 lhsInfo.reference = (SingleTypeReference) rhs;
2843 lhsInfo.typeIdentifier = ((SingleTypeReference) rhs).token;
2844 fMethodVariables.put(new String(
2845 ((FieldReference) lhs).token),
2847 rememberedVar = true;
2852 if (rememberedVar == false && lhs != null
2853 && lhs instanceof FieldReference) {
2854 if (fMethodVariables != null) {
2855 VariableInfo lhsInfo = new VariableInfo(
2856 ((FieldReference) lhs).sourceStart);
2857 fMethodVariables.put(new String(
2858 ((FieldReference) lhs).token), lhsInfo);
2862 case TokenNamePLUS_EQUAL:
2863 case TokenNameMINUS_EQUAL:
2864 case TokenNameMULTIPLY_EQUAL:
2865 case TokenNameDIVIDE_EQUAL:
2866 case TokenNameDOT_EQUAL:
2867 case TokenNameREMAINDER_EQUAL:
2868 case TokenNameAND_EQUAL:
2869 case TokenNameOR_EQUAL:
2870 case TokenNameXOR_EQUAL:
2871 case TokenNameRIGHT_SHIFT_EQUAL:
2872 case TokenNameLEFT_SHIFT_EQUAL:
2873 if (lhs != null && lhs instanceof FieldReference) {
2874 addVariableSet(((FieldReference) lhs).token);
2879 case TokenNamePLUS_PLUS:
2880 case TokenNameMINUS_MINUS:
2884 if (!only_variable) {
2885 throwSyntaxError("Variable expression not allowed (found token '"
2886 + scanner.toStringAction(token) + "').");
2894 if (token != TokenNameINLINE_HTML) {
2895 if (token > TokenNameKEYWORD) {
2899 // System.out.println(scanner.getCurrentTokenStartPosition());
2900 // System.out.println(scanner.getCurrentTokenEndPosition());
2902 throwSyntaxError("Error in expression (found token '"
2903 + scanner.toStringAction(token) + "').");
2908 if (Scanner.TRACE) {
2909 System.out.println("TRACE: expr_without_variable() PART 2");
2911 // | expr T_BOOLEAN_OR expr
2912 // | expr T_BOOLEAN_AND expr
2913 // | expr T_LOGICAL_OR expr
2914 // | expr T_LOGICAL_AND expr
2915 // | expr T_LOGICAL_XOR expr
2927 // | expr T_IS_IDENTICAL expr
2928 // | expr T_IS_NOT_IDENTICAL expr
2929 // | expr T_IS_EQUAL expr
2930 // | expr T_IS_NOT_EQUAL expr
2932 // | expr T_IS_SMALLER_OR_EQUAL expr
2934 // | expr T_IS_GREATER_OR_EQUAL expr
2937 case TokenNameOR_OR:
2939 expression = new OR_OR_Expression(expression, expr(), token);
2941 case TokenNameAND_AND:
2943 expression = new AND_AND_Expression(expression, expr(),
2946 case TokenNameEQUAL_EQUAL:
2948 expression = new EqualExpression(expression, expr(), token);
2958 case TokenNameMINUS:
2959 case TokenNameMULTIPLY:
2960 case TokenNameDIVIDE:
2961 case TokenNameREMAINDER:
2962 case TokenNameLEFT_SHIFT:
2963 case TokenNameRIGHT_SHIFT:
2964 case TokenNameEQUAL_EQUAL_EQUAL:
2965 case TokenNameNOT_EQUAL_EQUAL:
2966 case TokenNameNOT_EQUAL:
2968 case TokenNameLESS_EQUAL:
2969 case TokenNameGREATER:
2970 case TokenNameGREATER_EQUAL:
2972 expression = new BinaryExpression(expression, expr(), token);
2974 // | expr T_INSTANCEOF class_name_reference
2975 // | expr '?' expr ':' expr
2976 case TokenNameinstanceof:
2978 TypeReference classRef = class_name_reference();
2979 if (classRef != null) {
2980 expression = new InstanceOfExpression(expression,
2981 classRef, OperatorIds.INSTANCEOF);
2982 expression.sourceStart = exprSourceStart;
2983 expression.sourceEnd = scanner
2984 .getCurrentTokenEndPosition();
2987 case TokenNameQUESTION:
2989 Expression valueIfTrue = expr();
2990 if (token != TokenNameCOLON) {
2991 throwSyntaxError("':' expected in conditional expression.");
2994 Expression valueIfFalse = expr();
2996 expression = new ConditionalExpression(expression,
2997 valueIfTrue, valueIfFalse);
3003 } catch (SyntaxError e) {
3004 // try to find next token after expression with errors:
3005 if (token == TokenNameSEMICOLON) {
3009 if (token == TokenNameRBRACE || token == TokenNameRPAREN
3010 || token == TokenNameRBRACKET) {
3018 private SingleTypeReference class_name_reference() {
3019 // class_name_reference:
3021 // | dynamic_class_name_reference
3022 SingleTypeReference ref = null;
3023 if (Scanner.TRACE) {
3024 System.out.println("TRACE: class_name_reference()");
3026 if (token == TokenNameIdentifier) {
3027 ref = new SingleTypeReference(scanner.getCurrentIdentifierSource(),
3028 scanner.getCurrentTokenStartPosition());
3029 int pos = scanner.currentPosition;
3031 if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3032 // Not terminated by T_STRING, reduce to dynamic_class_name_reference
3033 scanner.currentPosition = pos;
3034 token = TokenNameIdentifier;
3036 dynamic_class_name_reference();
3040 dynamic_class_name_reference();
3045 private void dynamic_class_name_reference() {
3046 // dynamic_class_name_reference:
3047 // base_variable T_OBJECT_OPERATOR object_property
3048 // dynamic_class_name_variable_properties
3050 if (Scanner.TRACE) {
3051 System.out.println("TRACE: dynamic_class_name_reference()");
3053 base_variable(true);
3054 if (token == TokenNameMINUS_GREATER) {
3057 dynamic_class_name_variable_properties();
3061 private void dynamic_class_name_variable_properties() {
3062 // dynamic_class_name_variable_properties:
3063 // dynamic_class_name_variable_properties
3064 // dynamic_class_name_variable_property
3066 if (Scanner.TRACE) {
3068 .println("TRACE: dynamic_class_name_variable_properties()");
3070 while (token == TokenNameMINUS_GREATER) {
3071 dynamic_class_name_variable_property();
3075 private void dynamic_class_name_variable_property() {
3076 // dynamic_class_name_variable_property:
3077 // T_OBJECT_OPERATOR object_property
3078 if (Scanner.TRACE) {
3079 System.out.println("TRACE: dynamic_class_name_variable_property()");
3081 if (token == TokenNameMINUS_GREATER) {
3087 private void ctor_arguments() {
3090 // | '(' function_call_parameter_list ')'
3091 if (token == TokenNameLPAREN) {
3093 if (token == TokenNameRPAREN) {
3097 non_empty_function_call_parameter_list();
3098 if (token != TokenNameRPAREN) {
3099 throwSyntaxError("')' expected in ctor_arguments.");
3105 private void assignment_list() {
3107 // assignment_list ',' assignment_list_element
3108 // | assignment_list_element
3110 assignment_list_element();
3111 if (token != TokenNameCOMMA) {
3118 private void assignment_list_element() {
3119 // assignment_list_element:
3121 // | T_LIST '(' assignment_list ')'
3123 if (token == TokenNameVariable) {
3124 variable(true, false);
3125 } else if (token == TokenNameDOLLAR) {
3126 variable(false, false);
3127 } else if (token == TokenNameIdentifier) {
3128 identifier(true, true);
3130 if (token == TokenNamelist) {
3132 if (token == TokenNameLPAREN) {
3135 if (token != TokenNameRPAREN) {
3136 throwSyntaxError("')' expected after 'list' keyword.");
3140 throwSyntaxError("'(' expected after 'list' keyword.");
3146 private void array_pair_list() {
3149 // | non_empty_array_pair_list possible_comma
3150 non_empty_array_pair_list();
3151 if (token == TokenNameCOMMA) {
3156 private void non_empty_array_pair_list() {
3157 // non_empty_array_pair_list:
3158 // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
3159 // | non_empty_array_pair_list ',' expr
3160 // | expr T_DOUBLE_ARROW expr
3162 // | non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
3163 // | non_empty_array_pair_list ',' '&' w_variable
3164 // | expr T_DOUBLE_ARROW '&' w_variable
3167 if (token == TokenNameAND) {
3169 variable(true, false);
3172 if (token == TokenNameAND) {
3174 variable(true, false);
3175 } else if (token == TokenNameEQUAL_GREATER) {
3177 if (token == TokenNameAND) {
3179 variable(true, false);
3185 if (token != TokenNameCOMMA) {
3189 if (token == TokenNameRPAREN) {
3195 // private void variableList() {
3198 // if (token == TokenNameCOMMA) {
3205 private Expression variable_without_objects(boolean lefthandside,
3206 boolean ignoreVar) {
3207 // variable_without_objects:
3208 // reference_variable
3209 // | simple_indirect_reference reference_variable
3210 if (Scanner.TRACE) {
3211 System.out.println("TRACE: variable_without_objects()");
3213 while (token == TokenNameDOLLAR) {
3216 return reference_variable(lefthandside, ignoreVar);
3219 private Expression function_call(boolean lefthandside, boolean ignoreVar) {
3221 // T_STRING '(' function_call_parameter_list ')'
3222 // | class_constant '(' function_call_parameter_list ')'
3223 // | static_member '(' function_call_parameter_list ')'
3224 // | variable_without_objects '(' function_call_parameter_list ')'
3225 char[] defineName = null;
3226 char[] ident = null;
3229 Expression ref = null;
3230 if (Scanner.TRACE) {
3231 System.out.println("TRACE: function_call()");
3233 if (token == TokenNameIdentifier) {
3234 ident = scanner.getCurrentIdentifierSource();
3236 startPos = scanner.getCurrentTokenStartPosition();
3237 endPos = scanner.getCurrentTokenEndPosition();
3240 case TokenNamePAAMAYIM_NEKUDOTAYIM:
3244 if (token == TokenNameIdentifier) {
3249 variable_without_objects(true, false);
3254 ref = variable_without_objects(lefthandside, ignoreVar);
3256 if (token != TokenNameLPAREN) {
3257 if (defineName != null) {
3258 // does this identifier contain only uppercase characters?
3259 if (defineName.length == 3) {
3260 if (defineName[0] == 'd' && defineName[1] == 'i'
3261 && defineName[2] == 'e') {
3264 } else if (defineName.length == 4) {
3265 if (defineName[0] == 't' && defineName[1] == 'r'
3266 && defineName[2] == 'u' && defineName[3] == 'e') {
3268 } else if (defineName[0] == 'n' && defineName[1] == 'u'
3269 && defineName[2] == 'l' && defineName[3] == 'l') {
3272 } else if (defineName.length == 5) {
3273 if (defineName[0] == 'f' && defineName[1] == 'a'
3274 && defineName[2] == 'l' && defineName[3] == 's'
3275 && defineName[4] == 'e') {
3279 if (defineName != null) {
3280 for (int i = 0; i < defineName.length; i++) {
3281 if (Character.isLowerCase(defineName[i])) {
3282 problemReporter.phpUppercaseIdentifierWarning(
3283 startPos, endPos, referenceContext,
3284 compilationUnit.compilationResult);
3292 if (token == TokenNameRPAREN) {
3296 non_empty_function_call_parameter_list();
3297 if (token != TokenNameRPAREN) {
3298 String functionName;
3299 if (ident == null) {
3300 functionName = new String(" ");
3302 functionName = new String(ident);
3304 throwSyntaxError("')' expected in function call ("
3305 + functionName + ").");
3312 private void non_empty_function_call_parameter_list() {
3313 this.non_empty_function_call_parameter_list(null);
3316 // private void function_call_parameter_list() {
3317 // function_call_parameter_list:
3318 // non_empty_function_call_parameter_list { $$ = $1; }
3321 private void non_empty_function_call_parameter_list(String functionName) {
3322 // non_empty_function_call_parameter_list:
3323 // expr_without_variable
3326 // | non_empty_function_call_parameter_list ',' expr_without_variable
3327 // | non_empty_function_call_parameter_list ',' variable
3328 // | non_empty_function_call_parameter_list ',' '&' w_variable
3329 if (Scanner.TRACE) {
3331 .println("TRACE: non_empty_function_call_parameter_list()");
3333 UninitializedVariableHandler initHandler = new UninitializedVariableHandler();
3334 initHandler.setFunctionName(functionName);
3336 initHandler.incrementArgumentCount();
3337 if (token == TokenNameAND) {
3341 // if (token == TokenNameIdentifier || token ==
3342 // TokenNameVariable
3343 // || token == TokenNameDOLLAR) {
3346 expr_without_variable(true, initHandler);
3349 if (token != TokenNameCOMMA) {
3356 private void fully_qualified_class_name() {
3357 if (token == TokenNameIdentifier) {
3360 throwSyntaxError("Class name expected.");
3364 private void static_member() {
3366 // fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
3367 // variable_without_objects
3368 if (Scanner.TRACE) {
3369 System.out.println("TRACE: static_member()");
3371 fully_qualified_class_name();
3372 if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
3373 throwSyntaxError("'::' expected after class name (static_member).");
3376 variable_without_objects(false, false);
3379 private Expression base_variable_with_function_calls(boolean lefthandside,
3380 boolean ignoreVar) {
3381 // base_variable_with_function_calls:
3384 if (Scanner.TRACE) {
3385 System.out.println("TRACE: base_variable_with_function_calls()");
3387 return function_call(lefthandside, ignoreVar);
3390 private Expression base_variable(boolean lefthandside) {
3392 // reference_variable
3393 // | simple_indirect_reference reference_variable
3395 Expression ref = null;
3396 if (Scanner.TRACE) {
3397 System.out.println("TRACE: base_variable()");
3399 if (token == TokenNameIdentifier) {
3402 while (token == TokenNameDOLLAR) {
3405 reference_variable(lefthandside, false);
3410 // private void simple_indirect_reference() {
3411 // // simple_indirect_reference:
3413 // //| simple_indirect_reference '$'
3415 private Expression reference_variable(boolean lefthandside,
3416 boolean ignoreVar) {
3417 // reference_variable:
3418 // reference_variable '[' dim_offset ']'
3419 // | reference_variable '{' expr '}'
3420 // | compound_variable
3421 Expression ref = null;
3422 if (Scanner.TRACE) {
3423 System.out.println("TRACE: reference_variable()");
3425 ref = compound_variable(lefthandside, ignoreVar);
3427 if (token == TokenNameLBRACE) {
3431 if (token != TokenNameRBRACE) {
3432 throwSyntaxError("'}' expected in reference variable.");
3435 } else if (token == TokenNameLBRACKET) {
3436 // To remove "ref = null;" here, is probably better than the
3438 // commented in #1368081 - axelcl
3440 if (token != TokenNameRBRACKET) {
3443 if (token != TokenNameRBRACKET) {
3444 throwSyntaxError("']' expected in reference variable.");
3455 private Expression compound_variable(boolean lefthandside, boolean ignoreVar) {
3456 // compound_variable:
3458 // | '$' '{' expr '}'
3459 if (Scanner.TRACE) {
3460 System.out.println("TRACE: compound_variable()");
3462 if (token == TokenNameVariable) {
3463 if (!lefthandside) {
3464 if (!containsVariableSet()) {
3465 // reportSyntaxError("The local variable " + new
3466 // String(scanner.getCurrentIdentifierSource())
3467 // + " may not have been initialized");
3468 problemReporter.uninitializedLocalVariable(new String(
3469 scanner.getCurrentIdentifierSource()), scanner
3470 .getCurrentTokenStartPosition(), scanner
3471 .getCurrentTokenEndPosition(), referenceContext,
3472 compilationUnit.compilationResult);
3479 FieldReference ref = new FieldReference(scanner
3480 .getCurrentIdentifierSource(), scanner
3481 .getCurrentTokenStartPosition());
3485 // because of simple_indirect_reference
3486 while (token == TokenNameDOLLAR) {
3489 if (token != TokenNameLBRACE) {
3490 reportSyntaxError("'{' expected after compound variable token '$'.");
3495 if (token != TokenNameRBRACE) {
3496 throwSyntaxError("'}' expected after compound variable token '$'.");
3501 } // private void dim_offset() { // // dim_offset: // // /* empty */
3506 private void object_property() {
3509 // | variable_without_objects
3510 if (Scanner.TRACE) {
3511 System.out.println("TRACE: object_property()");
3513 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
3514 variable_without_objects(false, false);
3520 private void object_dim_list() {
3522 // object_dim_list '[' dim_offset ']'
3523 // | object_dim_list '{' expr '}'
3525 if (Scanner.TRACE) {
3526 System.out.println("TRACE: object_dim_list()");
3530 if (token == TokenNameLBRACE) {
3533 if (token != TokenNameRBRACE) {
3534 throwSyntaxError("'}' expected in object_dim_list.");
3537 } else if (token == TokenNameLBRACKET) {
3539 if (token == TokenNameRBRACKET) {
3544 if (token != TokenNameRBRACKET) {
3545 throwSyntaxError("']' expected in object_dim_list.");
3554 private void variable_name() {
3558 if (Scanner.TRACE) {
3559 System.out.println("TRACE: variable_name()");
3561 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
3562 if (token > TokenNameKEYWORD) {
3563 // TODO show a warning "Keyword used as variable" ?
3567 if (token != TokenNameLBRACE) {
3568 throwSyntaxError("'{' expected in variable name.");
3572 if (token != TokenNameRBRACE) {
3573 throwSyntaxError("'}' expected in variable name.");
3579 private void r_variable() {
3580 variable(false, false);
3583 private void w_variable(boolean lefthandside) {
3584 variable(lefthandside, false);
3587 private void rw_variable() {
3588 variable(false, false);
3591 private Expression variable(boolean lefthandside, boolean ignoreVar) {
3593 // base_variable_with_function_calls T_OBJECT_OPERATOR
3594 // object_property method_or_not variable_properties
3595 // | base_variable_with_function_calls
3596 Expression ref = base_variable_with_function_calls(lefthandside,
3598 if (token == TokenNameMINUS_GREATER) {
3603 variable_properties();
3608 private void variable_properties() {
3609 // variable_properties:
3610 // variable_properties variable_property
3612 while (token == TokenNameMINUS_GREATER) {
3613 variable_property();
3617 private void variable_property() {
3618 // variable_property:
3619 // T_OBJECT_OPERATOR object_property method_or_not
3620 if (Scanner.TRACE) {
3621 System.out.println("TRACE: variable_property()");
3623 if (token == TokenNameMINUS_GREATER) {
3628 throwSyntaxError("'->' expected in variable_property.");
3632 private Expression identifier(boolean lefthandside, boolean ignoreVar) {
3634 // base_variable_with_function_calls T_OBJECT_OPERATOR
3635 // object_property method_or_not variable_properties
3636 // | base_variable_with_function_calls
3638 // Expression ref = function_call(lefthandside, ignoreVar);
3641 // T_STRING '(' function_call_parameter_list ')'
3642 // | class_constant '(' function_call_parameter_list ')'
3643 // | static_member '(' function_call_parameter_list ')'
3644 // | variable_without_objects '(' function_call_parameter_list ')'
3645 char[] defineName = null;
3646 char[] ident = null;
3649 Expression ref = null;
3650 if (Scanner.TRACE) {
3651 System.out.println("TRACE: function_call()");
3653 if (token == TokenNameIdentifier) {
3654 ident = scanner.getCurrentIdentifierSource();
3656 startPos = scanner.getCurrentTokenStartPosition();
3657 endPos = scanner.getCurrentTokenEndPosition();
3660 if (token == TokenNameEQUAL || token == TokenNamePLUS_EQUAL
3661 || token == TokenNameMINUS_EQUAL
3662 || token == TokenNameMULTIPLY_EQUAL
3663 || token == TokenNameDIVIDE_EQUAL
3664 || token == TokenNameDOT_EQUAL
3665 || token == TokenNameREMAINDER_EQUAL
3666 || token == TokenNameAND_EQUAL
3667 || token == TokenNameOR_EQUAL
3668 || token == TokenNameXOR_EQUAL
3669 || token == TokenNameRIGHT_SHIFT_EQUAL
3670 || token == TokenNameLEFT_SHIFT_EQUAL) {
3671 String error = "Assignment operator '"
3672 + scanner.toStringAction(token)
3673 + "' not allowed after identifier '"
3675 + "' (use 'define(...)' to define constants).";
3676 reportSyntaxError(error);
3680 case TokenNamePAAMAYIM_NEKUDOTAYIM:
3684 if (token == TokenNameIdentifier) {
3689 variable_without_objects(true, false);
3694 ref = variable_without_objects(lefthandside, ignoreVar);
3696 if (token != TokenNameLPAREN) {
3697 if (defineName != null) {
3698 // does this identifier contain only uppercase characters?
3699 if (defineName.length == 3) {
3700 if (defineName[0] == 'd' && defineName[1] == 'i'
3701 && defineName[2] == 'e') {
3704 } else if (defineName.length == 4) {
3705 if (defineName[0] == 't' && defineName[1] == 'r'
3706 && defineName[2] == 'u' && defineName[3] == 'e') {
3708 } else if (defineName[0] == 'n' && defineName[1] == 'u'
3709 && defineName[2] == 'l' && defineName[3] == 'l') {
3712 } else if (defineName.length == 5) {
3713 if (defineName[0] == 'f' && defineName[1] == 'a'
3714 && defineName[2] == 'l' && defineName[3] == 's'
3715 && defineName[4] == 'e') {
3719 if (defineName != null) {
3720 for (int i = 0; i < defineName.length; i++) {
3721 if (Character.isLowerCase(defineName[i])) {
3722 problemReporter.phpUppercaseIdentifierWarning(
3723 startPos, endPos, referenceContext,
3724 compilationUnit.compilationResult);
3730 // TODO is this ok ?
3732 // throwSyntaxError("'(' expected in function call.");
3736 if (token == TokenNameRPAREN) {
3740 String functionName;
3741 if (ident == null) {
3742 functionName = new String(" ");
3744 functionName = new String(ident);
3746 non_empty_function_call_parameter_list(functionName);
3747 if (token != TokenNameRPAREN) {
3748 throwSyntaxError("')' expected in function call ("
3749 + functionName + ").");
3754 if (token == TokenNameMINUS_GREATER) {
3759 variable_properties();
3764 private void method_or_not() {
3766 // '(' function_call_parameter_list ')'
3768 if (Scanner.TRACE) {
3769 System.out.println("TRACE: method_or_not()");
3771 if (token == TokenNameLPAREN) {
3773 if (token == TokenNameRPAREN) {
3777 non_empty_function_call_parameter_list();
3778 if (token != TokenNameRPAREN) {
3779 throwSyntaxError("')' expected in method_or_not.");
3785 private void exit_expr() {
3789 if (token != TokenNameLPAREN) {
3793 if (token == TokenNameRPAREN) {
3798 if (token != TokenNameRPAREN) {
3799 throwSyntaxError("')' expected after keyword 'exit'");
3804 // private void encaps_list() {
3805 // // encaps_list encaps_var
3806 // // | encaps_list T_STRING
3807 // // | encaps_list T_NUM_STRING
3808 // // | encaps_list T_ENCAPSED_AND_WHITESPACE
3809 // // | encaps_list T_CHARACTER
3810 // // | encaps_list T_BAD_CHARACTER
3811 // // | encaps_list '['
3812 // // | encaps_list ']'
3813 // // | encaps_list '{'
3814 // // | encaps_list '}'
3815 // // | encaps_list T_OBJECT_OPERATOR
3819 // case TokenNameSTRING:
3822 // case TokenNameLBRACE:
3823 // // scanner.encapsedStringStack.pop();
3826 // case TokenNameRBRACE:
3827 // // scanner.encapsedStringStack.pop();
3830 // case TokenNameLBRACKET:
3831 // // scanner.encapsedStringStack.pop();
3834 // case TokenNameRBRACKET:
3835 // // scanner.encapsedStringStack.pop();
3838 // case TokenNameMINUS_GREATER:
3839 // // scanner.encapsedStringStack.pop();
3842 // case TokenNameVariable:
3843 // case TokenNameDOLLAR_LBRACE:
3844 // case TokenNameLBRACE_DOLLAR:
3848 // char encapsedChar = ((Character)
3849 // scanner.encapsedStringStack.peek()).charValue();
3850 // if (encapsedChar == '$') {
3851 // scanner.encapsedStringStack.pop();
3852 // encapsedChar = ((Character)
3853 // scanner.encapsedStringStack.peek()).charValue();
3854 // switch (encapsedChar) {
3856 // if (token == TokenNameEncapsedString0) {
3859 // token = TokenNameSTRING;
3862 // if (token == TokenNameEncapsedString1) {
3865 // token = TokenNameSTRING;
3868 // if (token == TokenNameEncapsedString2) {
3871 // token = TokenNameSTRING;
3880 // private void encaps_var() {
3882 // // | T_VARIABLE '[' encaps_var_offset ']'
3883 // // | T_VARIABLE T_OBJECT_OPERATOR T_STRING
3884 // // | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
3885 // // | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
3886 // // | T_CURLY_OPEN variable '}'
3888 // case TokenNameVariable:
3890 // if (token == TokenNameLBRACKET) {
3892 // expr(); //encaps_var_offset();
3893 // if (token != TokenNameRBRACKET) {
3894 // throwSyntaxError("']' expected after variable.");
3896 // // scanner.encapsedStringStack.pop();
3899 // } else if (token == TokenNameMINUS_GREATER) {
3901 // if (token != TokenNameIdentifier) {
3902 // throwSyntaxError("Identifier expected after '->'.");
3904 // // scanner.encapsedStringStack.pop();
3908 // // // scanner.encapsedStringStack.pop();
3909 // // int tempToken = TokenNameSTRING;
3910 // // if (!scanner.encapsedStringStack.isEmpty()
3911 // // && (token == TokenNameEncapsedString0
3912 // // || token == TokenNameEncapsedString1
3913 // // || token == TokenNameEncapsedString2 || token ==
3914 // // TokenNameERROR)) {
3915 // // char encapsedChar = ((Character)
3916 // // scanner.encapsedStringStack.peek())
3918 // // switch (token) {
3919 // // case TokenNameEncapsedString0 :
3920 // // if (encapsedChar == '`') {
3921 // // tempToken = TokenNameEncapsedString0;
3924 // // case TokenNameEncapsedString1 :
3925 // // if (encapsedChar == '\'') {
3926 // // tempToken = TokenNameEncapsedString1;
3929 // // case TokenNameEncapsedString2 :
3930 // // if (encapsedChar == '"') {
3931 // // tempToken = TokenNameEncapsedString2;
3934 // // case TokenNameERROR :
3935 // // if (scanner.source[scanner.currentPosition - 1] == '\\') {
3936 // // scanner.currentPosition--;
3937 // // getNextToken();
3942 // // token = tempToken;
3945 // case TokenNameDOLLAR_LBRACE:
3947 // if (token == TokenNameDOLLAR_LBRACE) {
3949 // } else if (token == TokenNameIdentifier) {
3951 // if (token == TokenNameLBRACKET) {
3953 // // if (token == TokenNameRBRACKET) {
3954 // // getNextToken();
3957 // if (token != TokenNameRBRACKET) {
3958 // throwSyntaxError("']' expected after '${'.");
3966 // if (token != TokenNameRBRACE) {
3967 // throwSyntaxError("'}' expected.");
3971 // case TokenNameLBRACE_DOLLAR:
3973 // if (token == TokenNameLBRACE_DOLLAR) {
3975 // } else if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
3977 // if (token == TokenNameLBRACKET) {
3979 // // if (token == TokenNameRBRACKET) {
3980 // // getNextToken();
3983 // if (token != TokenNameRBRACKET) {
3984 // throwSyntaxError("']' expected.");
3988 // } else if (token == TokenNameMINUS_GREATER) {
3990 // if (token != TokenNameIdentifier && token != TokenNameVariable) {
3991 // throwSyntaxError("String or Variable token expected.");
3994 // if (token == TokenNameLBRACKET) {
3996 // // if (token == TokenNameRBRACKET) {
3997 // // getNextToken();
4000 // if (token != TokenNameRBRACKET) {
4001 // throwSyntaxError("']' expected after '${'.");
4007 // // if (token != TokenNameRBRACE) {
4008 // // throwSyntaxError("'}' expected after '{$'.");
4010 // // // scanner.encapsedStringStack.pop();
4011 // // getNextToken();
4014 // if (token != TokenNameRBRACE) {
4015 // throwSyntaxError("'}' expected.");
4017 // // scanner.encapsedStringStack.pop();
4024 // private void encaps_var_offset() {
4026 // // | T_NUM_STRING
4029 // case TokenNameSTRING:
4032 // case TokenNameIntegerLiteral:
4035 // case TokenNameVariable:
4038 // case TokenNameIdentifier:
4042 // throwSyntaxError("Variable or String token expected.");
4047 private void internal_functions_in_yacc() {
4050 // case TokenNameisset:
4051 // // T_ISSET '(' isset_variables ')'
4053 // if (token != TokenNameLPAREN) {
4054 // throwSyntaxError("'(' expected after keyword 'isset'");
4057 // isset_variables();
4058 // if (token != TokenNameRPAREN) {
4059 // throwSyntaxError("')' expected after keyword 'isset'");
4063 // case TokenNameempty:
4064 // // T_EMPTY '(' variable ')'
4066 // if (token != TokenNameLPAREN) {
4067 // throwSyntaxError("'(' expected after keyword 'empty'");
4071 // if (token != TokenNameRPAREN) {
4072 // throwSyntaxError("')' expected after keyword 'empty'");
4076 case TokenNameinclude:
4078 checkFileName(token);
4080 case TokenNameinclude_once:
4081 // T_INCLUDE_ONCE expr
4082 checkFileName(token);
4085 // T_EVAL '(' expr ')'
4087 if (token != TokenNameLPAREN) {
4088 throwSyntaxError("'(' expected after keyword 'eval'");
4092 if (token != TokenNameRPAREN) {
4093 throwSyntaxError("')' expected after keyword 'eval'");
4097 case TokenNamerequire:
4099 checkFileName(token);
4101 case TokenNamerequire_once:
4102 // T_REQUIRE_ONCE expr
4103 checkFileName(token);
4105 case TokenNameNamespace:
4107 checkNameSpaceName();
4109 case TokenNameconst:
4117 * parse and check the namespace name
4119 * @param namespaceToken
4121 private void checkNameSpaceName(){
4124 if (token == TokenNameSEMICOLON) {
4132 * Parse and check the include file name
4134 * @param includeToken
4136 private void checkFileName(int includeToken) {
4137 // <include-token> expr
4138 int start = scanner.getCurrentTokenStartPosition();
4139 boolean hasLPAREN = false;
4141 if (token == TokenNameLPAREN) {
4145 Expression expression = expr();
4147 if (token == TokenNameRPAREN) {
4150 throwSyntaxError("')' expected for keyword '"
4151 + scanner.toStringAction(includeToken) + "'");
4154 char[] currTokenSource = scanner.getCurrentTokenSource(start);
4156 if (scanner.compilationUnit != null) {
4157 IResource resource = scanner.compilationUnit.getResource();
4158 if (resource != null && resource instanceof IFile) {
4159 file = (IFile) resource;
4163 tokens = new char[1][];
4164 tokens[0] = currTokenSource;
4166 ImportReference impt = new ImportReference(tokens, currTokenSource,
4167 start, scanner.getCurrentTokenEndPosition(), false);
4168 impt.declarationSourceEnd = impt.sourceEnd;
4169 impt.declarationEnd = impt.declarationSourceEnd;
4170 // endPosition is just before the ;
4171 impt.declarationSourceStart = start;
4172 includesList.add(impt);
4174 if (expression instanceof StringLiteral) {
4175 StringLiteral literal = (StringLiteral) expression;
4176 char[] includeName = literal.source();
4177 if (includeName.length == 0) {
4178 reportSyntaxError("Empty filename after keyword '"
4179 + scanner.toStringAction(includeToken) + "'",
4180 literal.sourceStart, literal.sourceStart + 1);
4182 String includeNameString = new String(includeName);
4183 if (literal instanceof StringLiteralDQ) {
4184 if (includeNameString.indexOf('$') >= 0) {
4185 // assuming that the filename contains a variable => no
4190 if (includeNameString.startsWith("http://")) {
4191 // assuming external include location
4195 // check the filename:
4196 // System.out.println(new
4197 // String(compilationUnit.getFileName())+" - "+
4198 // expression.toStringExpression());
4199 IProject project = file.getProject();
4200 if (project != null) {
4201 IPath path = PHPFileUtil.determineFilePath(
4202 includeNameString, file, project);
4205 // SyntaxError: "File: << >> doesn't exist in project."
4206 String[] args = { expression.toStringExpression(),
4207 project.getFullPath().toString() };
4208 problemReporter.phpIncludeNotExistWarning(args,
4209 literal.sourceStart, literal.sourceEnd,
4211 compilationUnit.compilationResult);
4214 String filePath = path.toString();
4215 String ext = file.getRawLocation()
4216 .getFileExtension();
4217 int fileExtensionLength = ext == null ? 0 : ext
4220 IFile f = PHPFileUtil.createFile(path, project);
4222 impt.tokens = CharOperation.splitOn('/', filePath
4223 .toCharArray(), 0, filePath.length()
4224 - fileExtensionLength);
4226 } catch (Exception e) {
4227 // the file is outside of the workspace
4235 private void isset_variables() {
4237 // | isset_variables ','
4238 if (token == TokenNameRPAREN) {
4239 throwSyntaxError("Variable expected after keyword 'isset'");
4242 variable(true, false);
4243 if (token == TokenNameCOMMA) {
4251 private boolean common_scalar() {
4255 // | T_CONSTANT_ENCAPSED_STRING
4262 case TokenNameIntegerLiteral:
4265 case TokenNameDoubleLiteral:
4268 case TokenNameStringDoubleQuote:
4271 case TokenNameStringSingleQuote:
4274 case TokenNameStringInterpolated:
4283 case TokenNameCLASS_C:
4286 case TokenNameMETHOD_C:
4289 case TokenNameFUNC_C:
4296 private void scalar() {
4299 // | T_STRING_VARNAME
4302 // | '"' encaps_list '"'
4303 // | '\'' encaps_list '\''
4304 // | T_START_HEREDOC encaps_list T_END_HEREDOC
4305 throwSyntaxError("Not yet implemented (scalar).");
4308 private void static_scalar() {
4309 // static_scalar: /* compile-time evaluated scalars */
4312 // | '+' static_scalar
4313 // | '-' static_scalar
4314 // | T_ARRAY '(' static_array_pair_list ')'
4315 // | static_class_constant
4316 if (common_scalar()) {
4320 case TokenNameIdentifier:
4322 // static_class_constant:
4323 // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
4324 if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
4326 if (token == TokenNameIdentifier) {
4329 throwSyntaxError("Identifier expected after '::' operator.");
4333 case TokenNameEncapsedString0:
4335 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4336 while (scanner.currentCharacter != '`') {
4337 if (scanner.currentCharacter == '\\') {
4338 scanner.currentPosition++;
4340 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4343 } catch (IndexOutOfBoundsException e) {
4344 throwSyntaxError("'`' expected at end of static string.");
4347 // case TokenNameEncapsedString1:
4349 // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4350 // while (scanner.currentCharacter != '\'') {
4351 // if (scanner.currentCharacter == '\\') {
4352 // scanner.currentPosition++;
4354 // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4357 // } catch (IndexOutOfBoundsException e) {
4358 // throwSyntaxError("'\'' expected at end of static string.");
4361 // case TokenNameEncapsedString2:
4363 // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4364 // while (scanner.currentCharacter != '"') {
4365 // if (scanner.currentCharacter == '\\') {
4366 // scanner.currentPosition++;
4368 // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
4371 // } catch (IndexOutOfBoundsException e) {
4372 // throwSyntaxError("'\"' expected at end of static string.");
4375 case TokenNameStringSingleQuote:
4378 case TokenNameStringDoubleQuote:
4385 case TokenNameMINUS:
4389 case TokenNamearray:
4391 if (token != TokenNameLPAREN) {
4392 throwSyntaxError("'(' expected after keyword 'array'");
4395 if (token == TokenNameRPAREN) {
4399 non_empty_static_array_pair_list();
4400 if (token != TokenNameRPAREN) {
4401 throwSyntaxError("')' or ',' expected after keyword 'array'");
4405 // case TokenNamenull :
4408 // case TokenNamefalse :
4411 // case TokenNametrue :
4415 throwSyntaxError("Static scalar/constant expected.");
4419 private void non_empty_static_array_pair_list() {
4420 // non_empty_static_array_pair_list:
4421 // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
4423 // | non_empty_static_array_pair_list ',' static_scalar
4424 // | static_scalar T_DOUBLE_ARROW static_scalar
4428 if (token == TokenNameEQUAL_GREATER) {
4432 if (token != TokenNameCOMMA) {
4436 if (token == TokenNameRPAREN) {
4442 // public void reportSyntaxError() { //int act, int currentKind, int
4443 // // stateStackTop) {
4444 // /* remember current scanner position */
4445 // int startPos = scanner.startPosition;
4446 // int currentPos = scanner.currentPosition;
4448 // this.checkAndReportBracketAnomalies(problemReporter());
4449 // /* reset scanner where it was */
4450 // scanner.startPosition = startPos;
4451 // scanner.currentPosition = currentPos;
4454 public static final int RoundBracket = 0;
4456 public static final int SquareBracket = 1;
4458 public static final int CurlyBracket = 2;
4460 public static final int BracketKinds = 3;
4462 protected int[] nestedMethod; // the ptr is nestedType
4464 protected int nestedType, dimensions;
4466 // variable set stack
4467 final static int VariableStackIncrement = 10;
4469 HashMap fTypeVariables = null;
4471 HashMap fMethodVariables = null;
4473 ArrayList fStackUnassigned = new ArrayList();
4476 final static int AstStackIncrement = 100;
4478 protected int astPtr;
4480 protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
4482 protected int astLengthPtr;
4484 protected int[] astLengthStack;
4486 ASTNode[] noAstNodes = new ASTNode[AstStackIncrement];
4488 public CompilationUnitDeclaration compilationUnit; /*
4493 protected ReferenceContext referenceContext;
4495 protected ProblemReporter problemReporter;
4497 protected CompilerOptions options;
4499 private ArrayList includesList;
4501 // protected CompilationResult compilationResult;
4503 * Returns this parser's problem reporter initialized with its reference
4504 * context. Also it is assumed that a problem is going to be reported, so
4505 * initializes the compilation result's line positions.
4507 public ProblemReporter problemReporter() {
4508 if (scanner.recordLineSeparator) {
4509 compilationUnit.compilationResult.lineSeparatorPositions = scanner
4512 problemReporter.referenceContext = referenceContext;
4513 return problemReporter;
4517 * Reconsider the entire source looking for inconsistencies in {} () []
4519 // public boolean checkAndReportBracketAnomalies(ProblemReporter
4520 // problemReporter) {
4521 // scanner.wasAcr = false;
4522 // boolean anomaliesDetected = false;
4524 // char[] source = scanner.source;
4525 // int[] leftCount = { 0, 0, 0 };
4526 // int[] rightCount = { 0, 0, 0 };
4527 // int[] depths = { 0, 0, 0 };
4528 // int[][] leftPositions = new int[][] { new int[10], new int[10], new
4531 // int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10]
4533 // int[][] rightPositions = new int[][] { new int[10], new int[10], new
4535 // int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10]
4537 // scanner.currentPosition = scanner.initialPosition; //starting
4539 // // (first-zero-based
4541 // while (scanner.currentPosition < scanner.eofPosition) { //loop for
4546 // // ---------Consume white space and handles
4547 // // startPosition---------
4548 // boolean isWhiteSpace;
4550 // scanner.startPosition = scanner.currentPosition;
4551 // // if (((scanner.currentCharacter =
4552 // // source[scanner.currentPosition++]) == '\\') &&
4553 // // (source[scanner.currentPosition] == 'u')) {
4554 // // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
4556 // if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') ||
4557 // (scanner.currentCharacter == '\n'))) {
4558 // if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
4559 // // only record line positions we have not
4561 // scanner.pushLineSeparator();
4564 // isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
4566 // } while (isWhiteSpace && (scanner.currentPosition <
4567 // scanner.eofPosition));
4568 // // -------consume token until } is found---------
4569 // switch (scanner.currentCharacter) {
4571 // int index = leftCount[CurlyBracket]++;
4572 // if (index == leftPositions[CurlyBracket].length) {
4573 // System.arraycopy(leftPositions[CurlyBracket], 0,
4574 // (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
4575 // System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] =
4576 // new int[index * 2]), 0, index);
4578 // leftPositions[CurlyBracket][index] = scanner.startPosition;
4579 // leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
4583 // int index = rightCount[CurlyBracket]++;
4584 // if (index == rightPositions[CurlyBracket].length) {
4585 // System.arraycopy(rightPositions[CurlyBracket], 0,
4586 // (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
4587 // System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket]
4589 // new int[index * 2]), 0, index);
4591 // rightPositions[CurlyBracket][index] = scanner.startPosition;
4592 // rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
4596 // int index = leftCount[RoundBracket]++;
4597 // if (index == leftPositions[RoundBracket].length) {
4598 // System.arraycopy(leftPositions[RoundBracket], 0,
4599 // (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
4600 // System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] =
4601 // new int[index * 2]), 0, index);
4603 // leftPositions[RoundBracket][index] = scanner.startPosition;
4604 // leftDepths[RoundBracket][index] = depths[RoundBracket]++;
4608 // int index = rightCount[RoundBracket]++;
4609 // if (index == rightPositions[RoundBracket].length) {
4610 // System.arraycopy(rightPositions[RoundBracket], 0,
4611 // (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
4612 // System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket]
4614 // new int[index * 2]), 0, index);
4616 // rightPositions[RoundBracket][index] = scanner.startPosition;
4617 // rightDepths[RoundBracket][index] = --depths[RoundBracket];
4621 // int index = leftCount[SquareBracket]++;
4622 // if (index == leftPositions[SquareBracket].length) {
4623 // System.arraycopy(leftPositions[SquareBracket], 0,
4624 // (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
4625 // System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket]
4627 // new int[index * 2]), 0, index);
4629 // leftPositions[SquareBracket][index] = scanner.startPosition;
4630 // leftDepths[SquareBracket][index] = depths[SquareBracket]++;
4634 // int index = rightCount[SquareBracket]++;
4635 // if (index == rightPositions[SquareBracket].length) {
4636 // System.arraycopy(rightPositions[SquareBracket], 0,
4637 // (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
4638 // System.arraycopy(rightDepths[SquareBracket], 0,
4639 // (rightDepths[SquareBracket]
4640 // = new int[index * 2]), 0, index);
4642 // rightPositions[SquareBracket][index] = scanner.startPosition;
4643 // rightDepths[SquareBracket][index] = --depths[SquareBracket];
4647 // if (scanner.getNextChar('\\')) {
4648 // scanner.scanEscapeCharacter();
4649 // } else { // consume next character
4650 // scanner.unicodeAsBackSlash = false;
4651 // // if (((scanner.currentCharacter =
4652 // // source[scanner.currentPosition++]) ==
4654 // // (source[scanner.currentPosition] ==
4656 // // scanner.getNextUnicodeChar();
4658 // if (scanner.withoutUnicodePtr != 0) {
4659 // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
4660 // scanner.currentCharacter;
4664 // scanner.getNextChar('\'');
4668 // // consume next character
4669 // scanner.unicodeAsBackSlash = false;
4670 // // if (((scanner.currentCharacter =
4671 // // source[scanner.currentPosition++]) == '\\') &&
4672 // // (source[scanner.currentPosition] == 'u')) {
4673 // // scanner.getNextUnicodeChar();
4675 // if (scanner.withoutUnicodePtr != 0) {
4676 // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
4677 // scanner.currentCharacter;
4680 // while (scanner.currentCharacter != '"') {
4681 // if (scanner.currentCharacter == '\r') {
4682 // if (source[scanner.currentPosition] == '\n')
4683 // scanner.currentPosition++;
4684 // break; // the string cannot go further that
4687 // if (scanner.currentCharacter == '\n') {
4688 // break; // the string cannot go further that
4691 // if (scanner.currentCharacter == '\\') {
4692 // scanner.scanEscapeCharacter();
4694 // // consume next character
4695 // scanner.unicodeAsBackSlash = false;
4696 // // if (((scanner.currentCharacter =
4697 // // source[scanner.currentPosition++]) == '\\')
4698 // // && (source[scanner.currentPosition] == 'u'))
4700 // // scanner.getNextUnicodeChar();
4702 // if (scanner.withoutUnicodePtr != 0) {
4703 // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
4704 // scanner.currentCharacter;
4711 // if ((test = scanner.getNextChar('/', '*')) == 0) { //line
4713 // //get the next char
4714 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
4716 // && (source[scanner.currentPosition] == 'u')) {
4717 // //-------------unicode traitement
4719 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4720 // scanner.currentPosition++;
4721 // while (source[scanner.currentPosition] == 'u') {
4722 // scanner.currentPosition++;
4724 // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
4726 // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
4729 // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
4732 // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
4734 // || c4 < 0) { //error
4738 // scanner.currentCharacter = 'A';
4739 // } //something different from \n and \r
4741 // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4744 // while (scanner.currentCharacter != '\r' && scanner.currentCharacter !=
4746 // //get the next char
4747 // scanner.startPosition = scanner.currentPosition;
4748 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
4750 // && (source[scanner.currentPosition] == 'u')) {
4751 // //-------------unicode traitement
4753 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4754 // scanner.currentPosition++;
4755 // while (source[scanner.currentPosition] == 'u') {
4756 // scanner.currentPosition++;
4758 // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
4760 // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
4763 // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
4766 // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
4768 // || c4 < 0) { //error
4772 // scanner.currentCharacter = 'A';
4773 // } //something different from \n
4776 // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4780 // if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') ||
4781 // (scanner.currentCharacter == '\n'))) {
4782 // if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
4783 // // only record line positions we
4784 // // have not recorded yet
4785 // scanner.pushLineSeparator();
4786 // if (this.scanner.taskTags != null) {
4787 // this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(),
4789 // .getCurrentTokenEndPosition());
4795 // if (test > 0) { //traditional and annotation
4797 // boolean star = false;
4798 // // consume next character
4799 // scanner.unicodeAsBackSlash = false;
4800 // // if (((scanner.currentCharacter =
4801 // // source[scanner.currentPosition++]) ==
4803 // // (source[scanner.currentPosition] ==
4805 // // scanner.getNextUnicodeChar();
4807 // if (scanner.withoutUnicodePtr != 0) {
4808 // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
4809 // scanner.currentCharacter;
4812 // if (scanner.currentCharacter == '*') {
4815 // //get the next char
4816 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
4818 // && (source[scanner.currentPosition] == 'u')) {
4819 // //-------------unicode traitement
4821 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4822 // scanner.currentPosition++;
4823 // while (source[scanner.currentPosition] == 'u') {
4824 // scanner.currentPosition++;
4826 // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
4828 // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
4831 // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
4834 // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
4836 // || c4 < 0) { //error
4840 // scanner.currentCharacter = 'A';
4841 // } //something different from * and /
4843 // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4846 // //loop until end of comment */
4847 // while ((scanner.currentCharacter != '/') || (!star)) {
4848 // star = scanner.currentCharacter == '*';
4850 // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
4852 // && (source[scanner.currentPosition] == 'u')) {
4853 // //-------------unicode traitement
4855 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4856 // scanner.currentPosition++;
4857 // while (source[scanner.currentPosition] == 'u') {
4858 // scanner.currentPosition++;
4860 // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
4862 // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
4865 // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
4868 // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
4870 // || c4 < 0) { //error
4874 // scanner.currentCharacter = 'A';
4875 // } //something different from * and
4878 // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4882 // if (this.scanner.taskTags != null) {
4883 // this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(),
4884 // this.scanner.getCurrentTokenEndPosition());
4891 // if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
4892 // scanner.scanIdentifierOrKeyword(false);
4895 // if (Character.isDigit(scanner.currentCharacter)) {
4896 // scanner.scanNumber(false);
4900 // //-----------------end switch while
4901 // // try--------------------
4902 // } catch (IndexOutOfBoundsException e) {
4903 // break; // read until EOF
4904 // } catch (InvalidInputException e) {
4905 // return false; // no clue
4908 // if (scanner.recordLineSeparator) {
4909 // compilationUnit.compilationResult.lineSeparatorPositions =
4910 // scanner.getLineEnds();
4912 // // check placement anomalies against other kinds of brackets
4913 // for (int kind = 0; kind < BracketKinds; kind++) {
4914 // for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
4915 // int start = leftPositions[kind][leftIndex]; // deepest
4917 // // find matching closing bracket
4918 // int depth = leftDepths[kind][leftIndex];
4920 // for (int i = 0; i < rightCount[kind]; i++) {
4921 // int pos = rightPositions[kind][i];
4922 // // want matching bracket further in source with same
4924 // if ((pos > start) && (depth == rightDepths[kind][i])) {
4929 // if (end < 0) { // did not find a good closing match
4930 // problemReporter.unmatchedBracket(start, referenceContext,
4931 // compilationUnit.compilationResult);
4934 // // check if even number of opening/closing other brackets
4935 // // in between this pair of brackets
4937 // for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds);
4939 // for (int i = 0; i < leftCount[otherKind]; i++) {
4940 // int pos = leftPositions[otherKind][i];
4941 // if ((pos > start) && (pos < end))
4944 // for (int i = 0; i < rightCount[otherKind]; i++) {
4945 // int pos = rightPositions[otherKind][i];
4946 // if ((pos > start) && (pos < end))
4949 // if (balance != 0) {
4950 // problemReporter.unmatchedBracket(start, referenceContext,
4951 // compilationUnit.compilationResult); //bracket
4957 // // too many opening brackets ?
4958 // for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
4959 // anomaliesDetected = true;
4960 // problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i
4962 // 1], referenceContext,
4963 // compilationUnit.compilationResult);
4965 // // too many closing brackets ?
4966 // for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
4967 // anomaliesDetected = true;
4968 // problemReporter.unmatchedBracket(rightPositions[kind][i],
4969 // referenceContext,
4970 // compilationUnit.compilationResult);
4972 // if (anomaliesDetected)
4975 // return anomaliesDetected;
4976 // } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
4977 // return anomaliesDetected;
4978 // } catch (NullPointerException e) { // jdk1.2.2 jit bug
4979 // return anomaliesDetected;
4982 protected void pushOnAstLengthStack(int pos) {
4984 astLengthStack[++astLengthPtr] = pos;
4985 } catch (IndexOutOfBoundsException e) {
4986 int oldStackLength = astLengthStack.length;
4987 int[] oldPos = astLengthStack;
4988 astLengthStack = new int[oldStackLength + StackIncrement];
4989 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
4990 astLengthStack[astLengthPtr] = pos;
4994 protected void pushOnAstStack(ASTNode node) {
4996 * add a new obj on top of the ast stack
4999 astStack[++astPtr] = node;
5000 } catch (IndexOutOfBoundsException e) {
5001 int oldStackLength = astStack.length;
5002 ASTNode[] oldStack = astStack;
5003 astStack = new ASTNode[oldStackLength + AstStackIncrement];
5004 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
5005 astPtr = oldStackLength;
5006 astStack[astPtr] = node;
5009 astLengthStack[++astLengthPtr] = 1;
5010 } catch (IndexOutOfBoundsException e) {
5011 int oldStackLength = astLengthStack.length;
5012 int[] oldPos = astLengthStack;
5013 astLengthStack = new int[oldStackLength + AstStackIncrement];
5014 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
5015 astLengthStack[astLengthPtr] = 1;
5019 protected void resetModifiers() {
5020 this.modifiers = AccDefault;
5021 this.modifiersSourceStart = -1; // <-- see comment into
5022 // modifiersFlag(int)
5023 this.scanner.commentPtr = -1;
5026 protected void consumePackageDeclarationName(IFile file) {
5027 // create a package name similar to java package names
5028 String projectPath = ProjectPrefUtil.getDocumentRoot(file.getProject())
5030 String filePath = file.getFullPath().toString();
5032 String ext = file.getFileExtension();
5033 int fileExtensionLength = ext == null ? 0 : ext.length() + 1;
5034 ImportReference impt;
5036 if (filePath.startsWith(projectPath)) {
5037 tokens = CharOperation.splitOn('/', filePath.toCharArray(),
5038 projectPath.length() + 1, filePath.length()
5039 - fileExtensionLength);
5041 String name = file.getName();
5042 tokens = new char[1][];
5043 tokens[0] = name.substring(0, name.length() - fileExtensionLength)
5047 this.compilationUnit.currentPackage = impt = new ImportReference(
5048 tokens, new char[0], 0, 0, true);
5050 impt.declarationSourceStart = 0;
5051 impt.declarationSourceEnd = 0;
5052 impt.declarationEnd = 0;
5053 // endPosition is just before the ;
5057 public final static String[] GLOBALS = { "$this", "$_COOKIE", "$_ENV",
5058 "$_FILES", "$_GET", "$GLOBALS", "$_POST", "$_REQUEST", "$_SESSION",
5064 private void pushFunctionVariableSet() {
5065 HashSet set = new HashSet();
5066 if (fStackUnassigned.isEmpty()) {
5067 for (int i = 0; i < GLOBALS.length; i++) {
5068 set.add(GLOBALS[i]);
5071 fStackUnassigned.add(set);
5074 private void pushIfVariableSet() {
5075 if (!fStackUnassigned.isEmpty()) {
5076 HashSet set = new HashSet();
5077 fStackUnassigned.add(set);
5081 private HashSet removeIfVariableSet() {
5082 if (!fStackUnassigned.isEmpty()) {
5083 return (HashSet) fStackUnassigned
5084 .remove(fStackUnassigned.size() - 1);
5090 * Returns the <i>set of assigned variables </i> returns null if no Set is
5091 * defined at the current scanner position
5093 private HashSet peekVariableSet() {
5094 if (!fStackUnassigned.isEmpty()) {
5095 return (HashSet) fStackUnassigned.get(fStackUnassigned.size() - 1);
5101 * add the current identifier source to the <i>set of assigned variables
5106 private void addVariableSet(HashSet set) {
5108 set.add(new String(scanner.getCurrentTokenSource()));
5113 * add the current identifier source to the <i>set of assigned variables
5117 private void addVariableSet() {
5118 HashSet set = peekVariableSet();
5120 set.add(new String(scanner.getCurrentTokenSource()));
5125 * add the current identifier source to the <i>set of assigned variables
5129 private void addVariableSet(char[] token) {
5130 HashSet set = peekVariableSet();
5132 set.add(new String(token));
5137 * check if the current identifier source is in the <i>set of assigned
5138 * variables </i> Returns true, if no set is defined for the current scanner
5142 private boolean containsVariableSet() {
5143 return containsVariableSet(scanner.getCurrentTokenSource());
5146 private boolean containsVariableSet(char[] token) {
5148 if (!fStackUnassigned.isEmpty()) {
5150 String str = new String(token);
5151 for (int i = 0; i < fStackUnassigned.size(); i++) {
5152 set = (HashSet) fStackUnassigned.get(i);
5153 if (set.contains(str)) {