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;
12 import net.sourceforge.phpdt.core.compiler.CharOperation;
13 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
14 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
15 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
16 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
17 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
18 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
19 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
20 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
21 import net.sourceforge.phpdt.internal.compiler.util.Util;
22 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
23 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.AND_AND_Expression;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.BinaryExpression;
28 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
29 import net.sourceforge.phpeclipse.internal.compiler.ast.ConditionalExpression;
30 import net.sourceforge.phpeclipse.internal.compiler.ast.EqualExpression;
31 import net.sourceforge.phpeclipse.internal.compiler.ast.Expression;
32 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
33 import net.sourceforge.phpeclipse.internal.compiler.ast.IfStatement;
34 import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
35 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
36 import net.sourceforge.phpeclipse.internal.compiler.ast.OR_OR_Expression;
37 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
38 import net.sourceforge.phpeclipse.internal.compiler.ast.Statement;
39 import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteral;
40 import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralDQ;
41 import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralSQ;
42 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
44 import org.eclipse.core.resources.IFile;
45 import org.eclipse.core.resources.IProject;
46 import org.eclipse.core.resources.IResource;
47 import org.eclipse.core.runtime.IPath;
49 public class Parser //extends PHPParserSuperclass
50 implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
51 //internal data for the automat
52 protected final static int StackIncrement = 255;
54 protected int stateStackTop;
56 protected int[] stack = new int[StackIncrement];
58 public int firstToken; // handle for multiple parsing goals
60 public int lastAct; //handle for multiple parsing goals
62 protected RecoveredElement currentElement;
64 public static boolean VERBOSE_RECOVERY = false;
66 protected boolean diet = false; //tells the scanner to jump over some
68 // parts of the code/expressions like
71 public Scanner scanner;
73 private ArrayList phpList;
75 private int currentPHPString;
77 private boolean phpEnd;
79 // private static HashMap keywordMap = null;
87 // row counter for syntax errors:
89 // column counter for syntax errors:
93 // // current identifier
99 private String stringValue;
101 /** Contains the current expression. */
102 // private StringBuffer expression;
103 //private boolean phpMode;
104 protected int modifiers;
106 protected int modifiersSourceStart;
108 // protected IdentifierIndexManager indexManager;
110 protected Parser(ProblemReporter problemReporter) {
111 this.problemReporter = problemReporter;
112 this.options = problemReporter.options;
113 this.currentPHPString = 0;
114 // PHPParserSuperclass.fileToParse = fileToParse;
116 // this.indexManager = null;
118 this.token = TokenNameEOF;
120 // this.rowCount = 1;
121 // this.columnCount = 0;
124 this.initializeScanner();
127 public void setFileToParse(IFile fileToParse) {
128 this.currentPHPString = 0;
129 // PHPParserSuperclass.fileToParse = fileToParse;
131 // this.indexManager = null;
133 this.token = TokenNameEOF;
135 this.initializeScanner();
139 * ClassDeclaration Constructor.
143 * Description of Parameter
146 public Parser(IFile fileToParse) {
147 // if (keywordMap == null) {
148 // keywordMap = new HashMap();
149 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
150 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
153 this.currentPHPString = 0;
154 // PHPParserSuperclass.fileToParse = fileToParse;
156 this.includesList = null;
158 this.token = TokenNameEOF;
160 // this.rowCount = 1;
161 // this.columnCount = 0;
164 this.initializeScanner();
167 public void initializeScanner() {
168 this.scanner = new Scanner(false /* comment */, false /* whitespace */, this.options
169 .getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /* nls */, false, false,
170 this.options.taskTags/* taskTags */,
171 this.options.taskPriorites/* taskPriorities */,
172 true/*isTaskCaseSensitive*/);
176 * Create marker for the parse error
178 // private void setMarker(String message, int charStart, int charEnd, int
180 // setMarker(fileToParse, message, charStart, charEnd, errorLevel);
183 * This method will throw the SyntaxError. It will add the good lines and columns to the Error
187 * @throws SyntaxError
190 private void throwSyntaxError(String error) {
191 int problemStartPosition = scanner.getCurrentTokenStartPosition();
192 int problemEndPosition = scanner.getCurrentTokenEndPosition();
193 throwSyntaxError(error, problemStartPosition, problemEndPosition + 1);
197 * This method will throw the SyntaxError. It will add the good lines and columns to the Error
201 * @throws SyntaxError
204 // private void throwSyntaxError(String error, int startRow) {
205 // throw new SyntaxError(startRow, 0, " ", error);
207 private void throwSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
208 problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
209 compilationUnit.compilationResult);
210 throw new SyntaxError(1, 0, " ", error);
213 private void reportSyntaxError(String error) {
214 int problemStartPosition = scanner.getCurrentTokenStartPosition();
215 int problemEndPosition = scanner.getCurrentTokenEndPosition();
216 reportSyntaxError(error, problemStartPosition, problemEndPosition + 1);
219 private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
220 problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
221 compilationUnit.compilationResult);
224 private void reportSyntaxWarning(String error, int problemStartPosition, int problemEndPosition) {
225 problemReporter.phpParsingWarning(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
226 compilationUnit.compilationResult);
230 * gets the next token from input
232 private void getNextToken() {
234 token = scanner.getNextToken();
236 int currentEndPosition = scanner.getCurrentTokenEndPosition();
237 int currentStartPosition = scanner.getCurrentTokenStartPosition();
238 System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
239 System.out.println(scanner.toStringAction(token));
241 } catch (InvalidInputException e) {
242 token = TokenNameERROR;
243 String detailedMessage = e.getMessage();
245 if (detailedMessage == Scanner.UNTERMINATED_STRING) {
246 throwSyntaxError("Unterminated string.");
247 } else if (detailedMessage == Scanner.UNTERMINATED_COMMENT) {
248 throwSyntaxError("Unterminated commment.");
254 public void init(String s) {
256 this.token = TokenNameEOF;
258 // this.rowCount = 1;
259 // this.columnCount = 0;
261 // this.phpMode = false;
262 /* scanner initialization */
263 scanner.setSource(s.toCharArray());
264 scanner.setPHPMode(false);
267 protected void initialize(boolean phpMode) {
268 initialize(phpMode, null);
271 protected void initialize(boolean phpMode, IdentifierIndexManager indexManager) {
272 compilationUnit = null;
273 referenceContext = null;
274 includesList = new ArrayList();
275 // this.indexManager = indexManager;
277 this.token = TokenNameEOF;
279 // this.rowCount = 1;
280 // this.columnCount = 0;
282 // this.phpMode = phpMode;
283 scanner.setPHPMode(phpMode);
287 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>'
289 public void parse(String s) {
295 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>'
297 protected void parse() {
301 if (token != TokenNameEOF && token != TokenNameERROR) {
304 if (token != TokenNameEOF) {
305 if (token == TokenNameERROR) {
306 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
308 if (token == TokenNameRPAREN) {
309 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
311 if (token == TokenNameRBRACE) {
312 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
314 if (token == TokenNameRBRACKET) {
315 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
317 if (token == TokenNameLPAREN) {
318 throwSyntaxError("Read character '('; end-of-file not reached.");
320 if (token == TokenNameLBRACE) {
321 throwSyntaxError("Read character '{'; end-of-file not reached.");
323 if (token == TokenNameLBRACKET) {
324 throwSyntaxError("Read character '['; end-of-file not reached.");
326 throwSyntaxError("End-of-file not reached.");
329 } catch (SyntaxError sytaxErr1) {
330 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(),
332 // setMarker(sytaxErr1.getMessage(),
333 // scanner.getCurrentTokenStartPosition(),
334 // scanner.getCurrentTokenEndPosition(), ERROR);
336 // if an error occured,
337 // try to find keywords 'class' or 'function'
338 // to parse the rest of the string
339 while (token != TokenNameEOF && token != TokenNameERROR) {
340 if (token == TokenNameabstract || token == TokenNamefinal || token == TokenNameclass || token == TokenNamefunction) {
345 if (token == TokenNameEOF || token == TokenNameERROR) {
348 } catch (SyntaxError sytaxErr2) {
349 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(),
351 // setMarker(sytaxErr2.getMessage(),
352 // scanner.getCurrentTokenStartPosition(),
353 // scanner.getCurrentTokenEndPosition(), ERROR);
362 protected CompilationUnitDeclaration endParse(int act) {
366 if (currentElement != null) {
367 currentElement.topElement().updateParseTree();
368 if (VERBOSE_RECOVERY) {
369 System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
370 System.out.println("--------------------------"); //$NON-NLS-1$
371 System.out.println(compilationUnit);
372 System.out.println("----------------------------------"); //$NON-NLS-1$
375 if (diet & VERBOSE_RECOVERY) {
376 System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
377 System.out.println("--------------------------"); //$NON-NLS-1$
378 System.out.println(compilationUnit);
379 System.out.println("----------------------------------"); //$NON-NLS-1$
382 if (scanner.recordLineSeparator) {
383 compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
385 if (scanner.taskTags != null) {
386 for (int i = 0; i < scanner.foundTaskCount; i++) {
387 problemReporter().task(new String(scanner.foundTaskTags[i]), new String(scanner.foundTaskMessages[i]),
388 scanner.foundTaskPriorities[i] == null ? null : new String(scanner.foundTaskPriorities[i]),
389 scanner.foundTaskPositions[i][0], scanner.foundTaskPositions[i][1]);
392 compilationUnit.imports = new ImportReference[includesList.size()];
393 for (int i = 0; i < includesList.size(); i++) {
394 compilationUnit.imports[i] = (ImportReference) includesList.get(i);
396 return compilationUnit;
399 // public PHPOutlineInfo parseInfo(Object parent, String s) {
400 // PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
401 // // Stack stack = new Stack();
402 // // stack.push(outlineInfo.getDeclarations());
404 // this.token = TokenNameEOF;
405 // // this.chIndx = 0;
406 // // this.rowCount = 1;
407 // // this.columnCount = 0;
408 // this.phpEnd = false;
409 // this.phpMode = false;
410 // scanner.setSource(s.toCharArray());
411 // scanner.setPHPMode(false);
414 // parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
416 // return outlineInfo;
418 private boolean isVariable() {
419 return token == TokenNameVariable; // || token == TokenNamethis;
422 // private void parseDeclarations(PHPOutlineInfo outlineInfo,
423 // OutlineableWithChildren current, boolean goBack) {
425 // // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
426 // PHPSegmentWithChildren temp;
428 // IPreferenceStore store =
429 // PHPeclipsePlugin.getDefault().getPreferenceStore();
431 // while (token != TokenNameEOF && token != TokenNameERROR) {
432 // if (token == TokenNameVariable) {
433 // ident = scanner.getCurrentIdentifierSource();
434 // outlineInfo.addVariable(new String(ident));
436 // } else if (token == TokenNamevar) {
438 // if (token == TokenNameVariable
439 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
440 // ident = scanner.getCurrentIdentifierSource();
441 // //substring(1) added because PHPVarDeclaration doesn't
442 // // need the $ anymore
443 // String variableName = new String(ident).substring(1);
444 // outlineInfo.addVariable(variableName);
446 // if (token != TokenNameSEMICOLON) {
448 // ident = scanner.getCurrentTokenSource();
449 // if (token > TokenNameKEYWORD) {
450 // current.add(new PHPVarDeclaration(current, variableName,
451 // // chIndx - ident.length,
452 // scanner.getCurrentTokenStartPosition(), new String(ident)));
455 // case TokenNameVariable :
456 // case TokenNamethis :
457 // current.add(new PHPVarDeclaration(current, variableName,
460 // scanner.getCurrentTokenStartPosition(), new String(
463 // case TokenNameIdentifier :
464 // current.add(new PHPVarDeclaration(current, variableName,
467 // scanner.getCurrentTokenStartPosition(), new String(
470 // case TokenNameDoubleLiteral :
471 // current.add(new PHPVarDeclaration(current, variableName
475 // scanner.getCurrentTokenStartPosition(), new String(
478 // case TokenNameIntegerLiteral :
479 // current.add(new PHPVarDeclaration(current, variableName,
482 // scanner.getCurrentTokenStartPosition(), new String(
485 // case TokenNameStringInterpolated :
486 // case TokenNameStringLiteral :
487 // current.add(new PHPVarDeclaration(current, variableName,
490 // scanner.getCurrentTokenStartPosition(), new String(
493 // case TokenNameStringConstant :
494 // current.add(new PHPVarDeclaration(current, variableName,
497 // scanner.getCurrentTokenStartPosition(), new String(
501 // current.add(new PHPVarDeclaration(current, variableName,
504 // scanner.getCurrentTokenStartPosition()));
509 // ident = scanner.getCurrentIdentifierSource();
510 // current.add(new PHPVarDeclaration(current, variableName,
511 // // chIndx - ident.length
512 // scanner.getCurrentTokenStartPosition()));
515 // } else if (token == TokenNamefunction) {
517 // if (token == TokenNameAND) {
520 // if (token == TokenNameIdentifier
521 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
522 // ident = scanner.getCurrentIdentifierSource();
523 // outlineInfo.addVariable(new String(ident));
524 // temp = new PHPFunctionDeclaration(current, new String(ident),
525 // // chIndx - ident.length
526 // scanner.getCurrentTokenStartPosition());
527 // current.add(temp);
529 // parseDeclarations(outlineInfo, temp, true);
531 // } else if (token == TokenNameclass) {
533 // if (token == TokenNameIdentifier
534 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
535 // ident = scanner.getCurrentIdentifierSource();
536 // outlineInfo.addVariable(new String(ident));
537 // temp = new PHPClassDeclaration(current, new String(ident),
538 // // chIndx - ident.len
539 // scanner.getCurrentTokenStartPosition());
540 // current.add(temp);
541 // // stack.push(temp);
543 // //skip tokens for classname, extends and others until
544 // // we have the opening '{'
545 // while (token != TokenNameLBRACE && token != TokenNameEOF
546 // && token != TokenNameERROR) {
549 // parseDeclarations(outlineInfo, temp, true);
552 // } else if ((token == TokenNameLBRACE)
553 // || (token == TokenNameDOLLAR_LBRACE)) {
556 // } else if (token == TokenNameRBRACE) {
559 // if (counter == 0 && goBack) {
562 // } else if (token == TokenNamerequire || token == TokenNamerequire_once
563 // || token == TokenNameinclude || token == TokenNameinclude_once) {
564 // ident = scanner.getCurrentTokenSource();
566 // int startPosition = scanner.getCurrentTokenStartPosition();
568 // char[] expr = scanner.getCurrentTokenSource(startPosition);
569 // outlineInfo.addVariable(new String(ident));
570 // current.add(new PHPReqIncDeclaration(current, new String(ident),
571 // // chIndx - ident.length,
572 // startPosition, new String(expr)));
578 // } catch (SyntaxError sytaxErr) {
580 // // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
581 // // setMarker(sytaxErr.getMessage(),
582 // // scanner.getCurrentTokenStartPosition(),
583 // // scanner.getCurrentTokenEndPosition(), ERROR);
584 // // } catch (CoreException e) {
588 private void statementList() {
590 statement(TokenNameEOF);
591 if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse)
592 || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor)
593 || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch)
594 || (token == TokenNameenddeclare) || (token == TokenNameEOF) || (token == TokenNameERROR)) {
600 private void functionBody(MethodDeclaration methodDecl) {
601 // '{' [statement-list] '}'
602 if (token == TokenNameLBRACE) {
605 throwSyntaxError("'{' expected in compound-statement.");
607 if (token != TokenNameRBRACE) {
610 if (token == TokenNameRBRACE) {
611 methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
614 throwSyntaxError("'}' expected in compound-statement.");
618 private Statement statement(int previousToken) {
619 Statement statement = null;
620 Expression expression;
621 int sourceStart = scanner.getCurrentTokenStartPosition();
622 if (token == TokenNameif) {
624 if (token == TokenNameLPAREN) {
627 throwSyntaxError("'(' expected after 'if' keyword.");
630 if (token == TokenNameRPAREN) {
633 throwSyntaxError("')' expected after 'if' condition.");
636 return new IfStatement(expression, statement, sourceStart, scanner.getCurrentTokenEndPosition());
637 } else if (token == TokenNameswitch) {
639 if (token == TokenNameLPAREN) {
642 throwSyntaxError("'(' expected after 'switch' keyword.");
645 if (token == TokenNameRPAREN) {
648 throwSyntaxError("')' expected after 'switch' condition.");
652 } else if (token == TokenNamefor) {
654 if (token == TokenNameLPAREN) {
657 throwSyntaxError("'(' expected after 'for' keyword.");
659 if (token == TokenNameSEMICOLON) {
663 if (token == TokenNameSEMICOLON) {
666 throwSyntaxError("';' expected after 'for'.");
669 if (token == TokenNameSEMICOLON) {
673 if (token == TokenNameSEMICOLON) {
676 throwSyntaxError("';' expected after 'for'.");
679 if (token == TokenNameRPAREN) {
683 if (token == TokenNameRPAREN) {
686 throwSyntaxError("')' expected after 'for'.");
691 } else if (token == TokenNamewhile) {
693 if (token == TokenNameLPAREN) {
696 throwSyntaxError("'(' expected after 'while' keyword.");
699 if (token == TokenNameRPAREN) {
702 throwSyntaxError("')' expected after 'while' condition.");
706 } else if (token == TokenNamedo) {
708 if (token == TokenNameLBRACE) {
710 if (token != TokenNameRBRACE) {
713 if (token == TokenNameRBRACE) {
716 throwSyntaxError("'}' expected after 'do' keyword.");
719 statement(TokenNameEOF);
721 if (token == TokenNamewhile) {
723 if (token == TokenNameLPAREN) {
726 throwSyntaxError("'(' expected after 'while' keyword.");
729 if (token == TokenNameRPAREN) {
732 throwSyntaxError("')' expected after 'while' condition.");
735 throwSyntaxError("'while' expected after 'do' keyword.");
737 if (token == TokenNameSEMICOLON) {
740 if (token != TokenNameINLINE_HTML) {
741 throwSyntaxError("';' expected after do-while statement.");
746 } else if (token == TokenNameforeach) {
748 if (token == TokenNameLPAREN) {
751 throwSyntaxError("'(' expected after 'foreach' keyword.");
754 if (token == TokenNameas) {
757 throwSyntaxError("'as' expected after 'foreach' exxpression.");
761 foreach_optional_arg();
762 if (token == TokenNameEQUAL_GREATER) {
766 if (token == TokenNameRPAREN) {
769 throwSyntaxError("')' expected after 'foreach' expression.");
773 } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
775 if (token != TokenNameSEMICOLON) {
778 if (token == TokenNameSEMICOLON) {
781 if (token != TokenNameINLINE_HTML) {
782 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
787 } else if (token == TokenNameecho) {
790 if (token == TokenNameSEMICOLON) {
793 if (token != TokenNameINLINE_HTML) {
794 throwSyntaxError("';' expected after 'echo' statement.");
799 } else if (token == TokenNameINLINE_HTML) {
802 // } else if (token == TokenNameprint) {
805 // if (token == TokenNameSEMICOLON) {
808 // if (token != TokenNameStopPHP) {
809 // throwSyntaxError("';' expected after 'print' statement.");
814 } else if (token == TokenNameglobal) {
817 if (token == TokenNameSEMICOLON) {
820 if (token != TokenNameINLINE_HTML) {
821 throwSyntaxError("';' expected after 'global' statement.");
826 } else if (token == TokenNamestatic) {
829 if (token == TokenNameSEMICOLON) {
832 if (token != TokenNameINLINE_HTML) {
833 throwSyntaxError("';' expected after 'static' statement.");
838 } else if (token == TokenNameunset) {
840 if (token == TokenNameLPAREN) {
843 throwSyntaxError("'(' expected after 'unset' statement.");
846 if (token == TokenNameRPAREN) {
849 throwSyntaxError("')' expected after 'unset' statement.");
851 if (token == TokenNameSEMICOLON) {
854 if (token != TokenNameINLINE_HTML) {
855 throwSyntaxError("';' expected after 'unset' statement.");
860 } else if (token == TokenNamefunction) {
861 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
862 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
863 methodDecl.modifiers = AccDefault;
865 functionDefinition(methodDecl);
867 } else if (token == TokenNamedeclare) {
868 //T_DECLARE '(' declare_list ')' declare_statement
870 if (token != TokenNameLPAREN) {
871 throwSyntaxError("'(' expected in 'declare' statement.");
875 if (token != TokenNameRPAREN) {
876 throwSyntaxError("')' expected in 'declare' statement.");
881 } else if (token == TokenNametry) {
883 if (token != TokenNameLBRACE) {
884 throwSyntaxError("'{' expected in 'try' statement.");
888 if (token != TokenNameRBRACE) {
889 throwSyntaxError("'}' expected in 'try' statement.");
893 } else if (token == TokenNamecatch) {
895 if (token != TokenNameLPAREN) {
896 throwSyntaxError("'(' expected in 'catch' statement.");
899 fully_qualified_class_name();
900 if (token != TokenNameVariable) {
901 throwSyntaxError("Variable expected in 'catch' statement.");
904 if (token != TokenNameRPAREN) {
905 throwSyntaxError("')' expected in 'catch' statement.");
908 if (token != TokenNameLBRACE) {
909 throwSyntaxError("'{' expected in 'catch' statement.");
912 if (token != TokenNameRBRACE) {
914 if (token != TokenNameRBRACE) {
915 throwSyntaxError("'}' expected in 'catch' statement.");
919 additional_catches();
921 } else if (token == TokenNamethrow) {
924 if (token == TokenNameSEMICOLON) {
927 throwSyntaxError("';' expected after 'throw' exxpression.");
930 } else if (token == TokenNamefinal || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) {
931 TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
932 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
933 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
934 typeDecl.name = new char[] { ' ' };
935 // default super class
936 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
937 compilationUnit.types.add(typeDecl);
939 pushOnAstStack(typeDecl);
940 unticked_class_declaration_statement(typeDecl);
941 // classBody(typeDecl);
948 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
949 } else if (token == TokenNameLBRACE) {
951 if (token != TokenNameRBRACE) {
954 if (token == TokenNameRBRACE) {
958 throwSyntaxError("'}' expected.");
961 if (token != TokenNameSEMICOLON) {
964 if (token == TokenNameSEMICOLON) {
968 if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
969 throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
978 private void declare_statement() {
980 //| ':' inner_statement_list T_ENDDECLARE ';'
982 if (token == TokenNameCOLON) {
984 // TODO: implement inner_statement_list();
986 if (token != TokenNameenddeclare) {
987 throwSyntaxError("'enddeclare' expected in 'declare' statement.");
990 if (token != TokenNameSEMICOLON) {
991 throwSyntaxError("';' expected after 'enddeclare' keyword.");
995 statement(TokenNameRPAREN);
999 private void declare_list() {
1000 // T_STRING '=' static_scalar
1001 //| declare_list ',' T_STRING '=' static_scalar
1003 if (token != TokenNameIdentifier) {
1004 throwSyntaxError("Identifier expected in 'declare' list.");
1007 if (token != TokenNameEQUAL) {
1008 throwSyntaxError("'=' expected in 'declare' list.");
1012 if (token != TokenNameCOMMA) {
1019 private void additional_catches() {
1020 while (token == TokenNamecatch) {
1022 if (token != TokenNameLPAREN) {
1023 throwSyntaxError("'(' expected in 'catch' statement.");
1026 fully_qualified_class_name();
1027 if (token != TokenNameVariable) {
1028 throwSyntaxError("Variable expected in 'catch' statement.");
1031 if (token != TokenNameRPAREN) {
1032 throwSyntaxError("')' expected in 'catch' statement.");
1035 if (token != TokenNameLBRACE) {
1036 throwSyntaxError("'{' expected in 'catch' statement.");
1039 if (token != TokenNameRBRACE) {
1042 if (token != TokenNameRBRACE) {
1043 throwSyntaxError("'}' expected in 'catch' statement.");
1049 private void foreach_variable() {
1052 if (token == TokenNameAND) {
1058 private void foreach_optional_arg() {
1060 //| T_DOUBLE_ARROW foreach_variable
1061 if (token == TokenNameEQUAL_GREATER) {
1067 private void global_var_list() {
1069 // global_var_list ',' global_var
1073 if (token != TokenNameCOMMA) {
1080 private void global_var() {
1084 //| '$' '{' expr '}'
1085 if (token == TokenNameVariable) {
1087 } else if (token == TokenNameDOLLAR) {
1089 if (token == TokenNameLPAREN) {
1092 if (token != TokenNameLPAREN) {
1093 throwSyntaxError("')' expected in global variable.");
1102 private void static_var_list() {
1104 // static_var_list ',' T_VARIABLE
1105 //| static_var_list ',' T_VARIABLE '=' static_scalar
1107 //| T_VARIABLE '=' static_scalar
1109 if (token == TokenNameVariable) {
1111 if (token == TokenNameEQUAL) {
1115 if (token != TokenNameCOMMA) {
1125 private void unset_variables() {
1128 // | unset_variables ',' unset_variable
1133 if (token != TokenNameCOMMA) {
1140 private final void initializeModifiers() {
1142 this.modifiersSourceStart = -1;
1145 private final void checkAndSetModifiers(int flag) {
1146 this.modifiers |= flag;
1147 if (this.modifiersSourceStart < 0)
1148 this.modifiersSourceStart = this.scanner.startPosition;
1151 private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1152 initializeModifiers();
1153 if (token == TokenNameinterface) {
1154 // interface_entry T_STRING
1155 // interface_extends_list
1156 // '{' class_statement_list '}'
1157 checkAndSetModifiers(AccInterface);
1159 typeDecl.modifiers = this.modifiers;
1160 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1161 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1162 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1163 typeDecl.name = scanner.getCurrentIdentifierSource();
1164 if (token > TokenNameKEYWORD) {
1165 problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
1166 scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
1167 // throwSyntaxError("Don't use a keyword for interface declaration [" + scanner.toStringAction(token) + "].",
1168 // typeDecl.sourceStart, typeDecl.sourceEnd);
1171 interface_extends_list(typeDecl);
1173 typeDecl.name = new char[] { ' ' };
1174 throwSyntaxError("Interface name expected after keyword 'interface'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1178 // class_entry_type T_STRING extends_from
1180 // '{' class_statement_list'}'
1182 typeDecl.modifiers = this.modifiers;
1183 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1184 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1186 //identifier 'extends' identifier
1187 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1188 typeDecl.name = scanner.getCurrentIdentifierSource();
1189 if (token > TokenNameKEYWORD) {
1190 problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
1191 scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
1192 // throwSyntaxError("Don't use a keyword for class declaration [" + scanner.toStringAction(token) + "].",
1193 // typeDecl.sourceStart, typeDecl.sourceEnd);
1198 // | T_EXTENDS fully_qualified_class_name
1199 if (token == TokenNameextends) {
1200 interface_extends_list(typeDecl);
1202 // if (token != TokenNameIdentifier) {
1203 // throwSyntaxError("Class name expected after keyword
1205 // scanner.getCurrentTokenStartPosition(), scanner
1206 // .getCurrentTokenEndPosition());
1209 implements_list(typeDecl);
1211 typeDecl.name = new char[] { ' ' };
1212 throwSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1216 // '{' class_statement_list '}'
1217 if (token == TokenNameLBRACE) {
1219 if (token != TokenNameRBRACE) {
1220 ArrayList list = new ArrayList();
1221 class_statement_list(list);
1222 typeDecl.fields = new FieldDeclaration[list.size()];
1223 for (int i = 0; i < list.size(); i++) {
1224 typeDecl.fields[i] = (FieldDeclaration) list.get(i);
1227 if (token == TokenNameRBRACE) {
1228 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1231 throwSyntaxError("'}' expected at end of class body.");
1234 throwSyntaxError("'{' expected at start of class body.");
1238 private void class_entry_type() {
1240 // | T_ABSTRACT T_CLASS
1241 // | T_FINAL T_CLASS
1242 if (token == TokenNameclass) {
1244 } else if (token == TokenNameabstract) {
1245 checkAndSetModifiers(AccAbstract);
1247 if (token != TokenNameclass) {
1248 throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1251 } else if (token == TokenNamefinal) {
1252 checkAndSetModifiers(AccFinal);
1254 if (token != TokenNameclass) {
1255 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1259 throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1263 private void class_extends(TypeDeclaration typeDecl) {
1265 // | T_EXTENDS interface_list
1266 if (token == TokenNameextends) {
1269 if (token == TokenNameIdentifier) {
1272 throwSyntaxError("Class name expected after keyword 'extends'.");
1277 private void interface_extends_list(TypeDeclaration typeDecl) {
1279 // | T_EXTENDS interface_list
1280 if (token == TokenNameextends) {
1286 private void implements_list(TypeDeclaration typeDecl) {
1288 // | T_IMPLEMENTS interface_list
1289 if (token == TokenNameimplements) {
1295 private void interface_list() {
1297 // fully_qualified_class_name
1298 //| interface_list ',' fully_qualified_class_name
1300 if (token == TokenNameIdentifier) {
1303 throwSyntaxError("Interface name expected after keyword 'implements'.");
1305 if (token != TokenNameCOMMA) {
1312 // private void classBody(TypeDeclaration typeDecl) {
1313 // //'{' [class-element-list] '}'
1314 // if (token == TokenNameLBRACE) {
1316 // if (token != TokenNameRBRACE) {
1317 // class_statement_list();
1319 // if (token == TokenNameRBRACE) {
1320 // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1323 // throwSyntaxError("'}' expected at end of class body.");
1326 // throwSyntaxError("'{' expected at start of class body.");
1329 private void class_statement_list(ArrayList list) {
1331 class_statement(list);
1332 } while (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic
1333 || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar
1334 || token == TokenNameconst);
1337 private void class_statement(ArrayList list) {
1339 // variable_modifiers class_variable_declaration ';'
1340 // | class_constant_declaration ';'
1341 // | method_modifiers T_FUNCTION is_reference T_STRING
1342 // '(' parameter_list ')' method_body
1343 initializeModifiers();
1344 int declarationSourceStart = scanner.getCurrentTokenStartPosition();
1346 if (token == TokenNamevar) {
1347 checkAndSetModifiers(AccPublic);
1348 problemReporter.phpVarDeprecatedWarning(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
1349 referenceContext, compilationUnit.compilationResult);
1351 class_variable_declaration(declarationSourceStart, list);
1352 } else if (token == TokenNameconst) {
1353 checkAndSetModifiers(AccFinal | AccPublic);
1354 class_constant_declaration(declarationSourceStart, list);
1355 if (token != TokenNameSEMICOLON) {
1356 throwSyntaxError("';' expected after class const declaration.");
1360 boolean hasModifiers = member_modifiers();
1361 if (token == TokenNamefunction) {
1362 if (!hasModifiers) {
1363 checkAndSetModifiers(AccPublic);
1365 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1366 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1367 methodDecl.modifiers = this.modifiers;
1369 functionDefinition(methodDecl);
1371 if (!hasModifiers) {
1372 throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1374 class_variable_declaration(declarationSourceStart, list);
1379 private void class_constant_declaration(int declarationSourceStart, ArrayList list) {
1380 // class_constant_declaration ',' T_STRING '=' static_scalar
1381 // | T_CONST T_STRING '=' static_scalar
1382 if (token != TokenNameconst) {
1383 throwSyntaxError("'const' keyword expected in class declaration.");
1388 if (token != TokenNameIdentifier) {
1389 throwSyntaxError("Identifier expected in class const declaration.");
1391 FieldDeclaration fieldDeclaration = new FieldDeclaration(scanner.getCurrentIdentifierSource(), scanner
1392 .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1393 fieldDeclaration.modifiers = this.modifiers;
1394 fieldDeclaration.declarationSourceStart = declarationSourceStart;
1395 fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1396 fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1397 // fieldDeclaration.type
1398 list.add(fieldDeclaration);
1400 if (token != TokenNameEQUAL) {
1401 throwSyntaxError("'=' expected in class const declaration.");
1405 if (token != TokenNameCOMMA) {
1406 break; // while(true)-loop
1412 // private void variable_modifiers() {
1413 // // variable_modifiers:
1414 // // non_empty_member_modifiers
1416 // initializeModifiers();
1417 // if (token == TokenNamevar) {
1418 // checkAndSetModifiers(AccPublic);
1419 // reportSyntaxError(
1420 // "Keyword 'var' is deprecated. Please use 'public' 'private' or
1422 // modifier for field declarations.",
1423 // scanner.getCurrentTokenStartPosition(), scanner
1424 // .getCurrentTokenEndPosition());
1427 // if (!member_modifiers()) {
1428 // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1429 // field declarations.");
1433 // private void method_modifiers() {
1434 // //method_modifiers:
1436 // //| non_empty_member_modifiers
1437 // initializeModifiers();
1438 // if (!member_modifiers()) {
1439 // checkAndSetModifiers(AccPublic);
1442 private boolean member_modifiers() {
1449 boolean foundToken = false;
1451 if (token == TokenNamepublic) {
1452 checkAndSetModifiers(AccPublic);
1455 } else if (token == TokenNameprotected) {
1456 checkAndSetModifiers(AccProtected);
1459 } else if (token == TokenNameprivate) {
1460 checkAndSetModifiers(AccPrivate);
1463 } else if (token == TokenNamestatic) {
1464 checkAndSetModifiers(AccStatic);
1467 } else if (token == TokenNameabstract) {
1468 checkAndSetModifiers(AccAbstract);
1471 } else if (token == TokenNamefinal) {
1472 checkAndSetModifiers(AccFinal);
1482 private void class_variable_declaration(int declarationSourceStart, ArrayList list) {
1483 // class_variable_declaration:
1484 // class_variable_declaration ',' T_VARIABLE
1485 // | class_variable_declaration ',' T_VARIABLE '=' static_scalar
1487 // | T_VARIABLE '=' static_scalar
1488 char[] classVariable;
1490 if (token == TokenNameVariable) {
1491 classVariable = scanner.getCurrentIdentifierSource();
1492 // indexManager.addIdentifierInformation('v', classVariable, buf, -1, -1);
1493 FieldDeclaration fieldDeclaration = new FieldDeclaration(classVariable, scanner.getCurrentTokenStartPosition(), scanner
1494 .getCurrentTokenEndPosition());
1495 fieldDeclaration.modifiers = this.modifiers;
1496 fieldDeclaration.declarationSourceStart = declarationSourceStart;
1497 fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1498 fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1499 // fieldDeclaration.type
1500 list.add(fieldDeclaration);
1502 if (token == TokenNameEQUAL) {
1507 // if (token == TokenNamethis) {
1508 // throwSyntaxError("'$this' not allowed after keyword 'public'
1509 // 'protected' 'private' 'var'.");
1511 throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
1513 if (token != TokenNameCOMMA) {
1518 if (token != TokenNameSEMICOLON) {
1519 throwSyntaxError("';' expected after field declaration.");
1524 private void functionDefinition(MethodDeclaration methodDecl) {
1525 boolean isAbstract = false;
1527 compilationUnit.types.add(methodDecl);
1529 ASTNode node = astStack[astPtr];
1530 if (node instanceof TypeDeclaration) {
1531 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1532 if (typeDecl.methods == null) {
1533 typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
1535 AbstractMethodDeclaration[] newMethods;
1536 System.arraycopy(typeDecl.methods, 0,
1537 newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 0,
1538 typeDecl.methods.length);
1539 newMethods[typeDecl.methods.length] = methodDecl;
1540 typeDecl.methods = newMethods;
1542 if ((typeDecl.modifiers & AccAbstract) == AccAbstract) {
1544 } else if ((typeDecl.modifiers & AccInterface) == AccInterface) {
1549 functionDeclarator(methodDecl);
1550 if (token == TokenNameSEMICOLON) {
1552 throwSyntaxError("Body declaration expected for method: " + new String(methodDecl.selector));
1557 functionBody(methodDecl);
1560 private void functionDeclarator(MethodDeclaration methodDecl) {
1561 //identifier '(' [parameter-list] ')'
1562 if (token == TokenNameAND) {
1565 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1566 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1567 if (Scanner.isIdentifierOrKeyword(token)) {
1568 methodDecl.selector = scanner.getCurrentIdentifierSource();
1569 if (token > TokenNameKEYWORD) {
1570 problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
1571 scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
1572 // reportSyntaxWarning("Don't use keyword for function declaration [" + scanner.toStringAction(token) + "].",
1573 // scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1576 if (token == TokenNameLPAREN) {
1579 throwSyntaxError("'(' expected in function declaration.");
1581 if (token != TokenNameRPAREN) {
1584 if (token != TokenNameRPAREN) {
1585 throwSyntaxError("')' expected in function declaration.");
1587 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1591 methodDecl.selector = "<undefined>".toCharArray();
1592 throwSyntaxError("Function name expected after keyword 'function'.");
1597 private void parameter_list() {
1598 // non_empty_parameter_list
1600 non_empty_parameter_list(true);
1603 private void non_empty_parameter_list(boolean empty_allowed) {
1604 // optional_class_type T_VARIABLE
1605 // | optional_class_type '&' T_VARIABLE
1606 // | optional_class_type '&' T_VARIABLE '=' static_scalar
1607 // | optional_class_type T_VARIABLE '=' static_scalar
1608 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE
1609 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
1610 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
1612 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
1614 if (token == TokenNameIdentifier || token == TokenNameVariable || token == TokenNameAND) {
1616 if (token == TokenNameIdentifier) {
1619 if (token == TokenNameAND) {
1622 if (token == TokenNameVariable) {
1624 if (token == TokenNameEQUAL) {
1629 throwSyntaxError("Variable expected in parameter list.");
1631 if (token != TokenNameCOMMA) {
1638 if (!empty_allowed) {
1639 throwSyntaxError("Identifier expected in parameter list.");
1643 private void optional_class_type() {
1648 private void parameterDeclaration() {
1650 //variable-reference
1651 if (token == TokenNameAND) {
1656 throwSyntaxError("Variable expected after reference operator '&'.");
1659 //variable '=' constant
1660 if (token == TokenNameVariable) {
1662 if (token == TokenNameEQUAL) {
1668 // if (token == TokenNamethis) {
1669 // throwSyntaxError("Reserved word '$this' not allowed in parameter
1674 private void labeledStatementList() {
1675 if (token != TokenNamecase && token != TokenNamedefault) {
1676 throwSyntaxError("'case' or 'default' expected.");
1679 if (token == TokenNamecase) {
1681 expr(); //constant();
1682 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1684 if (token == TokenNamecase || token == TokenNamedefault) {
1685 // empty case statement ?
1690 // else if (token == TokenNameSEMICOLON) {
1692 // "':' expected after 'case' keyword (Found token: " +
1693 // scanner.toStringAction(token) + ")",
1694 // scanner.getCurrentTokenStartPosition(),
1695 // scanner.getCurrentTokenEndPosition(),
1698 // if (token == TokenNamecase) { // empty case statement ?
1704 throwSyntaxError("':' character expected after 'case' constant (Found token: " + scanner.toStringAction(token) + ")");
1706 } else { // TokenNamedefault
1708 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1710 if (token == TokenNameRBRACE) {
1711 // empty default case
1714 if (token != TokenNamecase) {
1718 throwSyntaxError("':' character expected after 'default'.");
1721 } while (token == TokenNamecase || token == TokenNamedefault);
1724 // public void labeledStatement() {
1725 // if (token == TokenNamecase) {
1728 // if (token == TokenNameDDOT) {
1732 // throwSyntaxError("':' character after 'case' constant expected.");
1735 // } else if (token == TokenNamedefault) {
1737 // if (token == TokenNameDDOT) {
1741 // throwSyntaxError("':' character after 'default' expected.");
1746 // public void expressionStatement() {
1748 // private void inclusionStatement() {
1750 // public void compoundStatement() {
1752 // public void selectionStatement() {
1755 // public void iterationStatement() {
1758 // public void jumpStatement() {
1761 // public void outputStatement() {
1764 // public void scopeStatement() {
1767 // public void flowStatement() {
1770 // public void definitionStatement() {
1772 private void ifStatement() {
1773 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1774 if (token == TokenNameCOLON) {
1776 if (token != TokenNameendif) {
1781 if (token == TokenNameCOLON) {
1783 if (token != TokenNameendif) {
1787 if (token == TokenNameif) { //'else if'
1789 elseifStatementList();
1791 throwSyntaxError("':' expected after 'else'.");
1795 case TokenNameelseif:
1797 elseifStatementList();
1801 if (token != TokenNameendif) {
1802 throwSyntaxError("'endif' expected.");
1805 if (token != TokenNameSEMICOLON) {
1806 throwSyntaxError("';' expected after if-statement.");
1810 // statement [else-statement]
1811 statement(TokenNameEOF);
1812 if (token == TokenNameelseif) {
1814 if (token == TokenNameLPAREN) {
1817 throwSyntaxError("'(' expected after 'elseif' keyword.");
1820 if (token == TokenNameRPAREN) {
1823 throwSyntaxError("')' expected after 'elseif' condition.");
1826 } else if (token == TokenNameelse) {
1828 statement(TokenNameEOF);
1833 private void elseifStatementList() {
1839 if (token == TokenNameCOLON) {
1841 if (token != TokenNameendif) {
1846 if (token == TokenNameif) { //'else if'
1849 throwSyntaxError("':' expected after 'else'.");
1853 case TokenNameelseif:
1862 private void elseifStatement() {
1863 if (token == TokenNameLPAREN) {
1866 if (token != TokenNameRPAREN) {
1867 throwSyntaxError("')' expected in else-if-statement.");
1870 if (token != TokenNameCOLON) {
1871 throwSyntaxError("':' expected in else-if-statement.");
1874 if (token != TokenNameendif) {
1880 private void switchStatement() {
1881 if (token == TokenNameCOLON) {
1882 // ':' [labeled-statement-list] 'endswitch' ';'
1884 labeledStatementList();
1885 if (token != TokenNameendswitch) {
1886 throwSyntaxError("'endswitch' expected.");
1889 if (token != TokenNameSEMICOLON) {
1890 throwSyntaxError("';' expected after switch-statement.");
1894 // '{' [labeled-statement-list] '}'
1895 if (token != TokenNameLBRACE) {
1896 throwSyntaxError("'{' expected in switch statement.");
1899 if (token != TokenNameRBRACE) {
1900 labeledStatementList();
1902 if (token != TokenNameRBRACE) {
1903 throwSyntaxError("'}' expected in switch statement.");
1909 private void forStatement() {
1910 if (token == TokenNameCOLON) {
1913 if (token != TokenNameendfor) {
1914 throwSyntaxError("'endfor' expected.");
1917 if (token != TokenNameSEMICOLON) {
1918 throwSyntaxError("';' expected after for-statement.");
1922 statement(TokenNameEOF);
1926 private void whileStatement() {
1927 // ':' statement-list 'endwhile' ';'
1928 if (token == TokenNameCOLON) {
1931 if (token != TokenNameendwhile) {
1932 throwSyntaxError("'endwhile' expected.");
1935 if (token != TokenNameSEMICOLON) {
1936 throwSyntaxError("';' expected after while-statement.");
1940 statement(TokenNameEOF);
1944 private void foreachStatement() {
1945 if (token == TokenNameCOLON) {
1948 if (token != TokenNameendforeach) {
1949 throwSyntaxError("'endforeach' expected.");
1952 if (token != TokenNameSEMICOLON) {
1953 throwSyntaxError("';' expected after foreach-statement.");
1957 statement(TokenNameEOF);
1961 // private void exitStatus() {
1962 // if (token == TokenNameLPAREN) {
1965 // throwSyntaxError("'(' expected in 'exit-status'.");
1967 // if (token != TokenNameRPAREN) {
1970 // if (token == TokenNameRPAREN) {
1973 // throwSyntaxError("')' expected after 'exit-status'.");
1976 private void expressionList() {
1979 if (token == TokenNameCOMMA) {
1987 private Expression expr() {
1989 // | expr_without_variable
1990 // if (token!=TokenNameEOF) {
1991 if (Scanner.TRACE) {
1992 System.out.println("TRACE: expr()");
1994 return expr_without_variable(true);
1998 private Expression expr_without_variable(boolean only_variable) {
1999 int exprSourceStart = scanner.getCurrentTokenStartPosition();
2000 int exprSourceEnd = scanner.getCurrentTokenEndPosition();
2001 Expression expression = new Expression();
2002 expression.sourceStart = exprSourceStart;
2003 // default, may be overwritten
2004 expression.sourceEnd = exprSourceEnd;
2005 // internal_functions_in_yacc
2014 // | T_INC rw_variable
2015 // | T_DEC rw_variable
2016 // | T_INT_CAST expr
2017 // | T_DOUBLE_CAST expr
2018 // | T_STRING_CAST expr
2019 // | T_ARRAY_CAST expr
2020 // | T_OBJECT_CAST expr
2021 // | T_BOOL_CAST expr
2022 // | T_UNSET_CAST expr
2023 // | T_EXIT exit_expr
2025 // | T_ARRAY '(' array_pair_list ')'
2026 // | '`' encaps_list '`'
2027 // | T_LIST '(' assignment_list ')' '=' expr
2028 // | T_NEW class_name_reference ctor_arguments
2029 // | variable '=' expr
2030 // | variable '=' '&' variable
2031 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2032 // | variable T_PLUS_EQUAL expr
2033 // | variable T_MINUS_EQUAL expr
2034 // | variable T_MUL_EQUAL expr
2035 // | variable T_DIV_EQUAL expr
2036 // | variable T_CONCAT_EQUAL expr
2037 // | variable T_MOD_EQUAL expr
2038 // | variable T_AND_EQUAL expr
2039 // | variable T_OR_EQUAL expr
2040 // | variable T_XOR_EQUAL expr
2041 // | variable T_SL_EQUAL expr
2042 // | variable T_SR_EQUAL expr
2043 // | rw_variable T_INC
2044 // | rw_variable T_DEC
2045 // | expr T_BOOLEAN_OR expr
2046 // | expr T_BOOLEAN_AND expr
2047 // | expr T_LOGICAL_OR expr
2048 // | expr T_LOGICAL_AND expr
2049 // | expr T_LOGICAL_XOR expr
2061 // | expr T_IS_IDENTICAL expr
2062 // | expr T_IS_NOT_IDENTICAL expr
2063 // | expr T_IS_EQUAL expr
2064 // | expr T_IS_NOT_EQUAL expr
2066 // | expr T_IS_SMALLER_OR_EQUAL expr
2068 // | expr T_IS_GREATER_OR_EQUAL expr
2069 // | expr T_INSTANCEOF class_name_reference
2070 // | expr '?' expr ':' expr
2071 if (Scanner.TRACE) {
2072 System.out.println("TRACE: expr_without_variable() PART 1");
2075 case TokenNameisset:
2076 case TokenNameempty:
2078 case TokenNameinclude:
2079 case TokenNameinclude_once:
2080 case TokenNamerequire:
2081 case TokenNamerequire_once:
2082 internal_functions_in_yacc();
2085 case TokenNameLPAREN:
2088 if (token == TokenNameRPAREN) {
2091 throwSyntaxError("')' expected in expression.");
2101 // | T_INT_CAST expr
2102 // | T_DOUBLE_CAST expr
2103 // | T_STRING_CAST expr
2104 // | T_ARRAY_CAST expr
2105 // | T_OBJECT_CAST expr
2106 // | T_BOOL_CAST expr
2107 // | T_UNSET_CAST expr
2108 case TokenNameclone:
2109 case TokenNameprint:
2112 case TokenNameMINUS:
2114 case TokenNameTWIDDLE:
2115 case TokenNameintCAST:
2116 case TokenNamedoubleCAST:
2117 case TokenNamestringCAST:
2118 case TokenNamearrayCAST:
2119 case TokenNameobjectCAST:
2120 case TokenNameboolCAST:
2121 case TokenNameunsetCAST:
2131 //| T_STRING_VARNAME
2133 //| T_START_HEREDOC encaps_list T_END_HEREDOC
2134 // | '`' encaps_list '`'
2136 // | '`' encaps_list '`'
2137 case TokenNameEncapsedString0:
2138 scanner.encapsedStringStack.push(new Character('`'));
2141 if (token == TokenNameEncapsedString0) {
2144 if (token != TokenNameEncapsedString0) {
2145 throwSyntaxError("\'`\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2149 scanner.encapsedStringStack.pop();
2153 // | '\'' encaps_list '\''
2154 case TokenNameEncapsedString1:
2155 scanner.encapsedStringStack.push(new Character('\''));
2158 exprSourceStart = scanner.getCurrentTokenStartPosition();
2159 if (token == TokenNameEncapsedString1) {
2160 expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
2161 .getCurrentTokenEndPosition());
2164 if (token != TokenNameEncapsedString1) {
2165 throwSyntaxError("\'\'\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2167 expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
2168 .getCurrentTokenEndPosition());
2172 scanner.encapsedStringStack.pop();
2176 //| '"' encaps_list '"'
2177 case TokenNameEncapsedString2:
2178 scanner.encapsedStringStack.push(new Character('"'));
2181 exprSourceStart = scanner.getCurrentTokenStartPosition();
2182 if (token == TokenNameEncapsedString2) {
2183 expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
2184 .getCurrentTokenEndPosition());
2187 if (token != TokenNameEncapsedString2) {
2188 throwSyntaxError("'\"' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2190 expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
2191 .getCurrentTokenEndPosition());
2195 scanner.encapsedStringStack.pop();
2199 case TokenNameStringDoubleQuote:
2200 expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(), scanner.getCurrentTokenStartPosition(), scanner
2201 .getCurrentTokenEndPosition());
2204 case TokenNameStringSingleQuote:
2205 expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(), scanner.getCurrentTokenStartPosition(), scanner
2206 .getCurrentTokenEndPosition());
2209 case TokenNameIntegerLiteral:
2210 case TokenNameDoubleLiteral:
2211 case TokenNameStringInterpolated:
2214 case TokenNameCLASS_C:
2215 case TokenNameMETHOD_C:
2216 case TokenNameFUNC_C:
2219 case TokenNameHEREDOC:
2222 case TokenNamearray:
2223 // T_ARRAY '(' array_pair_list ')'
2225 if (token == TokenNameLPAREN) {
2227 if (token == TokenNameRPAREN) {
2232 if (token != TokenNameRPAREN) {
2233 throwSyntaxError("')' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2237 throwSyntaxError("'(' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2241 // | T_LIST '(' assignment_list ')' '=' expr
2243 if (token == TokenNameLPAREN) {
2246 if (token != TokenNameRPAREN) {
2247 throwSyntaxError("')' expected after 'list' keyword.");
2250 if (token != TokenNameEQUAL) {
2251 throwSyntaxError("'=' expected after 'list' keyword.");
2256 throwSyntaxError("'(' expected after 'list' keyword.");
2260 // | T_NEW class_name_reference ctor_arguments
2262 class_name_reference();
2265 // | T_INC rw_variable
2266 // | T_DEC rw_variable
2267 case TokenNamePLUS_PLUS:
2268 case TokenNameMINUS_MINUS:
2272 // | variable '=' expr
2273 // | variable '=' '&' variable
2274 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2275 // | variable T_PLUS_EQUAL expr
2276 // | variable T_MINUS_EQUAL expr
2277 // | variable T_MUL_EQUAL expr
2278 // | variable T_DIV_EQUAL expr
2279 // | variable T_CONCAT_EQUAL expr
2280 // | variable T_MOD_EQUAL expr
2281 // | variable T_AND_EQUAL expr
2282 // | variable T_OR_EQUAL expr
2283 // | variable T_XOR_EQUAL expr
2284 // | variable T_SL_EQUAL expr
2285 // | variable T_SR_EQUAL expr
2286 // | rw_variable T_INC
2287 // | rw_variable T_DEC
2288 case TokenNameIdentifier:
2289 case TokenNameVariable:
2290 case TokenNameDOLLAR:
2293 case TokenNameEQUAL:
2295 if (token == TokenNameAND) {
2297 if (token == TokenNamenew) {
2298 // | variable '=' '&' T_NEW class_name_reference
2301 class_name_reference();
2310 case TokenNamePLUS_EQUAL:
2311 case TokenNameMINUS_EQUAL:
2312 case TokenNameMULTIPLY_EQUAL:
2313 case TokenNameDIVIDE_EQUAL:
2314 case TokenNameDOT_EQUAL:
2315 case TokenNameREMAINDER_EQUAL:
2316 case TokenNameAND_EQUAL:
2317 case TokenNameOR_EQUAL:
2318 case TokenNameXOR_EQUAL:
2319 case TokenNameRIGHT_SHIFT_EQUAL:
2320 case TokenNameLEFT_SHIFT_EQUAL:
2324 case TokenNamePLUS_PLUS:
2325 case TokenNameMINUS_MINUS:
2329 if (!only_variable) {
2330 throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "').");
2335 if (token != TokenNameINLINE_HTML) {
2336 if (token > TokenNameKEYWORD) {
2340 throwSyntaxError("Error in expression (found token '" + scanner.toStringAction(token) + "').");
2345 if (Scanner.TRACE) {
2346 System.out.println("TRACE: expr_without_variable() PART 2");
2348 // | expr T_BOOLEAN_OR expr
2349 // | expr T_BOOLEAN_AND expr
2350 // | expr T_LOGICAL_OR expr
2351 // | expr T_LOGICAL_AND expr
2352 // | expr T_LOGICAL_XOR expr
2364 // | expr T_IS_IDENTICAL expr
2365 // | expr T_IS_NOT_IDENTICAL expr
2366 // | expr T_IS_EQUAL expr
2367 // | expr T_IS_NOT_EQUAL expr
2369 // | expr T_IS_SMALLER_OR_EQUAL expr
2371 // | expr T_IS_GREATER_OR_EQUAL expr
2374 case TokenNameOR_OR:
2376 expression = new OR_OR_Expression(expression, expr(), token);
2378 case TokenNameAND_AND:
2380 expression = new AND_AND_Expression(expression, expr(), token);
2382 case TokenNameEQUAL_EQUAL:
2384 expression = new EqualExpression(expression, expr(), token);
2394 case TokenNameMINUS:
2395 case TokenNameMULTIPLY:
2396 case TokenNameDIVIDE:
2397 case TokenNameREMAINDER:
2398 case TokenNameLEFT_SHIFT:
2399 case TokenNameRIGHT_SHIFT:
2400 case TokenNameEQUAL_EQUAL_EQUAL:
2401 case TokenNameNOT_EQUAL_EQUAL:
2402 case TokenNameNOT_EQUAL:
2404 case TokenNameLESS_EQUAL:
2405 case TokenNameGREATER:
2406 case TokenNameGREATER_EQUAL:
2408 expression = new BinaryExpression(expression, expr(), token);
2410 // | expr T_INSTANCEOF class_name_reference
2411 // | expr '?' expr ':' expr
2412 case TokenNameinstanceof:
2414 class_name_reference();
2415 // TODO use InstanceofExpression
2416 expression = new Expression();
2417 expression.sourceStart = exprSourceStart;
2418 expression.sourceEnd = scanner.getCurrentTokenEndPosition();
2420 case TokenNameQUESTION:
2422 Expression valueIfTrue = expr();
2423 if (token != TokenNameCOLON) {
2424 throwSyntaxError("':' expected in conditional expression.");
2427 Expression valueIfFalse = expr();
2429 expression = new ConditionalExpression(expression, valueIfTrue, valueIfFalse);
2437 private void class_name_reference() {
2438 // class_name_reference:
2440 //| dynamic_class_name_reference
2441 if (Scanner.TRACE) {
2442 System.out.println("TRACE: class_name_reference()");
2444 if (token == TokenNameIdentifier) {
2447 dynamic_class_name_reference();
2451 private void dynamic_class_name_reference() {
2452 //dynamic_class_name_reference:
2453 // base_variable T_OBJECT_OPERATOR object_property
2454 // dynamic_class_name_variable_properties
2456 if (Scanner.TRACE) {
2457 System.out.println("TRACE: dynamic_class_name_reference()");
2460 if (token == TokenNameMINUS_GREATER) {
2463 dynamic_class_name_variable_properties();
2467 private void dynamic_class_name_variable_properties() {
2468 // dynamic_class_name_variable_properties:
2469 // dynamic_class_name_variable_properties
2470 // dynamic_class_name_variable_property
2472 if (Scanner.TRACE) {
2473 System.out.println("TRACE: dynamic_class_name_variable_properties()");
2475 while (token == TokenNameMINUS_GREATER) {
2476 dynamic_class_name_variable_property();
2480 private void dynamic_class_name_variable_property() {
2481 // dynamic_class_name_variable_property:
2482 // T_OBJECT_OPERATOR object_property
2483 if (Scanner.TRACE) {
2484 System.out.println("TRACE: dynamic_class_name_variable_property()");
2486 if (token == TokenNameMINUS_GREATER) {
2492 private void ctor_arguments() {
2495 //| '(' function_call_parameter_list ')'
2496 if (token == TokenNameLPAREN) {
2498 if (token == TokenNameRPAREN) {
2502 non_empty_function_call_parameter_list();
2503 if (token != TokenNameRPAREN) {
2504 throwSyntaxError("')' expected in ctor_arguments.");
2510 private void assignment_list() {
2512 // assignment_list ',' assignment_list_element
2513 //| assignment_list_element
2515 assignment_list_element();
2516 if (token != TokenNameCOMMA) {
2523 private void assignment_list_element() {
2524 //assignment_list_element:
2526 //| T_LIST '(' assignment_list ')'
2528 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2531 if (token == TokenNamelist) {
2533 if (token == TokenNameLPAREN) {
2536 if (token != TokenNameRPAREN) {
2537 throwSyntaxError("')' expected after 'list' keyword.");
2541 throwSyntaxError("'(' expected after 'list' keyword.");
2547 private void array_pair_list() {
2550 //| non_empty_array_pair_list possible_comma
2551 non_empty_array_pair_list();
2552 if (token == TokenNameCOMMA) {
2557 private void non_empty_array_pair_list() {
2558 //non_empty_array_pair_list:
2559 // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2560 //| non_empty_array_pair_list ',' expr
2561 //| expr T_DOUBLE_ARROW expr
2563 //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2564 //| non_empty_array_pair_list ',' '&' w_variable
2565 //| expr T_DOUBLE_ARROW '&' w_variable
2568 if (token == TokenNameAND) {
2573 if (token == TokenNameAND) {
2576 } else if (token == TokenNameEQUAL_GREATER) {
2578 if (token == TokenNameAND) {
2586 if (token != TokenNameCOMMA) {
2590 if (token == TokenNameRPAREN) {
2596 // private void variableList() {
2599 // if (token == TokenNameCOMMA) {
2606 private void variable_without_objects() {
2607 // variable_without_objects:
2608 // reference_variable
2609 // | simple_indirect_reference reference_variable
2610 if (Scanner.TRACE) {
2611 System.out.println("TRACE: variable_without_objects()");
2613 while (token == TokenNameDOLLAR) {
2616 reference_variable();
2619 private void function_call() {
2621 // T_STRING '(' function_call_parameter_list ')'
2622 //| class_constant '(' function_call_parameter_list ')'
2623 //| static_member '(' function_call_parameter_list ')'
2624 //| variable_without_objects '(' function_call_parameter_list ')'
2625 char[] defineName = null;
2626 char[] ident = null;
2629 if (Scanner.TRACE) {
2630 System.out.println("TRACE: function_call()");
2632 if (token == TokenNameIdentifier) {
2633 ident = scanner.getCurrentIdentifierSource();
2635 startPos = scanner.getCurrentTokenStartPosition();
2636 endPos = scanner.getCurrentTokenEndPosition();
2639 case TokenNamePAAMAYIM_NEKUDOTAYIM:
2643 if (token == TokenNameIdentifier) {
2648 variable_without_objects();
2653 variable_without_objects();
2655 if (token != TokenNameLPAREN) {
2656 if (defineName != null) {
2657 // does this identifier contain only uppercase characters?
2658 if (defineName.length == 3) {
2659 if (defineName[0] == 'd' && defineName[1] == 'i' && defineName[2] == 'e') {
2662 } else if (defineName.length == 4) {
2663 if (defineName[0] == 't' && defineName[1] == 'r' && defineName[2] == 'u' && defineName[3] == 'e') {
2665 } else if (defineName[0] == 'n' && defineName[1] == 'u' && defineName[2] == 'l' && defineName[3] == 'l') {
2668 } else if (defineName.length == 5) {
2669 if (defineName[0] == 'f' && defineName[1] == 'a' && defineName[2] == 'l' && defineName[3] == 's' && defineName[4] == 'e') {
2673 if (defineName != null) {
2674 for (int i = 0; i < defineName.length; i++) {
2675 if (Character.isLowerCase(defineName[i])) {
2676 problemReporter.phpUppercaseIdentifierWarning(startPos, endPos, referenceContext, compilationUnit.compilationResult);
2682 // TODO is this ok ?
2684 // throwSyntaxError("'(' expected in function call.");
2687 if (token == TokenNameRPAREN) {
2691 non_empty_function_call_parameter_list();
2692 if (token != TokenNameRPAREN) {
2693 String functionName;
2694 if (ident == null) {
2695 functionName = new String(" ");
2697 functionName = new String(ident);
2699 throwSyntaxError("')' expected in function call (" + functionName + ").");
2704 // private void function_call_parameter_list() {
2705 // function_call_parameter_list:
2706 // non_empty_function_call_parameter_list { $$ = $1; }
2709 private void non_empty_function_call_parameter_list() {
2710 //non_empty_function_call_parameter_list:
2711 // expr_without_variable
2714 // | non_empty_function_call_parameter_list ',' expr_without_variable
2715 // | non_empty_function_call_parameter_list ',' variable
2716 // | non_empty_function_call_parameter_list ',' '&' w_variable
2717 if (Scanner.TRACE) {
2718 System.out.println("TRACE: non_empty_function_call_parameter_list()");
2721 if (token == TokenNameAND) {
2725 // if (token == TokenNameIdentifier || token ==
2726 // TokenNameVariable
2727 // || token == TokenNameDOLLAR) {
2730 expr_without_variable(true);
2733 if (token != TokenNameCOMMA) {
2740 private void fully_qualified_class_name() {
2741 if (token == TokenNameIdentifier) {
2744 throwSyntaxError("Class name expected.");
2748 private void static_member() {
2750 // fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
2751 // variable_without_objects
2752 if (Scanner.TRACE) {
2753 System.out.println("TRACE: static_member()");
2755 fully_qualified_class_name();
2756 if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
2757 throwSyntaxError("'::' expected after class name (static_member).");
2760 variable_without_objects();
2763 private void base_variable_with_function_calls() {
2764 // base_variable_with_function_calls:
2767 boolean functionCall = false;
2768 if (Scanner.TRACE) {
2769 System.out.println("TRACE: base_variable_with_function_calls()");
2771 // if (token == TokenNameIdentifier) {
2772 // functionCall = true;
2773 // } else if (token == TokenNameVariable) {
2774 // int tempToken = token;
2775 // int tempPosition = scanner.currentPosition;
2777 // if (token == TokenNameLPAREN) {
2778 // functionCall = true;
2780 // token = tempToken;
2781 // scanner.currentPosition = tempPosition;
2782 // scanner.phpMode = true;
2784 // if (functionCall) {
2791 private void base_variable() {
2793 // reference_variable
2794 // | simple_indirect_reference reference_variable
2796 if (Scanner.TRACE) {
2797 System.out.println("TRACE: base_variable()");
2799 if (token == TokenNameIdentifier) {
2802 while (token == TokenNameDOLLAR) {
2805 reference_variable();
2809 // private void simple_indirect_reference() {
2810 // // simple_indirect_reference:
2812 // //| simple_indirect_reference '$'
2814 private void reference_variable() {
2815 // reference_variable:
2816 // reference_variable '[' dim_offset ']'
2817 // | reference_variable '{' expr '}'
2818 // | compound_variable
2819 if (Scanner.TRACE) {
2820 System.out.println("TRACE: reference_variable()");
2822 compound_variable();
2824 if (token == TokenNameLBRACE) {
2827 if (token != TokenNameRBRACE) {
2828 throwSyntaxError("'}' expected in reference variable.");
2831 } else if (token == TokenNameLBRACKET) {
2833 if (token != TokenNameRBRACKET) {
2836 if (token != TokenNameRBRACKET) {
2837 throwSyntaxError("']' expected in reference variable.");
2847 private void compound_variable() {
2848 // compound_variable:
2850 // | '$' '{' expr '}'
2851 if (Scanner.TRACE) {
2852 System.out.println("TRACE: compound_variable()");
2854 if (token == TokenNameVariable) {
2857 // because of simple_indirect_reference
2858 while (token == TokenNameDOLLAR) {
2861 if (token != TokenNameLBRACE) {
2862 throwSyntaxError("'{' expected after compound variable token '$'.");
2866 if (token != TokenNameRBRACE) {
2867 throwSyntaxError("'}' expected after compound variable token '$'.");
2873 // private void dim_offset() {
2879 private void object_property() {
2882 //| variable_without_objects
2883 if (Scanner.TRACE) {
2884 System.out.println("TRACE: object_property()");
2886 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2887 variable_without_objects();
2893 private void object_dim_list() {
2895 // object_dim_list '[' dim_offset ']'
2896 //| object_dim_list '{' expr '}'
2898 if (Scanner.TRACE) {
2899 System.out.println("TRACE: object_dim_list()");
2903 if (token == TokenNameLBRACE) {
2906 if (token != TokenNameRBRACE) {
2907 throwSyntaxError("'}' expected in object_dim_list.");
2910 } else if (token == TokenNameLBRACKET) {
2912 if (token == TokenNameRBRACKET) {
2917 if (token != TokenNameRBRACKET) {
2918 throwSyntaxError("']' expected in object_dim_list.");
2927 private void variable_name() {
2931 if (Scanner.TRACE) {
2932 System.out.println("TRACE: variable_name()");
2934 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
2935 if (token > TokenNameKEYWORD) {
2936 // TODO show a warning "Keyword used as variable" ?
2940 if (token != TokenNameLBRACE) {
2941 throwSyntaxError("'{' expected in variable name.");
2945 if (token != TokenNameRBRACE) {
2946 throwSyntaxError("'}' expected in variable name.");
2952 private void r_variable() {
2956 private void w_variable() {
2960 private void rw_variable() {
2964 private void variable() {
2966 // base_variable_with_function_calls T_OBJECT_OPERATOR
2967 // object_property method_or_not variable_properties
2968 // | base_variable_with_function_calls
2969 base_variable_with_function_calls();
2970 if (token == TokenNameMINUS_GREATER) {
2974 variable_properties();
2976 // if (token == TokenNameDOLLAR_LBRACE) {
2980 // if (token != TokenNameRBRACE) {
2981 // throwSyntaxError("'}' expected after indirect variable token '${'.");
2985 // if (token == TokenNameVariable) {
2987 // if (token == TokenNameLBRACKET) {
2990 // if (token != TokenNameRBRACKET) {
2991 // throwSyntaxError("']' expected in variable-list.");
2994 // } else if (token == TokenNameEQUAL) {
2999 // throwSyntaxError("$-variable expected in variable-list.");
3004 private void variable_properties() {
3005 // variable_properties:
3006 // variable_properties variable_property
3008 while (token == TokenNameMINUS_GREATER) {
3009 variable_property();
3013 private void variable_property() {
3014 // variable_property:
3015 // T_OBJECT_OPERATOR object_property method_or_not
3016 if (Scanner.TRACE) {
3017 System.out.println("TRACE: variable_property()");
3019 if (token == TokenNameMINUS_GREATER) {
3024 throwSyntaxError("'->' expected in variable_property.");
3028 private void method_or_not() {
3030 // '(' function_call_parameter_list ')'
3032 if (Scanner.TRACE) {
3033 System.out.println("TRACE: method_or_not()");
3035 if (token == TokenNameLPAREN) {
3037 if (token == TokenNameRPAREN) {
3041 non_empty_function_call_parameter_list();
3042 if (token != TokenNameRPAREN) {
3043 throwSyntaxError("')' expected in method_or_not.");
3049 private void exit_expr() {
3053 if (token != TokenNameLPAREN) {
3057 if (token == TokenNameRPAREN) {
3062 if (token != TokenNameRPAREN) {
3063 throwSyntaxError("')' expected after keyword 'exit'");
3068 private void encaps_list() {
3069 // encaps_list encaps_var
3070 // | encaps_list T_STRING
3071 // | encaps_list T_NUM_STRING
3072 // | encaps_list T_ENCAPSED_AND_WHITESPACE
3073 // | encaps_list T_CHARACTER
3074 // | encaps_list T_BAD_CHARACTER
3075 // | encaps_list '['
3076 // | encaps_list ']'
3077 // | encaps_list '{'
3078 // | encaps_list '}'
3079 // | encaps_list T_OBJECT_OPERATOR
3083 case TokenNameSTRING:
3086 case TokenNameLBRACE:
3087 // scanner.encapsedStringStack.pop();
3090 case TokenNameRBRACE:
3091 // scanner.encapsedStringStack.pop();
3094 case TokenNameLBRACKET:
3095 // scanner.encapsedStringStack.pop();
3098 case TokenNameRBRACKET:
3099 // scanner.encapsedStringStack.pop();
3102 case TokenNameMINUS_GREATER:
3103 // scanner.encapsedStringStack.pop();
3106 case TokenNameVariable:
3107 case TokenNameDOLLAR_LBRACE:
3108 case TokenNameLBRACE_DOLLAR:
3112 char encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
3113 if (encapsedChar == '$') {
3114 scanner.encapsedStringStack.pop();
3115 encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
3116 switch (encapsedChar) {
3118 if (token == TokenNameEncapsedString0) {
3121 token = TokenNameSTRING;
3124 if (token == TokenNameEncapsedString1) {
3127 token = TokenNameSTRING;
3130 if (token == TokenNameEncapsedString2) {
3133 token = TokenNameSTRING;
3142 private void encaps_var() {
3144 // | T_VARIABLE '[' encaps_var_offset ']'
3145 // | T_VARIABLE T_OBJECT_OPERATOR T_STRING
3146 // | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
3147 // | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
3148 // | T_CURLY_OPEN variable '}'
3150 case TokenNameVariable:
3152 if (token == TokenNameLBRACKET) {
3154 expr(); //encaps_var_offset();
3155 if (token != TokenNameRBRACKET) {
3156 throwSyntaxError("']' expected after variable.");
3158 // scanner.encapsedStringStack.pop();
3161 } else if (token == TokenNameMINUS_GREATER) {
3163 if (token != TokenNameIdentifier) {
3164 throwSyntaxError("Identifier expected after '->'.");
3166 // scanner.encapsedStringStack.pop();
3170 // // scanner.encapsedStringStack.pop();
3171 // int tempToken = TokenNameSTRING;
3172 // if (!scanner.encapsedStringStack.isEmpty()
3173 // && (token == TokenNameEncapsedString0
3174 // || token == TokenNameEncapsedString1
3175 // || token == TokenNameEncapsedString2 || token ==
3176 // TokenNameERROR)) {
3177 // char encapsedChar = ((Character)
3178 // scanner.encapsedStringStack.peek())
3181 // case TokenNameEncapsedString0 :
3182 // if (encapsedChar == '`') {
3183 // tempToken = TokenNameEncapsedString0;
3186 // case TokenNameEncapsedString1 :
3187 // if (encapsedChar == '\'') {
3188 // tempToken = TokenNameEncapsedString1;
3191 // case TokenNameEncapsedString2 :
3192 // if (encapsedChar == '"') {
3193 // tempToken = TokenNameEncapsedString2;
3196 // case TokenNameERROR :
3197 // if (scanner.source[scanner.currentPosition - 1] == '\\') {
3198 // scanner.currentPosition--;
3204 // token = tempToken;
3207 case TokenNameDOLLAR_LBRACE:
3209 if (token == TokenNameDOLLAR_LBRACE) {
3211 } else if (token == TokenNameIdentifier) {
3213 if (token == TokenNameLBRACKET) {
3215 // if (token == TokenNameRBRACKET) {
3219 if (token != TokenNameRBRACKET) {
3220 throwSyntaxError("']' expected after '${'.");
3228 if (token != TokenNameRBRACE) {
3229 throwSyntaxError("'}' expected.");
3233 case TokenNameLBRACE_DOLLAR:
3235 if (token == TokenNameLBRACE_DOLLAR) {
3237 } else if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
3239 if (token == TokenNameLBRACKET) {
3241 // if (token == TokenNameRBRACKET) {
3245 if (token != TokenNameRBRACKET) {
3246 throwSyntaxError("']' expected.");
3250 } else if (token == TokenNameMINUS_GREATER) {
3252 if (token != TokenNameIdentifier && token != TokenNameVariable) {
3253 throwSyntaxError("String or Variable token expected.");
3256 if (token == TokenNameLBRACKET) {
3258 // if (token == TokenNameRBRACKET) {
3262 if (token != TokenNameRBRACKET) {
3263 throwSyntaxError("']' expected after '${'.");
3269 // if (token != TokenNameRBRACE) {
3270 // throwSyntaxError("'}' expected after '{$'.");
3272 // // scanner.encapsedStringStack.pop();
3276 if (token != TokenNameRBRACE) {
3277 throwSyntaxError("'}' expected.");
3279 // scanner.encapsedStringStack.pop();
3286 private void encaps_var_offset() {
3291 case TokenNameSTRING:
3294 case TokenNameIntegerLiteral:
3297 case TokenNameVariable:
3300 case TokenNameIdentifier:
3304 throwSyntaxError("Variable or String token expected.");
3309 private void internal_functions_in_yacc() {
3311 ImportReference impt = null;
3313 case TokenNameisset:
3314 // T_ISSET '(' isset_variables ')'
3316 if (token != TokenNameLPAREN) {
3317 throwSyntaxError("'(' expected after keyword 'isset'");
3321 if (token != TokenNameRPAREN) {
3322 throwSyntaxError("')' expected after keyword 'isset'");
3326 case TokenNameempty:
3327 // T_EMPTY '(' variable ')'
3329 if (token != TokenNameLPAREN) {
3330 throwSyntaxError("'(' expected after keyword 'empty'");
3334 if (token != TokenNameRPAREN) {
3335 throwSyntaxError("')' expected after keyword 'empty'");
3339 case TokenNameinclude:
3341 checkFileName(token, impt);
3343 case TokenNameinclude_once:
3344 // T_INCLUDE_ONCE expr
3345 checkFileName(token, impt);
3348 // T_EVAL '(' expr ')'
3350 if (token != TokenNameLPAREN) {
3351 throwSyntaxError("'(' expected after keyword 'eval'");
3355 if (token != TokenNameRPAREN) {
3356 throwSyntaxError("')' expected after keyword 'eval'");
3360 case TokenNamerequire:
3362 checkFileName(token, impt);
3364 case TokenNamerequire_once:
3365 // T_REQUIRE_ONCE expr
3366 checkFileName(token, impt);
3371 private void checkFileName(int includeToken, ImportReference impt) {
3372 //<include-token> expr
3373 int start = scanner.getCurrentTokenStartPosition();
3374 boolean hasLPAREN = false;
3376 if (token == TokenNameLPAREN) {
3380 Expression expression = expr();
3382 if (token == TokenNameRPAREN) {
3385 throwSyntaxError("')' expected for keyword '" + scanner.toStringAction(includeToken) + "'");
3388 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3389 impt.declarationSourceEnd = impt.sourceEnd;
3390 impt.declarationEnd = impt.declarationSourceEnd;
3391 //endPosition is just before the ;
3392 impt.declarationSourceStart = start;
3393 includesList.add(impt);
3395 if (expression instanceof StringLiteral) {
3396 StringLiteral literal = (StringLiteral) expression;
3397 char[] includeName = literal.source();
3398 if (includeName.length == 0) {
3399 reportSyntaxError("Empty filename after keyword '" + scanner.toStringAction(includeToken) + "'", literal.sourceStart,
3400 literal.sourceStart + 1);
3402 String includeNameString = new String(includeName);
3403 if (literal instanceof StringLiteralDQ) {
3404 if (includeNameString.indexOf('$') >= 0) {
3405 // assuming that the filename contains a variable => no filename check
3409 if (includeNameString.startsWith("http://")) {
3410 // assuming external include location
3413 if (scanner.compilationUnit != null) {
3414 IResource resource = scanner.compilationUnit.getResource();
3415 // java.io.File f = new java.io.File(new String(compilationUnit.getFileName()));
3416 // System.out.println(expression.toStringExpression());
3418 if (resource != null && resource instanceof IFile) {
3419 // check the filename:
3420 // System.out.println(new String(compilationUnit.getFileName())+" - "+ expression.toStringExpression());
3421 IProject project = resource.getProject();
3422 if (project != null) {
3423 IPath path = PHPFileUtil.determineFilePath(includeNameString, resource, project);
3426 // reportSyntaxError("File: " + expression.toStringExpression() + " doesn't exist in project: "
3427 // + project.getLocation().toString(), literal.sourceStart, literal.sourceEnd);
3428 String[] args = { expression.toStringExpression(), project.getLocation().toString() };
3429 problemReporter.phpIncludeNotExistWarning(args, literal.sourceStart, literal.sourceEnd, referenceContext,
3430 compilationUnit.compilationResult);
3433 impt.setFile( PHPFileUtil.createFile(path, project) );
3434 } catch (Exception e) {
3435 // the file is outside of the workspace
3444 private void isset_variables() {
3446 // | isset_variables ','
3447 if (token == TokenNameRPAREN) {
3448 throwSyntaxError("Variable expected after keyword 'isset'");
3452 if (token == TokenNameCOMMA) {
3460 private boolean common_scalar() {
3464 // | T_CONSTANT_ENCAPSED_STRING
3471 case TokenNameIntegerLiteral:
3474 case TokenNameDoubleLiteral:
3477 case TokenNameStringDoubleQuote:
3480 case TokenNameStringSingleQuote:
3483 case TokenNameStringInterpolated:
3492 case TokenNameCLASS_C:
3495 case TokenNameMETHOD_C:
3498 case TokenNameFUNC_C:
3505 private void scalar() {
3508 //| T_STRING_VARNAME
3511 //| '"' encaps_list '"'
3512 //| '\'' encaps_list '\''
3513 //| T_START_HEREDOC encaps_list T_END_HEREDOC
3514 throwSyntaxError("Not yet implemented (scalar).");
3517 private void static_scalar() {
3518 // static_scalar: /* compile-time evaluated scalars */
3521 // | '+' static_scalar
3522 // | '-' static_scalar
3523 // | T_ARRAY '(' static_array_pair_list ')'
3524 // | static_class_constant
3525 if (common_scalar()) {
3529 case TokenNameIdentifier:
3531 // static_class_constant:
3532 // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3533 if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3535 if (token == TokenNameIdentifier) {
3538 throwSyntaxError("Identifier expected after '::' operator.");
3542 case TokenNameEncapsedString0:
3544 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3545 while (scanner.currentCharacter != '`') {
3546 if (scanner.currentCharacter == '\\') {
3547 scanner.currentPosition++;
3549 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3552 } catch (IndexOutOfBoundsException e) {
3553 throwSyntaxError("'`' expected at end of static string.");
3556 case TokenNameEncapsedString1:
3558 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3559 while (scanner.currentCharacter != '\'') {
3560 if (scanner.currentCharacter == '\\') {
3561 scanner.currentPosition++;
3563 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3566 } catch (IndexOutOfBoundsException e) {
3567 throwSyntaxError("'\'' expected at end of static string.");
3570 case TokenNameEncapsedString2:
3572 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3573 while (scanner.currentCharacter != '"') {
3574 if (scanner.currentCharacter == '\\') {
3575 scanner.currentPosition++;
3577 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3580 } catch (IndexOutOfBoundsException e) {
3581 throwSyntaxError("'\"' expected at end of static string.");
3588 case TokenNameMINUS:
3592 case TokenNamearray:
3594 if (token != TokenNameLPAREN) {
3595 throwSyntaxError("'(' expected after keyword 'array'");
3598 if (token == TokenNameRPAREN) {
3602 non_empty_static_array_pair_list();
3603 if (token != TokenNameRPAREN) {
3604 throwSyntaxError("')' expected after keyword 'array'");
3608 // case TokenNamenull :
3611 // case TokenNamefalse :
3614 // case TokenNametrue :
3618 throwSyntaxError("Static scalar/constant expected.");
3622 private void non_empty_static_array_pair_list() {
3623 // non_empty_static_array_pair_list:
3624 // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3626 //| non_empty_static_array_pair_list ',' static_scalar
3627 //| static_scalar T_DOUBLE_ARROW static_scalar
3631 if (token == TokenNameEQUAL_GREATER) {
3635 if (token != TokenNameCOMMA) {
3639 if (token == TokenNameRPAREN) {
3645 public void reportSyntaxError() { //int act, int currentKind, int
3647 /* remember current scanner position */
3648 int startPos = scanner.startPosition;
3649 int currentPos = scanner.currentPosition;
3650 // String[] expectings;
3651 // String tokenName = name[symbol_index[currentKind]];
3652 //fetch all "accurate" possible terminals that could recover the error
3653 // int start, end = start = asi(stack[stateStackTop]);
3654 // while (asr[end] != 0)
3656 // int length = end - start;
3657 // expectings = new String[length];
3658 // if (length != 0) {
3659 // char[] indexes = new char[length];
3660 // System.arraycopy(asr, start, indexes, 0, length);
3661 // for (int i = 0; i < length; i++) {
3662 // expectings[i] = name[symbol_index[indexes[i]]];
3665 //if the pb is an EOF, try to tell the user that they are some
3666 // if (tokenName.equals(UNEXPECTED_EOF)) {
3667 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3668 // char[] tokenSource;
3670 // tokenSource = this.scanner.getCurrentTokenSource();
3671 // } catch (Exception e) {
3672 // tokenSource = new char[] {};
3674 // problemReporter().parseError(
3675 // this.scanner.startPosition,
3676 // this.scanner.currentPosition - 1,
3681 // } else { //the next test is HEAVILY grammar DEPENDENT.
3682 // if ((length == 14)
3683 // && (expectings[0] == "=") //$NON-NLS-1$
3684 // && (expectings[1] == "*=") //$NON-NLS-1$
3685 // && (expressionPtr > -1)) {
3686 // switch(currentKind) {
3687 // case TokenNameSEMICOLON:
3688 // case TokenNamePLUS:
3689 // case TokenNameMINUS:
3690 // case TokenNameDIVIDE:
3691 // case TokenNameREMAINDER:
3692 // case TokenNameMULTIPLY:
3693 // case TokenNameLEFT_SHIFT:
3694 // case TokenNameRIGHT_SHIFT:
3695 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3696 // case TokenNameLESS:
3697 // case TokenNameGREATER:
3698 // case TokenNameLESS_EQUAL:
3699 // case TokenNameGREATER_EQUAL:
3700 // case TokenNameEQUAL_EQUAL:
3701 // case TokenNameNOT_EQUAL:
3702 // case TokenNameXOR:
3703 // case TokenNameAND:
3704 // case TokenNameOR:
3705 // case TokenNameOR_OR:
3706 // case TokenNameAND_AND:
3707 // // the ; is not the expected token ==> it ends a statement when an
3708 // expression is not ended
3709 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3711 // case TokenNameRBRACE :
3712 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3715 // char[] tokenSource;
3717 // tokenSource = this.scanner.getCurrentTokenSource();
3718 // } catch (Exception e) {
3719 // tokenSource = new char[] {};
3721 // problemReporter().parseError(
3722 // this.scanner.startPosition,
3723 // this.scanner.currentPosition - 1,
3727 // this.checkAndReportBracketAnomalies(problemReporter());
3732 tokenSource = this.scanner.getCurrentTokenSource();
3733 } catch (Exception e) {
3734 tokenSource = new char[] {};
3736 // problemReporter().parseError(
3737 // this.scanner.startPosition,
3738 // this.scanner.currentPosition - 1,
3742 this.checkAndReportBracketAnomalies(problemReporter());
3745 /* reset scanner where it was */
3746 scanner.startPosition = startPos;
3747 scanner.currentPosition = currentPos;
3750 public static final int RoundBracket = 0;
3752 public static final int SquareBracket = 1;
3754 public static final int CurlyBracket = 2;
3756 public static final int BracketKinds = 3;
3758 protected int[] nestedMethod; //the ptr is nestedType
3760 protected int nestedType, dimensions;
3763 final static int AstStackIncrement = 100;
3765 protected int astPtr;
3767 protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
3769 protected int astLengthPtr;
3771 protected int[] astLengthStack;
3773 ASTNode[] noAstNodes = new ASTNode[AstStackIncrement];
3775 public CompilationUnitDeclaration compilationUnit; /*
3776 * the result from parse()
3779 protected ReferenceContext referenceContext;
3781 protected ProblemReporter problemReporter;
3783 protected CompilerOptions options;
3785 private ArrayList includesList;
3787 // protected CompilationResult compilationResult;
3789 * Returns this parser's problem reporter initialized with its reference context. Also it is assumed that a problem is going to be
3790 * reported, so initializes the compilation result's line positions.
3792 public ProblemReporter problemReporter() {
3793 if (scanner.recordLineSeparator) {
3794 compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
3796 problemReporter.referenceContext = referenceContext;
3797 return problemReporter;
3801 * Reconsider the entire source looking for inconsistencies in {} () []
3803 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3804 scanner.wasAcr = false;
3805 boolean anomaliesDetected = false;
3807 char[] source = scanner.source;
3808 int[] leftCount = { 0, 0, 0 };
3809 int[] rightCount = { 0, 0, 0 };
3810 int[] depths = { 0, 0, 0 };
3811 int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] };
3812 int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] };
3813 int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] };
3814 int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] };
3815 scanner.currentPosition = scanner.initialPosition; //starting
3817 // (first-zero-based
3819 while (scanner.currentPosition < scanner.eofPosition) { //loop for
3824 // ---------Consume white space and handles
3825 // startPosition---------
3826 boolean isWhiteSpace;
3828 scanner.startPosition = scanner.currentPosition;
3829 // if (((scanner.currentCharacter =
3830 // source[scanner.currentPosition++]) == '\\') &&
3831 // (source[scanner.currentPosition] == 'u')) {
3832 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3834 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3835 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3836 // only record line positions we have not
3838 scanner.pushLineSeparator();
3841 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3843 } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
3844 // -------consume token until } is found---------
3845 switch (scanner.currentCharacter) {
3847 int index = leftCount[CurlyBracket]++;
3848 if (index == leftPositions[CurlyBracket].length) {
3849 System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
3850 System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
3852 leftPositions[CurlyBracket][index] = scanner.startPosition;
3853 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3857 int index = rightCount[CurlyBracket]++;
3858 if (index == rightPositions[CurlyBracket].length) {
3859 System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
3860 System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
3862 rightPositions[CurlyBracket][index] = scanner.startPosition;
3863 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3867 int index = leftCount[RoundBracket]++;
3868 if (index == leftPositions[RoundBracket].length) {
3869 System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
3870 System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
3872 leftPositions[RoundBracket][index] = scanner.startPosition;
3873 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3877 int index = rightCount[RoundBracket]++;
3878 if (index == rightPositions[RoundBracket].length) {
3879 System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
3880 System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
3882 rightPositions[RoundBracket][index] = scanner.startPosition;
3883 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3887 int index = leftCount[SquareBracket]++;
3888 if (index == leftPositions[SquareBracket].length) {
3889 System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
3890 System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
3892 leftPositions[SquareBracket][index] = scanner.startPosition;
3893 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3897 int index = rightCount[SquareBracket]++;
3898 if (index == rightPositions[SquareBracket].length) {
3899 System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
3900 System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
3902 rightPositions[SquareBracket][index] = scanner.startPosition;
3903 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3907 if (scanner.getNextChar('\\')) {
3908 scanner.scanEscapeCharacter();
3909 } else { // consume next character
3910 scanner.unicodeAsBackSlash = false;
3911 // if (((scanner.currentCharacter =
3912 // source[scanner.currentPosition++]) ==
3914 // (source[scanner.currentPosition] ==
3916 // scanner.getNextUnicodeChar();
3918 if (scanner.withoutUnicodePtr != 0) {
3919 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3923 scanner.getNextChar('\'');
3927 // consume next character
3928 scanner.unicodeAsBackSlash = false;
3929 // if (((scanner.currentCharacter =
3930 // source[scanner.currentPosition++]) == '\\') &&
3931 // (source[scanner.currentPosition] == 'u')) {
3932 // scanner.getNextUnicodeChar();
3934 if (scanner.withoutUnicodePtr != 0) {
3935 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3938 while (scanner.currentCharacter != '"') {
3939 if (scanner.currentCharacter == '\r') {
3940 if (source[scanner.currentPosition] == '\n')
3941 scanner.currentPosition++;
3942 break; // the string cannot go further that
3945 if (scanner.currentCharacter == '\n') {
3946 break; // the string cannot go further that
3949 if (scanner.currentCharacter == '\\') {
3950 scanner.scanEscapeCharacter();
3952 // consume next character
3953 scanner.unicodeAsBackSlash = false;
3954 // if (((scanner.currentCharacter =
3955 // source[scanner.currentPosition++]) == '\\')
3956 // && (source[scanner.currentPosition] == 'u'))
3958 // scanner.getNextUnicodeChar();
3960 if (scanner.withoutUnicodePtr != 0) {
3961 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3968 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3971 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3972 && (source[scanner.currentPosition] == 'u')) {
3973 //-------------unicode traitement
3975 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3976 scanner.currentPosition++;
3977 while (source[scanner.currentPosition] == 'u') {
3978 scanner.currentPosition++;
3980 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3981 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3982 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3983 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3987 scanner.currentCharacter = 'A';
3988 } //something different from \n and \r
3990 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3993 while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
3995 scanner.startPosition = scanner.currentPosition;
3996 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3997 && (source[scanner.currentPosition] == 'u')) {
3998 //-------------unicode traitement
4000 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4001 scanner.currentPosition++;
4002 while (source[scanner.currentPosition] == 'u') {
4003 scanner.currentPosition++;
4005 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
4006 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
4007 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
4008 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
4012 scanner.currentCharacter = 'A';
4013 } //something different from \n
4016 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4020 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
4021 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
4022 // only record line positions we
4023 // have not recorded yet
4024 scanner.pushLineSeparator();
4025 if (this.scanner.taskTags != null) {
4026 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner
4027 .getCurrentTokenEndPosition());
4033 if (test > 0) { //traditional and annotation
4035 boolean star = false;
4036 // consume next character
4037 scanner.unicodeAsBackSlash = false;
4038 // if (((scanner.currentCharacter =
4039 // source[scanner.currentPosition++]) ==
4041 // (source[scanner.currentPosition] ==
4043 // scanner.getNextUnicodeChar();
4045 if (scanner.withoutUnicodePtr != 0) {
4046 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
4049 if (scanner.currentCharacter == '*') {
4053 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
4054 && (source[scanner.currentPosition] == 'u')) {
4055 //-------------unicode traitement
4057 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4058 scanner.currentPosition++;
4059 while (source[scanner.currentPosition] == 'u') {
4060 scanner.currentPosition++;
4062 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
4063 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
4064 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
4065 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
4069 scanner.currentCharacter = 'A';
4070 } //something different from * and /
4072 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4075 //loop until end of comment */
4076 while ((scanner.currentCharacter != '/') || (!star)) {
4077 star = scanner.currentCharacter == '*';
4079 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
4080 && (source[scanner.currentPosition] == 'u')) {
4081 //-------------unicode traitement
4083 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
4084 scanner.currentPosition++;
4085 while (source[scanner.currentPosition] == 'u') {
4086 scanner.currentPosition++;
4088 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
4089 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
4090 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
4091 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
4095 scanner.currentCharacter = 'A';
4096 } //something different from * and
4099 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
4103 if (this.scanner.taskTags != null) {
4104 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
4111 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
4112 scanner.scanIdentifierOrKeyword(false);
4115 if (Character.isDigit(scanner.currentCharacter)) {
4116 scanner.scanNumber(false);
4120 //-----------------end switch while
4121 // try--------------------
4122 } catch (IndexOutOfBoundsException e) {
4123 break; // read until EOF
4124 } catch (InvalidInputException e) {
4125 return false; // no clue
4128 if (scanner.recordLineSeparator) {
4129 // compilationUnit.compilationResult.lineSeparatorPositions =
4130 // scanner.getLineEnds();
4132 // check placement anomalies against other kinds of brackets
4133 for (int kind = 0; kind < BracketKinds; kind++) {
4134 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
4135 int start = leftPositions[kind][leftIndex]; // deepest
4137 // find matching closing bracket
4138 int depth = leftDepths[kind][leftIndex];
4140 for (int i = 0; i < rightCount[kind]; i++) {
4141 int pos = rightPositions[kind][i];
4142 // want matching bracket further in source with same
4144 if ((pos > start) && (depth == rightDepths[kind][i])) {
4149 if (end < 0) { // did not find a good closing match
4150 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
4153 // check if even number of opening/closing other brackets
4154 // in between this pair of brackets
4156 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
4157 for (int i = 0; i < leftCount[otherKind]; i++) {
4158 int pos = leftPositions[otherKind][i];
4159 if ((pos > start) && (pos < end))
4162 for (int i = 0; i < rightCount[otherKind]; i++) {
4163 int pos = rightPositions[otherKind][i];
4164 if ((pos > start) && (pos < end))
4168 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket
4174 // too many opening brackets ?
4175 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
4176 anomaliesDetected = true;
4177 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext,
4178 compilationUnit.compilationResult);
4180 // too many closing brackets ?
4181 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
4182 anomaliesDetected = true;
4183 problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
4185 if (anomaliesDetected)
4188 return anomaliesDetected;
4189 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
4190 return anomaliesDetected;
4191 } catch (NullPointerException e) { // jdk1.2.2 jit bug
4192 return anomaliesDetected;
4196 protected void pushOnAstLengthStack(int pos) {
4198 astLengthStack[++astLengthPtr] = pos;
4199 } catch (IndexOutOfBoundsException e) {
4200 int oldStackLength = astLengthStack.length;
4201 int[] oldPos = astLengthStack;
4202 astLengthStack = new int[oldStackLength + StackIncrement];
4203 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
4204 astLengthStack[astLengthPtr] = pos;
4208 protected void pushOnAstStack(ASTNode node) {
4210 * add a new obj on top of the ast stack
4213 astStack[++astPtr] = node;
4214 } catch (IndexOutOfBoundsException e) {
4215 int oldStackLength = astStack.length;
4216 ASTNode[] oldStack = astStack;
4217 astStack = new ASTNode[oldStackLength + AstStackIncrement];
4218 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
4219 astPtr = oldStackLength;
4220 astStack[astPtr] = node;
4223 astLengthStack[++astLengthPtr] = 1;
4224 } catch (IndexOutOfBoundsException e) {
4225 int oldStackLength = astLengthStack.length;
4226 int[] oldPos = astLengthStack;
4227 astLengthStack = new int[oldStackLength + AstStackIncrement];
4228 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
4229 astLengthStack[astLengthPtr] = 1;
4233 protected void resetModifiers() {
4234 this.modifiers = AccDefault;
4235 this.modifiersSourceStart = -1; // <-- see comment into
4236 // modifiersFlag(int)
4237 this.scanner.commentPtr = -1;