1 /***********************************************************************************************************************************
2 * Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de All rights reserved. This program and the accompanying material are
3 * made available under the 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: Klaus Hartlage - www.eclipseproject.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.phpeclipse.builder.IdentifierIndexManager;
23 import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.Expression;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
28 import net.sourceforge.phpeclipse.internal.compiler.ast.IfStatement;
29 import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
30 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
31 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
32 import net.sourceforge.phpeclipse.internal.compiler.ast.Statement;
33 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
35 import org.eclipse.core.resources.IFile;
37 public class Parser //extends PHPParserSuperclass
38 implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
39 //internal data for the automat
40 protected final static int StackIncrement = 255;
42 protected int stateStackTop;
44 protected int[] stack = new int[StackIncrement];
46 public int firstToken; // handle for multiple parsing goals
48 public int lastAct; //handle for multiple parsing goals
50 protected RecoveredElement currentElement;
52 public static boolean VERBOSE_RECOVERY = false;
54 protected boolean diet = false; //tells the scanner to jump over some
56 // parts of the code/expressions like
59 public Scanner scanner;
61 private ArrayList phpList;
63 private int currentPHPString;
65 private boolean phpEnd;
67 // private static HashMap keywordMap = null;
75 // row counter for syntax errors:
77 // column counter for syntax errors:
81 // // current identifier
87 private String stringValue;
89 /** Contains the current expression. */
90 // private StringBuffer expression;
91 //private boolean phpMode;
92 protected int modifiers;
94 protected int modifiersSourceStart;
96 // protected IdentifierIndexManager indexManager;
98 protected Parser(ProblemReporter problemReporter) {
99 this.problemReporter = problemReporter;
100 this.options = problemReporter.options;
101 this.currentPHPString = 0;
102 // PHPParserSuperclass.fileToParse = fileToParse;
104 // this.indexManager = null;
106 this.token = TokenNameEOF;
108 // this.rowCount = 1;
109 // this.columnCount = 0;
112 this.initializeScanner();
115 public void setFileToParse(IFile fileToParse) {
116 this.currentPHPString = 0;
117 // PHPParserSuperclass.fileToParse = fileToParse;
119 // this.indexManager = null;
121 this.token = TokenNameEOF;
123 this.initializeScanner();
127 * ClassDeclaration Constructor.
131 * Description of Parameter
134 public Parser(IFile fileToParse) {
135 // if (keywordMap == null) {
136 // keywordMap = new HashMap();
137 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
138 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
141 this.currentPHPString = 0;
142 // PHPParserSuperclass.fileToParse = fileToParse;
144 this.includesList = null;
146 this.token = TokenNameEOF;
148 // this.rowCount = 1;
149 // this.columnCount = 0;
152 this.initializeScanner();
155 public void initializeScanner() {
156 this.scanner = new Scanner(false /* comment */, false /* whitespace */, this.options
157 .getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /* nls */, false, false,
158 this.options.taskTags/* taskTags */, this.options.taskPriorites/* taskPriorities */);
162 * Create marker for the parse error
164 // private void setMarker(String message, int charStart, int charEnd, int
166 // setMarker(fileToParse, message, charStart, charEnd, errorLevel);
169 * This method will throw the SyntaxError. It will add the good lines and columns to the Error
173 * @throws SyntaxError
176 private void throwSyntaxError(String error) {
177 int problemStartPosition = scanner.getCurrentTokenStartPosition();
178 int problemEndPosition = scanner.getCurrentTokenEndPosition();
179 throwSyntaxError(error, problemStartPosition, problemEndPosition + 1);
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, int startRow) {
191 // throw new SyntaxError(startRow, 0, " ", error);
193 private void throwSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
194 problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
195 compilationUnit.compilationResult);
196 throw new SyntaxError(1, 0, " ", error);
199 private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
200 problemReporter.phpParsingError(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
201 compilationUnit.compilationResult);
204 private void reportSyntaxWarning(String error, int problemStartPosition, int problemEndPosition) {
205 problemReporter.phpParsingWarning(new String[] { error }, problemStartPosition, problemEndPosition, referenceContext,
206 compilationUnit.compilationResult);
210 * Method Declaration.
214 // private void getChar() {
215 // if (str.length() > chIndx) {
216 // ch = str.charAt(chIndx++);
221 // chIndx = str.length() + 1;
223 // // token = TokenNameEOF;
227 * gets the next token from input
229 private void getNextToken() {
231 token = scanner.getNextToken();
233 int currentEndPosition = scanner.getCurrentTokenEndPosition();
234 int currentStartPosition = scanner.getCurrentTokenStartPosition();
235 System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
236 System.out.println(scanner.toStringAction(token));
238 } catch (InvalidInputException e) {
239 token = TokenNameERROR;
240 String detailedMessage = e.getMessage();
242 if (detailedMessage == Scanner.UNTERMINATED_STRING) {
243 throwSyntaxError("Unterminated string.");
244 } else if (detailedMessage == Scanner.UNTERMINATED_COMMENT) {
245 throwSyntaxError("Unterminated commment.");
251 public void init(String s) {
253 this.token = TokenNameEOF;
255 // this.rowCount = 1;
256 // this.columnCount = 0;
258 // this.phpMode = false;
259 /* scanner initialization */
260 scanner.setSource(s.toCharArray());
261 scanner.setPHPMode(false);
264 protected void initialize(boolean phpMode) {
265 initialize(phpMode, null);
268 protected void initialize(boolean phpMode, IdentifierIndexManager indexManager) {
269 compilationUnit = null;
270 referenceContext = null;
271 includesList = new ArrayList();
272 // this.indexManager = indexManager;
274 this.token = TokenNameEOF;
276 // this.rowCount = 1;
277 // this.columnCount = 0;
279 // this.phpMode = phpMode;
280 scanner.setPHPMode(phpMode);
284 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>'
286 public void parse(String s) {
292 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?> </body>'
294 protected void parse() {
298 if (token != TokenNameEOF && token != TokenNameERROR) {
301 if (token != TokenNameEOF) {
302 if (token == TokenNameERROR) {
303 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
305 if (token == TokenNameRPAREN) {
306 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
308 if (token == TokenNameRBRACE) {
309 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
311 if (token == TokenNameRBRACKET) {
312 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
314 if (token == TokenNameLPAREN) {
315 throwSyntaxError("Read character '('; end-of-file not reached.");
317 if (token == TokenNameLBRACE) {
318 throwSyntaxError("Read character '{'; end-of-file not reached.");
320 if (token == TokenNameLBRACKET) {
321 throwSyntaxError("Read character '['; end-of-file not reached.");
323 throwSyntaxError("End-of-file not reached.");
326 } catch (SyntaxError sytaxErr1) {
327 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(),
329 // setMarker(sytaxErr1.getMessage(),
330 // scanner.getCurrentTokenStartPosition(),
331 // scanner.getCurrentTokenEndPosition(), ERROR);
333 // if an error occured,
334 // try to find keywords 'class' or 'function'
335 // to parse the rest of the string
336 while (token != TokenNameEOF && token != TokenNameERROR) {
337 if (token == TokenNameabstract || token == TokenNamefinal || token == TokenNameclass || token == TokenNamefunction) {
342 if (token == TokenNameEOF || token == TokenNameERROR) {
345 } catch (SyntaxError sytaxErr2) {
346 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(),
348 // setMarker(sytaxErr2.getMessage(),
349 // scanner.getCurrentTokenStartPosition(),
350 // scanner.getCurrentTokenEndPosition(), ERROR);
359 protected CompilationUnitDeclaration endParse(int act) {
363 if (currentElement != null) {
364 currentElement.topElement().updateParseTree();
365 if (VERBOSE_RECOVERY) {
366 System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
367 System.out.println("--------------------------"); //$NON-NLS-1$
368 System.out.println(compilationUnit);
369 System.out.println("----------------------------------"); //$NON-NLS-1$
372 if (diet & VERBOSE_RECOVERY) {
373 System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
374 System.out.println("--------------------------"); //$NON-NLS-1$
375 System.out.println(compilationUnit);
376 System.out.println("----------------------------------"); //$NON-NLS-1$
379 if (scanner.recordLineSeparator) {
380 compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
382 if (scanner.taskTags != null) {
383 for (int i = 0; i < scanner.foundTaskCount; i++) {
384 problemReporter().task(new String(scanner.foundTaskTags[i]), new String(scanner.foundTaskMessages[i]),
385 scanner.foundTaskPriorities[i] == null ? null : new String(scanner.foundTaskPriorities[i]),
386 scanner.foundTaskPositions[i][0], scanner.foundTaskPositions[i][1]);
389 compilationUnit.imports = new ImportReference[includesList.size()];
390 for (int i = 0; i < includesList.size(); i++) {
391 compilationUnit.imports[i] = (ImportReference) includesList.get(i);
393 return compilationUnit;
396 // public PHPOutlineInfo parseInfo(Object parent, String s) {
397 // PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
398 // // Stack stack = new Stack();
399 // // stack.push(outlineInfo.getDeclarations());
401 // this.token = TokenNameEOF;
402 // // this.chIndx = 0;
403 // // this.rowCount = 1;
404 // // this.columnCount = 0;
405 // this.phpEnd = false;
406 // this.phpMode = false;
407 // scanner.setSource(s.toCharArray());
408 // scanner.setPHPMode(false);
411 // parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
413 // return outlineInfo;
415 private boolean isVariable() {
416 return token == TokenNameVariable; // || token == TokenNamethis;
419 // private void parseDeclarations(PHPOutlineInfo outlineInfo,
420 // OutlineableWithChildren current, boolean goBack) {
422 // // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
423 // PHPSegmentWithChildren temp;
425 // IPreferenceStore store =
426 // PHPeclipsePlugin.getDefault().getPreferenceStore();
428 // while (token != TokenNameEOF && token != TokenNameERROR) {
429 // if (token == TokenNameVariable) {
430 // ident = scanner.getCurrentIdentifierSource();
431 // outlineInfo.addVariable(new String(ident));
433 // } else if (token == TokenNamevar) {
435 // if (token == TokenNameVariable
436 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
437 // ident = scanner.getCurrentIdentifierSource();
438 // //substring(1) added because PHPVarDeclaration doesn't
439 // // need the $ anymore
440 // String variableName = new String(ident).substring(1);
441 // outlineInfo.addVariable(variableName);
443 // if (token != TokenNameSEMICOLON) {
445 // ident = scanner.getCurrentTokenSource();
446 // if (token > TokenNameKEYWORD) {
447 // current.add(new PHPVarDeclaration(current, variableName,
448 // // chIndx - ident.length,
449 // scanner.getCurrentTokenStartPosition(), new String(ident)));
452 // case TokenNameVariable :
453 // case TokenNamethis :
454 // current.add(new PHPVarDeclaration(current, variableName,
457 // scanner.getCurrentTokenStartPosition(), new String(
460 // case TokenNameIdentifier :
461 // current.add(new PHPVarDeclaration(current, variableName,
464 // scanner.getCurrentTokenStartPosition(), new String(
467 // case TokenNameDoubleLiteral :
468 // current.add(new PHPVarDeclaration(current, variableName
472 // scanner.getCurrentTokenStartPosition(), new String(
475 // case TokenNameIntegerLiteral :
476 // current.add(new PHPVarDeclaration(current, variableName,
479 // scanner.getCurrentTokenStartPosition(), new String(
482 // case TokenNameStringInterpolated :
483 // case TokenNameStringLiteral :
484 // current.add(new PHPVarDeclaration(current, variableName,
487 // scanner.getCurrentTokenStartPosition(), new String(
490 // case TokenNameStringConstant :
491 // current.add(new PHPVarDeclaration(current, variableName,
494 // scanner.getCurrentTokenStartPosition(), new String(
498 // current.add(new PHPVarDeclaration(current, variableName,
501 // scanner.getCurrentTokenStartPosition()));
506 // ident = scanner.getCurrentIdentifierSource();
507 // current.add(new PHPVarDeclaration(current, variableName,
508 // // chIndx - ident.length
509 // scanner.getCurrentTokenStartPosition()));
512 // } else if (token == TokenNamefunction) {
514 // if (token == TokenNameAND) {
517 // if (token == TokenNameIdentifier
518 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
519 // ident = scanner.getCurrentIdentifierSource();
520 // outlineInfo.addVariable(new String(ident));
521 // temp = new PHPFunctionDeclaration(current, new String(ident),
522 // // chIndx - ident.length
523 // scanner.getCurrentTokenStartPosition());
524 // current.add(temp);
526 // parseDeclarations(outlineInfo, temp, true);
528 // } else if (token == TokenNameclass) {
530 // if (token == TokenNameIdentifier
531 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
532 // ident = scanner.getCurrentIdentifierSource();
533 // outlineInfo.addVariable(new String(ident));
534 // temp = new PHPClassDeclaration(current, new String(ident),
535 // // chIndx - ident.len
536 // scanner.getCurrentTokenStartPosition());
537 // current.add(temp);
538 // // stack.push(temp);
540 // //skip tokens for classname, extends and others until
541 // // we have the opening '{'
542 // while (token != TokenNameLBRACE && token != TokenNameEOF
543 // && token != TokenNameERROR) {
546 // parseDeclarations(outlineInfo, temp, true);
549 // } else if ((token == TokenNameLBRACE)
550 // || (token == TokenNameDOLLAR_LBRACE)) {
553 // } else if (token == TokenNameRBRACE) {
556 // if (counter == 0 && goBack) {
559 // } else if (token == TokenNamerequire || token == TokenNamerequire_once
560 // || token == TokenNameinclude || token == TokenNameinclude_once) {
561 // ident = scanner.getCurrentTokenSource();
563 // int startPosition = scanner.getCurrentTokenStartPosition();
565 // char[] expr = scanner.getCurrentTokenSource(startPosition);
566 // outlineInfo.addVariable(new String(ident));
567 // current.add(new PHPReqIncDeclaration(current, new String(ident),
568 // // chIndx - ident.length,
569 // startPosition, new String(expr)));
575 // } catch (SyntaxError sytaxErr) {
577 // // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
578 // // setMarker(sytaxErr.getMessage(),
579 // // scanner.getCurrentTokenStartPosition(),
580 // // scanner.getCurrentTokenEndPosition(), ERROR);
581 // // } catch (CoreException e) {
585 private void statementList() {
587 statement(TokenNameEOF);
588 if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse)
589 || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor)
590 || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch)
591 || (token == TokenNameEOF) || (token == TokenNameERROR)) {
597 private void functionBody(MethodDeclaration methodDecl) {
598 // '{' [statement-list] '}'
599 if (token == TokenNameLBRACE) {
602 throwSyntaxError("'{' expected in compound-statement.");
604 if (token != TokenNameRBRACE) {
607 if (token == TokenNameRBRACE) {
608 methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
611 throwSyntaxError("'}' expected in compound-statement.");
615 private Statement statement(int previousToken) {
616 Statement statement = null;
617 Expression expression;
618 int sourceStart = scanner.getCurrentTokenStartPosition();
619 if (token == TokenNameif) {
621 if (token == TokenNameLPAREN) {
624 throwSyntaxError("'(' expected after 'if' keyword.");
627 if (token == TokenNameRPAREN) {
630 throwSyntaxError("')' expected after 'if' condition.");
633 return new IfStatement(expression, statement, sourceStart, scanner.getCurrentTokenEndPosition());
634 } else if (token == TokenNameswitch) {
636 if (token == TokenNameLPAREN) {
639 throwSyntaxError("'(' expected after 'switch' keyword.");
642 if (token == TokenNameRPAREN) {
645 throwSyntaxError("')' expected after 'switch' condition.");
649 } else if (token == TokenNamefor) {
651 if (token == TokenNameLPAREN) {
654 throwSyntaxError("'(' expected after 'for' keyword.");
656 if (token == TokenNameSEMICOLON) {
660 if (token == TokenNameSEMICOLON) {
663 throwSyntaxError("';' expected after 'for'.");
666 if (token == TokenNameSEMICOLON) {
670 if (token == TokenNameSEMICOLON) {
673 throwSyntaxError("';' expected after 'for'.");
676 if (token == TokenNameRPAREN) {
680 if (token == TokenNameRPAREN) {
683 throwSyntaxError("')' expected after 'for'.");
688 } else if (token == TokenNamewhile) {
690 if (token == TokenNameLPAREN) {
693 throwSyntaxError("'(' expected after 'while' keyword.");
696 if (token == TokenNameRPAREN) {
699 throwSyntaxError("')' expected after 'while' condition.");
703 } else if (token == TokenNamedo) {
705 if (token == TokenNameLBRACE) {
707 if (token != TokenNameRBRACE) {
710 if (token == TokenNameRBRACE) {
713 throwSyntaxError("'}' expected after 'do' keyword.");
716 statement(TokenNameEOF);
718 if (token == TokenNamewhile) {
720 if (token == TokenNameLPAREN) {
723 throwSyntaxError("'(' expected after 'while' keyword.");
726 if (token == TokenNameRPAREN) {
729 throwSyntaxError("')' expected after 'while' condition.");
732 throwSyntaxError("'while' expected after 'do' keyword.");
734 if (token == TokenNameSEMICOLON) {
737 if (token != TokenNameINLINE_HTML) {
738 throwSyntaxError("';' expected after do-while statement.");
743 } else if (token == TokenNameforeach) {
745 if (token == TokenNameLPAREN) {
748 throwSyntaxError("'(' expected after 'foreach' keyword.");
751 if (token == TokenNameas) {
754 throwSyntaxError("'as' expected after 'foreach' exxpression.");
758 foreach_optional_arg();
759 if (token == TokenNameEQUAL_GREATER) {
763 if (token == TokenNameRPAREN) {
766 throwSyntaxError("')' expected after 'foreach' expression.");
770 } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
772 if (token != TokenNameSEMICOLON) {
775 if (token == TokenNameSEMICOLON) {
778 if (token != TokenNameINLINE_HTML) {
779 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
784 } else if (token == TokenNameecho) {
787 if (token == TokenNameSEMICOLON) {
790 if (token != TokenNameINLINE_HTML) {
791 throwSyntaxError("';' expected after 'echo' statement.");
796 } else if (token == TokenNameINLINE_HTML) {
799 // } else if (token == TokenNameprint) {
802 // if (token == TokenNameSEMICOLON) {
805 // if (token != TokenNameStopPHP) {
806 // throwSyntaxError("';' expected after 'print' statement.");
811 } else if (token == TokenNameglobal) {
814 if (token == TokenNameSEMICOLON) {
817 if (token != TokenNameINLINE_HTML) {
818 throwSyntaxError("';' expected after 'global' statement.");
823 } else if (token == TokenNamestatic) {
826 if (token == TokenNameSEMICOLON) {
829 if (token != TokenNameINLINE_HTML) {
830 throwSyntaxError("';' expected after 'static' statement.");
835 } else if (token == TokenNameunset) {
837 if (token == TokenNameLPAREN) {
840 throwSyntaxError("'(' expected after 'unset' statement.");
843 if (token == TokenNameRPAREN) {
846 throwSyntaxError("')' expected after 'unset' statement.");
848 if (token == TokenNameSEMICOLON) {
851 if (token != TokenNameINLINE_HTML) {
852 throwSyntaxError("';' expected after 'unset' statement.");
857 } else if (token == TokenNamefunction) {
858 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
859 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
860 methodDecl.modifiers = AccDefault;
862 functionDefinition(methodDecl);
864 } else if (token == TokenNametry) {
866 if (token != TokenNameLBRACE) {
867 throwSyntaxError("'{' expected in 'try' statement.");
871 if (token != TokenNameRBRACE) {
872 throwSyntaxError("'}' expected in 'try' statement.");
876 } else if (token == TokenNamecatch) {
878 if (token != TokenNameLPAREN) {
879 throwSyntaxError("'(' expected in 'catch' statement.");
882 fully_qualified_class_name();
883 if (token != TokenNameVariable) {
884 throwSyntaxError("Variable expected in 'catch' statement.");
887 if (token != TokenNameRPAREN) {
888 throwSyntaxError("')' expected in 'catch' statement.");
891 if (token != TokenNameLBRACE) {
892 throwSyntaxError("'{' expected in 'catch' statement.");
895 if (token != TokenNameRBRACE) {
897 if (token != TokenNameRBRACE) {
898 throwSyntaxError("'}' expected in 'catch' statement.");
902 additional_catches();
904 } else if (token == TokenNamethrow) {
907 if (token == TokenNameSEMICOLON) {
910 throwSyntaxError("';' expected after 'throw' exxpression.");
913 } else if (token == TokenNamefinal || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) {
914 TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
915 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
916 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
917 typeDecl.name = new char[] { ' ' };
918 // default super class
919 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
920 compilationUnit.types.add(typeDecl);
922 pushOnAstStack(typeDecl);
923 unticked_class_declaration_statement(typeDecl);
924 // classBody(typeDecl);
931 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
932 } else if (token == TokenNameLBRACE) {
934 if (token != TokenNameRBRACE) {
937 if (token == TokenNameRBRACE) {
941 throwSyntaxError("'}' expected.");
944 if (token != TokenNameSEMICOLON) {
947 if (token == TokenNameSEMICOLON) {
951 if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
952 throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
961 private void additional_catches() {
962 while (token == TokenNamecatch) {
964 if (token != TokenNameLPAREN) {
965 throwSyntaxError("'(' expected in 'catch' statement.");
968 fully_qualified_class_name();
969 if (token != TokenNameVariable) {
970 throwSyntaxError("Variable expected in 'catch' statement.");
973 if (token != TokenNameRPAREN) {
974 throwSyntaxError("')' expected in 'catch' statement.");
977 if (token != TokenNameLBRACE) {
978 throwSyntaxError("'{' expected in 'catch' statement.");
982 if (token != TokenNameRBRACE) {
983 throwSyntaxError("'}' expected in 'catch' statement.");
989 private void foreach_variable() {
992 if (token == TokenNameAND) {
998 private void foreach_optional_arg() {
1000 //| T_DOUBLE_ARROW foreach_variable
1001 if (token == TokenNameEQUAL_GREATER) {
1007 private void global_var_list() {
1009 // global_var_list ',' global_var
1013 if (token != TokenNameCOMMA) {
1020 private void global_var() {
1024 //| '$' '{' expr '}'
1025 if (token == TokenNameVariable) {
1027 } else if (token == TokenNameDOLLAR) {
1029 if (token == TokenNameLPAREN) {
1032 if (token != TokenNameLPAREN) {
1033 throwSyntaxError("')' expected in global variable.");
1042 private void static_var_list() {
1044 // static_var_list ',' T_VARIABLE
1045 //| static_var_list ',' T_VARIABLE '=' static_scalar
1047 //| T_VARIABLE '=' static_scalar
1049 if (token == TokenNameVariable) {
1051 if (token == TokenNameEQUAL) {
1055 if (token != TokenNameCOMMA) {
1065 private void unset_variables() {
1068 // | unset_variables ',' unset_variable
1073 if (token != TokenNameCOMMA) {
1080 private final void initializeModifiers() {
1082 this.modifiersSourceStart = -1;
1085 private final void checkAndSetModifiers(int flag) {
1086 this.modifiers |= flag;
1087 if (this.modifiersSourceStart < 0)
1088 this.modifiersSourceStart = this.scanner.startPosition;
1091 private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1092 initializeModifiers();
1093 if (token == TokenNameinterface) {
1094 // interface_entry T_STRING
1095 // interface_extends_list
1096 // '{' class_statement_list '}'
1097 checkAndSetModifiers(AccInterface);
1099 typeDecl.modifiers = this.modifiers;
1100 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1101 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1102 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1103 typeDecl.name = scanner.getCurrentIdentifierSource();
1104 if (token > TokenNameKEYWORD) {
1105 problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
1106 scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
1107 // throwSyntaxError("Don't use a keyword for interface declaration [" + scanner.toStringAction(token) + "].",
1108 // typeDecl.sourceStart, typeDecl.sourceEnd);
1111 interface_extends_list();
1113 typeDecl.name = new char[] { ' ' };
1114 throwSyntaxError("Interface name expected after keyword 'interface'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1118 // class_entry_type T_STRING extends_from
1120 // '{' class_statement_list'}'
1122 typeDecl.modifiers = this.modifiers;
1123 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1124 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1126 //identifier 'extends' identifier
1127 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1128 typeDecl.name = scanner.getCurrentIdentifierSource();
1129 if (token > TokenNameKEYWORD) {
1130 problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
1131 scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
1132 // throwSyntaxError("Don't use a keyword for class declaration [" + scanner.toStringAction(token) + "].",
1133 // typeDecl.sourceStart, typeDecl.sourceEnd);
1138 // | T_EXTENDS fully_qualified_class_name
1139 if (token == TokenNameextends) {
1140 interface_extends_list();
1142 // if (token != TokenNameIdentifier) {
1143 // throwSyntaxError("Class name expected after keyword
1145 // scanner.getCurrentTokenStartPosition(), scanner
1146 // .getCurrentTokenEndPosition());
1151 typeDecl.name = new char[] { ' ' };
1152 throwSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1156 // '{' class_statement_list '}'
1157 if (token == TokenNameLBRACE) {
1159 if (token != TokenNameRBRACE) {
1160 ArrayList list = new ArrayList();
1161 class_statement_list(list);
1162 typeDecl.fields = new FieldDeclaration[list.size()];
1163 for (int i = 0; i < list.size(); i++) {
1164 typeDecl.fields[i] = (FieldDeclaration) list.get(i);
1167 if (token == TokenNameRBRACE) {
1168 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1171 throwSyntaxError("'}' expected at end of class body.");
1174 throwSyntaxError("'{' expected at start of class body.");
1178 private void class_entry_type() {
1180 // | T_ABSTRACT T_CLASS
1181 // | T_FINAL T_CLASS
1182 if (token == TokenNameclass) {
1184 } else if (token == TokenNameabstract) {
1185 checkAndSetModifiers(AccAbstract);
1187 if (token != TokenNameclass) {
1188 throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1191 } else if (token == TokenNamefinal) {
1192 checkAndSetModifiers(AccFinal);
1194 if (token != TokenNameclass) {
1195 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1199 throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1203 private void interface_extends_list() {
1205 // | T_EXTENDS interface_list
1206 if (token == TokenNameextends) {
1212 private void implements_list() {
1214 // | T_IMPLEMENTS interface_list
1215 if (token == TokenNameimplements) {
1221 private void interface_list() {
1223 // fully_qualified_class_name
1224 //| interface_list ',' fully_qualified_class_name
1226 if (token == TokenNameIdentifier) {
1229 throwSyntaxError("Interface name expected after keyword 'implements'.");
1231 if (token != TokenNameCOMMA) {
1238 // private void classBody(TypeDeclaration typeDecl) {
1239 // //'{' [class-element-list] '}'
1240 // if (token == TokenNameLBRACE) {
1242 // if (token != TokenNameRBRACE) {
1243 // class_statement_list();
1245 // if (token == TokenNameRBRACE) {
1246 // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1249 // throwSyntaxError("'}' expected at end of class body.");
1252 // throwSyntaxError("'{' expected at start of class body.");
1255 private void class_statement_list(ArrayList list) {
1257 class_statement(list);
1258 } while (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic
1259 || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar
1260 || token == TokenNameconst);
1263 private void class_statement(ArrayList list) {
1265 // variable_modifiers class_variable_declaration ';'
1266 // | class_constant_declaration ';'
1267 // | method_modifiers T_FUNCTION is_reference T_STRING
1268 // '(' parameter_list ')' method_body
1269 initializeModifiers();
1270 int declarationSourceStart = scanner.getCurrentTokenStartPosition();
1272 if (token == TokenNamevar) {
1273 checkAndSetModifiers(AccPublic);
1274 problemReporter.phpVarDeprecatedWarning(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
1275 referenceContext, compilationUnit.compilationResult);
1277 class_variable_declaration(declarationSourceStart, list);
1278 } else if (token == TokenNameconst) {
1279 checkAndSetModifiers(AccFinal | AccPublic);
1280 class_constant_declaration(declarationSourceStart, list);
1281 if (token != TokenNameSEMICOLON) {
1282 throwSyntaxError("';' expected after class const declaration.");
1286 boolean hasModifiers = member_modifiers();
1287 if (token == TokenNamefunction) {
1288 if (!hasModifiers) {
1289 checkAndSetModifiers(AccPublic);
1291 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1292 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1293 methodDecl.modifiers = this.modifiers;
1295 functionDefinition(methodDecl);
1297 if (!hasModifiers) {
1298 throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1300 class_variable_declaration(declarationSourceStart, list);
1305 private void class_constant_declaration(int declarationSourceStart, ArrayList list) {
1306 // class_constant_declaration ',' T_STRING '=' static_scalar
1307 // | T_CONST T_STRING '=' static_scalar
1308 if (token != TokenNameconst) {
1309 throwSyntaxError("'const' keyword expected in class declaration.");
1314 if (token != TokenNameIdentifier) {
1315 throwSyntaxError("Identifier expected in class const declaration.");
1317 FieldDeclaration fieldDeclaration = new FieldDeclaration(scanner.getCurrentIdentifierSource(), scanner
1318 .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1319 fieldDeclaration.modifiers = this.modifiers;
1320 fieldDeclaration.declarationSourceStart = declarationSourceStart;
1321 fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1322 fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1323 // fieldDeclaration.type
1324 list.add(fieldDeclaration);
1326 if (token != TokenNameEQUAL) {
1327 throwSyntaxError("'=' expected in class const declaration.");
1331 if (token != TokenNameCOMMA) {
1332 break; // while(true)-loop
1338 // private void variable_modifiers() {
1339 // // variable_modifiers:
1340 // // non_empty_member_modifiers
1342 // initializeModifiers();
1343 // if (token == TokenNamevar) {
1344 // checkAndSetModifiers(AccPublic);
1345 // reportSyntaxError(
1346 // "Keyword 'var' is deprecated. Please use 'public' 'private' or
1348 // modifier for field declarations.",
1349 // scanner.getCurrentTokenStartPosition(), scanner
1350 // .getCurrentTokenEndPosition());
1353 // if (!member_modifiers()) {
1354 // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1355 // field declarations.");
1359 // private void method_modifiers() {
1360 // //method_modifiers:
1362 // //| non_empty_member_modifiers
1363 // initializeModifiers();
1364 // if (!member_modifiers()) {
1365 // checkAndSetModifiers(AccPublic);
1368 private boolean member_modifiers() {
1375 boolean foundToken = false;
1377 if (token == TokenNamepublic) {
1378 checkAndSetModifiers(AccPublic);
1381 } else if (token == TokenNameprotected) {
1382 checkAndSetModifiers(AccProtected);
1385 } else if (token == TokenNameprivate) {
1386 checkAndSetModifiers(AccPrivate);
1389 } else if (token == TokenNamestatic) {
1390 checkAndSetModifiers(AccStatic);
1393 } else if (token == TokenNameabstract) {
1394 checkAndSetModifiers(AccAbstract);
1397 } else if (token == TokenNamefinal) {
1398 checkAndSetModifiers(AccFinal);
1408 private void class_variable_declaration(int declarationSourceStart, ArrayList list) {
1409 // class_variable_declaration:
1410 // class_variable_declaration ',' T_VARIABLE
1411 // | class_variable_declaration ',' T_VARIABLE '=' static_scalar
1413 // | T_VARIABLE '=' static_scalar
1414 char[] classVariable;
1416 if (token == TokenNameVariable) {
1417 classVariable = scanner.getCurrentIdentifierSource();
1418 // indexManager.addIdentifierInformation('v', classVariable, buf, -1, -1);
1419 FieldDeclaration fieldDeclaration = new FieldDeclaration(classVariable, scanner.getCurrentTokenStartPosition(), scanner
1420 .getCurrentTokenEndPosition());
1421 fieldDeclaration.modifiers = this.modifiers;
1422 fieldDeclaration.declarationSourceStart = declarationSourceStart;
1423 fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1424 fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1425 // fieldDeclaration.type
1426 list.add(fieldDeclaration);
1428 if (token == TokenNameEQUAL) {
1433 // if (token == TokenNamethis) {
1434 // throwSyntaxError("'$this' not allowed after keyword 'public'
1435 // 'protected' 'private' 'var'.");
1437 throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
1439 if (token != TokenNameCOMMA) {
1444 if (token != TokenNameSEMICOLON) {
1445 throwSyntaxError("';' expected after field declaration.");
1450 private void functionDefinition(MethodDeclaration methodDecl) {
1451 boolean isAbstract = false;
1453 compilationUnit.types.add(methodDecl);
1455 ASTNode node = astStack[astPtr];
1456 if (node instanceof TypeDeclaration) {
1457 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1458 if (typeDecl.methods == null) {
1459 typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
1461 AbstractMethodDeclaration[] newMethods;
1462 System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1,
1463 typeDecl.methods.length);
1464 newMethods[0] = methodDecl;
1465 typeDecl.methods = newMethods;
1467 if ((typeDecl.modifiers & AccAbstract) == AccAbstract) {
1469 } else if ((typeDecl.modifiers & AccInterface) == AccInterface) {
1474 functionDeclarator(methodDecl);
1475 if (token == TokenNameSEMICOLON) {
1477 throwSyntaxError("Body declaration expected for method: " + new String(methodDecl.selector));
1482 functionBody(methodDecl);
1485 private void functionDeclarator(MethodDeclaration methodDecl) {
1486 //identifier '(' [parameter-list] ')'
1487 if (token == TokenNameAND) {
1490 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1491 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1492 if (Scanner.isIdentifierOrKeyword(token)) {
1493 methodDecl.selector = scanner.getCurrentIdentifierSource();
1494 if (token > TokenNameKEYWORD) {
1495 problemReporter.phpKeywordWarning(new String[] { scanner.toStringAction(token) }, scanner.getCurrentTokenStartPosition(),
1496 scanner.getCurrentTokenEndPosition(), referenceContext, compilationUnit.compilationResult);
1497 // reportSyntaxWarning("Don't use keyword for function declaration [" + scanner.toStringAction(token) + "].",
1498 // scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1501 if (token == TokenNameLPAREN) {
1504 throwSyntaxError("'(' expected in function declaration.");
1506 if (token != TokenNameRPAREN) {
1509 if (token != TokenNameRPAREN) {
1510 throwSyntaxError("')' expected in function declaration.");
1512 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1516 methodDecl.selector = "<undefined>".toCharArray();
1517 throwSyntaxError("Function name expected after keyword 'function'.");
1522 private void parameter_list() {
1523 // non_empty_parameter_list
1525 non_empty_parameter_list(true);
1528 private void non_empty_parameter_list(boolean empty_allowed) {
1529 // optional_class_type T_VARIABLE
1530 // | optional_class_type '&' T_VARIABLE
1531 // | optional_class_type '&' T_VARIABLE '=' static_scalar
1532 // | optional_class_type T_VARIABLE '=' static_scalar
1533 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE
1534 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
1535 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
1537 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
1539 if (token == TokenNameIdentifier || token == TokenNameVariable || token == TokenNameAND) {
1541 if (token == TokenNameIdentifier) {
1544 if (token == TokenNameAND) {
1547 if (token == TokenNameVariable) {
1549 if (token == TokenNameEQUAL) {
1554 throwSyntaxError("Variable expected in parameter list.");
1556 if (token != TokenNameCOMMA) {
1563 if (!empty_allowed) {
1564 throwSyntaxError("Identifier expected in parameter list.");
1568 private void optional_class_type() {
1573 private void parameterDeclaration() {
1575 //variable-reference
1576 if (token == TokenNameAND) {
1581 throwSyntaxError("Variable expected after reference operator '&'.");
1584 //variable '=' constant
1585 if (token == TokenNameVariable) {
1587 if (token == TokenNameEQUAL) {
1593 // if (token == TokenNamethis) {
1594 // throwSyntaxError("Reserved word '$this' not allowed in parameter
1599 private void labeledStatementList() {
1600 if (token != TokenNamecase && token != TokenNamedefault) {
1601 throwSyntaxError("'case' or 'default' expected.");
1604 if (token == TokenNamecase) {
1606 expr(); //constant();
1607 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1609 if (token == TokenNamecase || token == TokenNamedefault) {
1610 // empty case statement ?
1615 // else if (token == TokenNameSEMICOLON) {
1617 // "':' expected after 'case' keyword (Found token: " +
1618 // scanner.toStringAction(token) + ")",
1619 // scanner.getCurrentTokenStartPosition(),
1620 // scanner.getCurrentTokenEndPosition(),
1623 // if (token == TokenNamecase) { // empty case statement ?
1629 throwSyntaxError("':' character expected after 'case' constant (Found token: " + scanner.toStringAction(token) + ")");
1631 } else { // TokenNamedefault
1633 if (token == TokenNameCOLON) {
1635 if (token == TokenNameRBRACE) {
1636 // empty default case
1639 if (token != TokenNamecase) {
1643 throwSyntaxError("':' character expected after 'default'.");
1646 } while (token == TokenNamecase || token == TokenNamedefault);
1649 // public void labeledStatement() {
1650 // if (token == TokenNamecase) {
1653 // if (token == TokenNameDDOT) {
1657 // throwSyntaxError("':' character after 'case' constant expected.");
1660 // } else if (token == TokenNamedefault) {
1662 // if (token == TokenNameDDOT) {
1666 // throwSyntaxError("':' character after 'default' expected.");
1671 // public void expressionStatement() {
1673 // private void inclusionStatement() {
1675 // public void compoundStatement() {
1677 // public void selectionStatement() {
1680 // public void iterationStatement() {
1683 // public void jumpStatement() {
1686 // public void outputStatement() {
1689 // public void scopeStatement() {
1692 // public void flowStatement() {
1695 // public void definitionStatement() {
1697 private void ifStatement() {
1698 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1699 if (token == TokenNameCOLON) {
1701 if (token != TokenNameendif) {
1706 if (token == TokenNameCOLON) {
1708 if (token != TokenNameendif) {
1712 if (token == TokenNameif) { //'else if'
1714 elseifStatementList();
1716 throwSyntaxError("':' expected after 'else'.");
1720 case TokenNameelseif:
1722 elseifStatementList();
1726 if (token != TokenNameendif) {
1727 throwSyntaxError("'endif' expected.");
1730 if (token != TokenNameSEMICOLON) {
1731 throwSyntaxError("';' expected after if-statement.");
1735 // statement [else-statement]
1736 statement(TokenNameEOF);
1737 if (token == TokenNameelseif) {
1739 if (token == TokenNameLPAREN) {
1742 throwSyntaxError("'(' expected after 'elseif' keyword.");
1745 if (token == TokenNameRPAREN) {
1748 throwSyntaxError("')' expected after 'elseif' condition.");
1751 } else if (token == TokenNameelse) {
1753 statement(TokenNameEOF);
1758 private void elseifStatementList() {
1764 if (token == TokenNameCOLON) {
1766 if (token != TokenNameendif) {
1771 if (token == TokenNameif) { //'else if'
1774 throwSyntaxError("':' expected after 'else'.");
1778 case TokenNameelseif:
1787 private void elseifStatement() {
1788 if (token == TokenNameLPAREN) {
1791 if (token != TokenNameRPAREN) {
1792 throwSyntaxError("')' expected in else-if-statement.");
1795 if (token != TokenNameCOLON) {
1796 throwSyntaxError("':' expected in else-if-statement.");
1799 if (token != TokenNameendif) {
1805 private void switchStatement() {
1806 if (token == TokenNameCOLON) {
1807 // ':' [labeled-statement-list] 'endswitch' ';'
1809 labeledStatementList();
1810 if (token != TokenNameendswitch) {
1811 throwSyntaxError("'endswitch' expected.");
1814 if (token != TokenNameSEMICOLON) {
1815 throwSyntaxError("';' expected after switch-statement.");
1819 // '{' [labeled-statement-list] '}'
1820 if (token != TokenNameLBRACE) {
1821 throwSyntaxError("'{' expected in switch statement.");
1824 if (token != TokenNameRBRACE) {
1825 labeledStatementList();
1827 if (token != TokenNameRBRACE) {
1828 throwSyntaxError("'}' expected in switch statement.");
1834 private void forStatement() {
1835 if (token == TokenNameCOLON) {
1838 if (token != TokenNameendfor) {
1839 throwSyntaxError("'endfor' expected.");
1842 if (token != TokenNameSEMICOLON) {
1843 throwSyntaxError("';' expected after for-statement.");
1847 statement(TokenNameEOF);
1851 private void whileStatement() {
1852 // ':' statement-list 'endwhile' ';'
1853 if (token == TokenNameCOLON) {
1856 if (token != TokenNameendwhile) {
1857 throwSyntaxError("'endwhile' expected.");
1860 if (token != TokenNameSEMICOLON) {
1861 throwSyntaxError("';' expected after while-statement.");
1865 statement(TokenNameEOF);
1869 private void foreachStatement() {
1870 if (token == TokenNameCOLON) {
1873 if (token != TokenNameendforeach) {
1874 throwSyntaxError("'endforeach' expected.");
1877 if (token != TokenNameSEMICOLON) {
1878 throwSyntaxError("';' expected after foreach-statement.");
1882 statement(TokenNameEOF);
1886 // private void exitStatus() {
1887 // if (token == TokenNameLPAREN) {
1890 // throwSyntaxError("'(' expected in 'exit-status'.");
1892 // if (token != TokenNameRPAREN) {
1895 // if (token == TokenNameRPAREN) {
1898 // throwSyntaxError("')' expected after 'exit-status'.");
1901 private void expressionList() {
1904 if (token == TokenNameCOMMA) {
1912 private Expression expr() {
1914 // | expr_without_variable
1915 // if (token!=TokenNameEOF) {
1916 if (Scanner.TRACE) {
1917 System.out.println("TRACE: expr()");
1919 return expr_without_variable(true);
1923 private Expression expr_without_variable(boolean only_variable) {
1924 Expression expression = new Expression();
1925 expression.sourceStart = scanner.getCurrentTokenStartPosition();
1926 // default, may be overwritten
1927 expression.sourceEnd = scanner.getCurrentTokenEndPosition();
1928 // internal_functions_in_yacc
1937 // | T_INC rw_variable
1938 // | T_DEC rw_variable
1939 // | T_INT_CAST expr
1940 // | T_DOUBLE_CAST expr
1941 // | T_STRING_CAST expr
1942 // | T_ARRAY_CAST expr
1943 // | T_OBJECT_CAST expr
1944 // | T_BOOL_CAST expr
1945 // | T_UNSET_CAST expr
1946 // | T_EXIT exit_expr
1948 // | T_ARRAY '(' array_pair_list ')'
1949 // | '`' encaps_list '`'
1950 // | T_LIST '(' assignment_list ')' '=' expr
1951 // | T_NEW class_name_reference ctor_arguments
1952 // | variable '=' expr
1953 // | variable '=' '&' variable
1954 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
1955 // | variable T_PLUS_EQUAL expr
1956 // | variable T_MINUS_EQUAL expr
1957 // | variable T_MUL_EQUAL expr
1958 // | variable T_DIV_EQUAL expr
1959 // | variable T_CONCAT_EQUAL expr
1960 // | variable T_MOD_EQUAL expr
1961 // | variable T_AND_EQUAL expr
1962 // | variable T_OR_EQUAL expr
1963 // | variable T_XOR_EQUAL expr
1964 // | variable T_SL_EQUAL expr
1965 // | variable T_SR_EQUAL expr
1966 // | rw_variable T_INC
1967 // | rw_variable T_DEC
1968 // | expr T_BOOLEAN_OR expr
1969 // | expr T_BOOLEAN_AND expr
1970 // | expr T_LOGICAL_OR expr
1971 // | expr T_LOGICAL_AND expr
1972 // | expr T_LOGICAL_XOR expr
1984 // | expr T_IS_IDENTICAL expr
1985 // | expr T_IS_NOT_IDENTICAL expr
1986 // | expr T_IS_EQUAL expr
1987 // | expr T_IS_NOT_EQUAL expr
1989 // | expr T_IS_SMALLER_OR_EQUAL expr
1991 // | expr T_IS_GREATER_OR_EQUAL expr
1992 // | expr T_INSTANCEOF class_name_reference
1993 // | expr '?' expr ':' expr
1994 if (Scanner.TRACE) {
1995 System.out.println("TRACE: expr_without_variable() PART 1");
1998 case TokenNameisset:
1999 case TokenNameempty:
2001 case TokenNameinclude:
2002 case TokenNameinclude_once:
2003 case TokenNamerequire:
2004 case TokenNamerequire_once:
2005 internal_functions_in_yacc();
2008 case TokenNameLPAREN:
2011 if (token == TokenNameRPAREN) {
2014 throwSyntaxError("')' expected in expression.");
2024 // | T_INT_CAST expr
2025 // | T_DOUBLE_CAST expr
2026 // | T_STRING_CAST expr
2027 // | T_ARRAY_CAST expr
2028 // | T_OBJECT_CAST expr
2029 // | T_BOOL_CAST expr
2030 // | T_UNSET_CAST expr
2031 case TokenNameclone:
2032 case TokenNameprint:
2035 case TokenNameMINUS:
2037 case TokenNameTWIDDLE:
2038 case TokenNameintCAST:
2039 case TokenNamedoubleCAST:
2040 case TokenNamestringCAST:
2041 case TokenNamearrayCAST:
2042 case TokenNameobjectCAST:
2043 case TokenNameboolCAST:
2044 case TokenNameunsetCAST:
2054 //| T_STRING_VARNAME
2056 //| T_START_HEREDOC encaps_list T_END_HEREDOC
2057 // | '`' encaps_list '`'
2059 // | '`' encaps_list '`'
2060 case TokenNameEncapsedString0:
2061 scanner.encapsedStringStack.push(new Character('`'));
2064 if (token == TokenNameEncapsedString0) {
2067 if (token != TokenNameEncapsedString0) {
2068 throwSyntaxError("\'`\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2072 scanner.encapsedStringStack.pop();
2076 // | '\'' encaps_list '\''
2077 case TokenNameEncapsedString1:
2078 scanner.encapsedStringStack.push(new Character('\''));
2081 if (token == TokenNameEncapsedString1) {
2084 if (token != TokenNameEncapsedString1) {
2085 throwSyntaxError("\'\'\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2089 scanner.encapsedStringStack.pop();
2093 //| '"' encaps_list '"'
2094 case TokenNameEncapsedString2:
2095 scanner.encapsedStringStack.push(new Character('"'));
2098 if (token == TokenNameEncapsedString2) {
2101 if (token != TokenNameEncapsedString2) {
2102 throwSyntaxError("'\"' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2106 scanner.encapsedStringStack.pop();
2110 case TokenNameIntegerLiteral:
2111 case TokenNameDoubleLiteral:
2112 case TokenNameStringDoubleQuote:
2113 case TokenNameStringSingleQuote:
2114 case TokenNameStringInterpolated:
2117 case TokenNameCLASS_C:
2118 case TokenNameMETHOD_C:
2119 case TokenNameFUNC_C:
2122 case TokenNameHEREDOC:
2125 case TokenNamearray:
2126 // T_ARRAY '(' array_pair_list ')'
2128 if (token == TokenNameLPAREN) {
2130 if (token == TokenNameRPAREN) {
2135 if (token != TokenNameRPAREN) {
2136 throwSyntaxError("')' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2140 throwSyntaxError("'(' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2144 // | T_LIST '(' assignment_list ')' '=' expr
2146 if (token == TokenNameLPAREN) {
2149 if (token != TokenNameRPAREN) {
2150 throwSyntaxError("')' expected after 'list' keyword.");
2153 if (token != TokenNameEQUAL) {
2154 throwSyntaxError("'=' expected after 'list' keyword.");
2159 throwSyntaxError("'(' expected after 'list' keyword.");
2163 // | T_NEW class_name_reference ctor_arguments
2165 class_name_reference();
2168 // | T_INC rw_variable
2169 // | T_DEC rw_variable
2170 case TokenNamePLUS_PLUS:
2171 case TokenNameMINUS_MINUS:
2175 // | variable '=' expr
2176 // | variable '=' '&' variable
2177 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2178 // | variable T_PLUS_EQUAL expr
2179 // | variable T_MINUS_EQUAL expr
2180 // | variable T_MUL_EQUAL expr
2181 // | variable T_DIV_EQUAL expr
2182 // | variable T_CONCAT_EQUAL expr
2183 // | variable T_MOD_EQUAL expr
2184 // | variable T_AND_EQUAL expr
2185 // | variable T_OR_EQUAL expr
2186 // | variable T_XOR_EQUAL expr
2187 // | variable T_SL_EQUAL expr
2188 // | variable T_SR_EQUAL expr
2189 // | rw_variable T_INC
2190 // | rw_variable T_DEC
2191 case TokenNameIdentifier:
2192 case TokenNameVariable:
2193 case TokenNameDOLLAR:
2196 case TokenNameEQUAL:
2198 if (token == TokenNameAND) {
2200 if (token == TokenNamenew) {
2201 // | variable '=' '&' T_NEW class_name_reference
2204 class_name_reference();
2213 case TokenNamePLUS_EQUAL:
2214 case TokenNameMINUS_EQUAL:
2215 case TokenNameMULTIPLY_EQUAL:
2216 case TokenNameDIVIDE_EQUAL:
2217 case TokenNameDOT_EQUAL:
2218 case TokenNameREMAINDER_EQUAL:
2219 case TokenNameAND_EQUAL:
2220 case TokenNameOR_EQUAL:
2221 case TokenNameXOR_EQUAL:
2222 case TokenNameRIGHT_SHIFT_EQUAL:
2223 case TokenNameLEFT_SHIFT_EQUAL:
2227 case TokenNamePLUS_PLUS:
2228 case TokenNameMINUS_MINUS:
2232 if (!only_variable) {
2233 throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "').");
2238 if (token != TokenNameINLINE_HTML) {
2239 if (token > TokenNameKEYWORD) {
2243 throwSyntaxError("Error in expression (found token '" + scanner.toStringAction(token) + "').");
2248 if (Scanner.TRACE) {
2249 System.out.println("TRACE: expr_without_variable() PART 2");
2251 // | expr T_BOOLEAN_OR expr
2252 // | expr T_BOOLEAN_AND expr
2253 // | expr T_LOGICAL_OR expr
2254 // | expr T_LOGICAL_AND expr
2255 // | expr T_LOGICAL_XOR expr
2267 // | expr T_IS_IDENTICAL expr
2268 // | expr T_IS_NOT_IDENTICAL expr
2269 // | expr T_IS_EQUAL expr
2270 // | expr T_IS_NOT_EQUAL expr
2272 // | expr T_IS_SMALLER_OR_EQUAL expr
2274 // | expr T_IS_GREATER_OR_EQUAL expr
2277 case TokenNameOR_OR:
2278 case TokenNameAND_AND:
2287 case TokenNameMINUS:
2288 case TokenNameMULTIPLY:
2289 case TokenNameDIVIDE:
2290 case TokenNameREMAINDER:
2291 case TokenNameLEFT_SHIFT:
2292 case TokenNameRIGHT_SHIFT:
2293 case TokenNameEQUAL_EQUAL_EQUAL:
2294 case TokenNameNOT_EQUAL_EQUAL:
2295 case TokenNameEQUAL_EQUAL:
2296 case TokenNameNOT_EQUAL:
2298 case TokenNameLESS_EQUAL:
2299 case TokenNameGREATER:
2300 case TokenNameGREATER_EQUAL:
2304 // | expr T_INSTANCEOF class_name_reference
2305 // | expr '?' expr ':' expr
2306 case TokenNameinstanceof:
2308 class_name_reference();
2310 case TokenNameQUESTION:
2313 if (token == TokenNameCOLON) {
2324 private void class_name_reference() {
2325 // class_name_reference:
2327 //| dynamic_class_name_reference
2328 if (Scanner.TRACE) {
2329 System.out.println("TRACE: class_name_reference()");
2331 if (token == TokenNameIdentifier) {
2334 dynamic_class_name_reference();
2338 private void dynamic_class_name_reference() {
2339 //dynamic_class_name_reference:
2340 // base_variable T_OBJECT_OPERATOR object_property
2341 // dynamic_class_name_variable_properties
2343 if (Scanner.TRACE) {
2344 System.out.println("TRACE: dynamic_class_name_reference()");
2347 if (token == TokenNameMINUS_GREATER) {
2350 dynamic_class_name_variable_properties();
2354 private void dynamic_class_name_variable_properties() {
2355 // dynamic_class_name_variable_properties:
2356 // dynamic_class_name_variable_properties
2357 // dynamic_class_name_variable_property
2359 if (Scanner.TRACE) {
2360 System.out.println("TRACE: dynamic_class_name_variable_properties()");
2362 while (token == TokenNameMINUS_GREATER) {
2363 dynamic_class_name_variable_property();
2367 private void dynamic_class_name_variable_property() {
2368 // dynamic_class_name_variable_property:
2369 // T_OBJECT_OPERATOR object_property
2370 if (Scanner.TRACE) {
2371 System.out.println("TRACE: dynamic_class_name_variable_property()");
2373 if (token == TokenNameMINUS_GREATER) {
2379 private void ctor_arguments() {
2382 //| '(' function_call_parameter_list ')'
2383 if (token == TokenNameLPAREN) {
2385 if (token == TokenNameRPAREN) {
2389 non_empty_function_call_parameter_list();
2390 if (token != TokenNameRPAREN) {
2391 throwSyntaxError("')' expected in ctor_arguments.");
2397 private void assignment_list() {
2399 // assignment_list ',' assignment_list_element
2400 //| assignment_list_element
2402 assignment_list_element();
2403 if (token != TokenNameCOMMA) {
2410 private void assignment_list_element() {
2411 //assignment_list_element:
2413 //| T_LIST '(' assignment_list ')'
2415 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2418 if (token == TokenNamelist) {
2420 if (token == TokenNameLPAREN) {
2423 if (token != TokenNameRPAREN) {
2424 throwSyntaxError("')' expected after 'list' keyword.");
2428 throwSyntaxError("'(' expected after 'list' keyword.");
2434 private void array_pair_list() {
2437 //| non_empty_array_pair_list possible_comma
2438 non_empty_array_pair_list();
2439 if (token == TokenNameCOMMA) {
2444 private void non_empty_array_pair_list() {
2445 //non_empty_array_pair_list:
2446 // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2447 //| non_empty_array_pair_list ',' expr
2448 //| expr T_DOUBLE_ARROW expr
2450 //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2451 //| non_empty_array_pair_list ',' '&' w_variable
2452 //| expr T_DOUBLE_ARROW '&' w_variable
2455 if (token == TokenNameAND) {
2460 if (token == TokenNameAND) {
2463 } else if (token == TokenNameEQUAL_GREATER) {
2465 if (token == TokenNameAND) {
2473 if (token != TokenNameCOMMA) {
2477 if (token == TokenNameRPAREN) {
2483 // private void variableList() {
2486 // if (token == TokenNameCOMMA) {
2493 private void variable_without_objects() {
2494 // variable_without_objects:
2495 // reference_variable
2496 // | simple_indirect_reference reference_variable
2497 if (Scanner.TRACE) {
2498 System.out.println("TRACE: variable_without_objects()");
2500 while (token == TokenNameDOLLAR) {
2503 reference_variable();
2506 private void function_call() {
2508 // T_STRING '(' function_call_parameter_list ')'
2509 //| class_constant '(' function_call_parameter_list ')'
2510 //| static_member '(' function_call_parameter_list ')'
2511 //| variable_without_objects '(' function_call_parameter_list ')'
2512 char[] defineName = null;
2513 char[] ident = null;
2516 if (Scanner.TRACE) {
2517 System.out.println("TRACE: function_call()");
2519 if (token == TokenNameIdentifier) {
2520 ident = scanner.getCurrentIdentifierSource();
2522 startPos = scanner.getCurrentTokenStartPosition();
2523 endPos = scanner.getCurrentTokenEndPosition();
2526 case TokenNamePAAMAYIM_NEKUDOTAYIM:
2530 if (token == TokenNameIdentifier) {
2535 variable_without_objects();
2540 variable_without_objects();
2542 if (token != TokenNameLPAREN) {
2543 if (defineName != null) {
2544 // does this identifier contain only uppercase characters?
2545 if (defineName.length == 3) {
2546 if (defineName[0] == 'd' && defineName[1] == 'i' && defineName[2] == 'e') {
2549 } else if (defineName.length == 4) {
2550 if (defineName[0] == 't' && defineName[1] == 'r' && defineName[2] == 'u' && defineName[3] == 'e') {
2552 } else if (defineName[0] == 'n' && defineName[1] == 'u' && defineName[2] == 'l' && defineName[3] == 'l') {
2555 } else if (defineName.length == 5) {
2556 if (defineName[0] == 'f' && defineName[1] == 'a' && defineName[2] == 'l' && defineName[3] == 's' && defineName[4] == 'e') {
2560 if (defineName != null) {
2561 for (int i = 0; i < defineName.length; i++) {
2562 if (Character.isLowerCase(defineName[i])) {
2563 problemReporter.phpUppercaseIdentifierWarning(startPos, endPos, referenceContext, compilationUnit.compilationResult);
2569 // TODO is this ok ?
2571 // throwSyntaxError("'(' expected in function call.");
2574 if (token == TokenNameRPAREN) {
2578 non_empty_function_call_parameter_list();
2579 if (token != TokenNameRPAREN) {
2580 String functionName;
2581 if (ident == null) {
2582 functionName = new String(" ");
2584 functionName = new String(ident);
2586 throwSyntaxError("')' expected in function call (" + functionName + ").");
2591 // private void function_call_parameter_list() {
2592 // function_call_parameter_list:
2593 // non_empty_function_call_parameter_list { $$ = $1; }
2596 private void non_empty_function_call_parameter_list() {
2597 //non_empty_function_call_parameter_list:
2598 // expr_without_variable
2601 // | non_empty_function_call_parameter_list ',' expr_without_variable
2602 // | non_empty_function_call_parameter_list ',' variable
2603 // | non_empty_function_call_parameter_list ',' '&' w_variable
2604 if (Scanner.TRACE) {
2605 System.out.println("TRACE: non_empty_function_call_parameter_list()");
2608 if (token == TokenNameAND) {
2612 // if (token == TokenNameIdentifier || token ==
2613 // TokenNameVariable
2614 // || token == TokenNameDOLLAR) {
2617 expr_without_variable(true);
2620 if (token != TokenNameCOMMA) {
2627 private void fully_qualified_class_name() {
2628 if (token == TokenNameIdentifier) {
2631 throwSyntaxError("Class name expected.");
2635 private void static_member() {
2637 // fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
2638 // variable_without_objects
2639 if (Scanner.TRACE) {
2640 System.out.println("TRACE: static_member()");
2642 fully_qualified_class_name();
2643 if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
2644 throwSyntaxError("'::' expected after class name (static_member).");
2647 variable_without_objects();
2650 private void base_variable_with_function_calls() {
2651 // base_variable_with_function_calls:
2654 boolean functionCall = false;
2655 if (Scanner.TRACE) {
2656 System.out.println("TRACE: base_variable_with_function_calls()");
2658 // if (token == TokenNameIdentifier) {
2659 // functionCall = true;
2660 // } else if (token == TokenNameVariable) {
2661 // int tempToken = token;
2662 // int tempPosition = scanner.currentPosition;
2664 // if (token == TokenNameLPAREN) {
2665 // functionCall = true;
2667 // token = tempToken;
2668 // scanner.currentPosition = tempPosition;
2669 // scanner.phpMode = true;
2671 // if (functionCall) {
2678 private void base_variable() {
2680 // reference_variable
2681 // | simple_indirect_reference reference_variable
2683 if (Scanner.TRACE) {
2684 System.out.println("TRACE: base_variable()");
2686 if (token == TokenNameIdentifier) {
2689 while (token == TokenNameDOLLAR) {
2692 reference_variable();
2696 // private void simple_indirect_reference() {
2697 // // simple_indirect_reference:
2699 // //| simple_indirect_reference '$'
2701 private void reference_variable() {
2702 // reference_variable:
2703 // reference_variable '[' dim_offset ']'
2704 // | reference_variable '{' expr '}'
2705 // | compound_variable
2706 if (Scanner.TRACE) {
2707 System.out.println("TRACE: reference_variable()");
2709 compound_variable();
2711 if (token == TokenNameLBRACE) {
2714 if (token != TokenNameRBRACE) {
2715 throwSyntaxError("'}' expected in reference variable.");
2718 } else if (token == TokenNameLBRACKET) {
2720 if (token != TokenNameRBRACKET) {
2723 if (token != TokenNameRBRACKET) {
2724 throwSyntaxError("']' expected in reference variable.");
2734 private void compound_variable() {
2735 // compound_variable:
2737 // | '$' '{' expr '}'
2738 if (Scanner.TRACE) {
2739 System.out.println("TRACE: compound_variable()");
2741 if (token == TokenNameVariable) {
2744 // because of simple_indirect_reference
2745 while (token == TokenNameDOLLAR) {
2748 if (token != TokenNameLBRACE) {
2749 throwSyntaxError("'{' expected after compound variable token '$'.");
2753 if (token != TokenNameRBRACE) {
2754 throwSyntaxError("'}' expected after compound variable token '$'.");
2760 // private void dim_offset() {
2766 private void object_property() {
2769 //| variable_without_objects
2770 if (Scanner.TRACE) {
2771 System.out.println("TRACE: object_property()");
2773 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2774 variable_without_objects();
2780 private void object_dim_list() {
2782 // object_dim_list '[' dim_offset ']'
2783 //| object_dim_list '{' expr '}'
2785 if (Scanner.TRACE) {
2786 System.out.println("TRACE: object_dim_list()");
2790 if (token == TokenNameLBRACE) {
2793 if (token != TokenNameRBRACE) {
2794 throwSyntaxError("'}' expected in object_dim_list.");
2797 } else if (token == TokenNameLBRACKET) {
2799 if (token == TokenNameRBRACKET) {
2804 if (token != TokenNameRBRACKET) {
2805 throwSyntaxError("']' expected in object_dim_list.");
2814 private void variable_name() {
2818 if (Scanner.TRACE) {
2819 System.out.println("TRACE: variable_name()");
2821 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
2822 if (token > TokenNameKEYWORD) {
2823 // TODO show a warning "Keyword used as variable" ?
2827 if (token != TokenNameLBRACE) {
2828 throwSyntaxError("'{' expected in variable name.");
2832 if (token != TokenNameRBRACE) {
2833 throwSyntaxError("'}' expected in variable name.");
2839 private void r_variable() {
2843 private void w_variable() {
2847 private void rw_variable() {
2851 private void variable() {
2853 // base_variable_with_function_calls T_OBJECT_OPERATOR
2854 // object_property method_or_not variable_properties
2855 // | base_variable_with_function_calls
2856 base_variable_with_function_calls();
2857 if (token == TokenNameMINUS_GREATER) {
2861 variable_properties();
2863 // if (token == TokenNameDOLLAR_LBRACE) {
2867 // if (token != TokenNameRBRACE) {
2868 // throwSyntaxError("'}' expected after indirect variable token '${'.");
2872 // if (token == TokenNameVariable) {
2874 // if (token == TokenNameLBRACKET) {
2877 // if (token != TokenNameRBRACKET) {
2878 // throwSyntaxError("']' expected in variable-list.");
2881 // } else if (token == TokenNameEQUAL) {
2886 // throwSyntaxError("$-variable expected in variable-list.");
2891 private void variable_properties() {
2892 // variable_properties:
2893 // variable_properties variable_property
2895 while (token == TokenNameMINUS_GREATER) {
2896 variable_property();
2900 private void variable_property() {
2901 // variable_property:
2902 // T_OBJECT_OPERATOR object_property method_or_not
2903 if (Scanner.TRACE) {
2904 System.out.println("TRACE: variable_property()");
2906 if (token == TokenNameMINUS_GREATER) {
2911 throwSyntaxError("'->' expected in variable_property.");
2915 private void method_or_not() {
2917 // '(' function_call_parameter_list ')'
2919 if (Scanner.TRACE) {
2920 System.out.println("TRACE: method_or_not()");
2922 if (token == TokenNameLPAREN) {
2924 if (token == TokenNameRPAREN) {
2928 non_empty_function_call_parameter_list();
2929 if (token != TokenNameRPAREN) {
2930 throwSyntaxError("')' expected in method_or_not.");
2936 private void exit_expr() {
2940 if (token != TokenNameLPAREN) {
2944 if (token == TokenNameRPAREN) {
2949 if (token != TokenNameRPAREN) {
2950 throwSyntaxError("')' expected after keyword 'exit'");
2955 private void encaps_list() {
2956 // encaps_list encaps_var
2957 // | encaps_list T_STRING
2958 // | encaps_list T_NUM_STRING
2959 // | encaps_list T_ENCAPSED_AND_WHITESPACE
2960 // | encaps_list T_CHARACTER
2961 // | encaps_list T_BAD_CHARACTER
2962 // | encaps_list '['
2963 // | encaps_list ']'
2964 // | encaps_list '{'
2965 // | encaps_list '}'
2966 // | encaps_list T_OBJECT_OPERATOR
2970 case TokenNameSTRING:
2973 case TokenNameLBRACE:
2974 // scanner.encapsedStringStack.pop();
2977 case TokenNameRBRACE:
2978 // scanner.encapsedStringStack.pop();
2981 case TokenNameLBRACKET:
2982 // scanner.encapsedStringStack.pop();
2985 case TokenNameRBRACKET:
2986 // scanner.encapsedStringStack.pop();
2989 case TokenNameMINUS_GREATER:
2990 // scanner.encapsedStringStack.pop();
2993 case TokenNameVariable:
2994 case TokenNameDOLLAR_LBRACE:
2995 case TokenNameLBRACE_DOLLAR:
2999 char encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
3000 if (encapsedChar == '$') {
3001 scanner.encapsedStringStack.pop();
3002 encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
3003 switch (encapsedChar) {
3005 if (token == TokenNameEncapsedString0) {
3008 token = TokenNameSTRING;
3011 if (token == TokenNameEncapsedString1) {
3014 token = TokenNameSTRING;
3017 if (token == TokenNameEncapsedString2) {
3020 token = TokenNameSTRING;
3029 private void encaps_var() {
3031 // | T_VARIABLE '[' encaps_var_offset ']'
3032 // | T_VARIABLE T_OBJECT_OPERATOR T_STRING
3033 // | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
3034 // | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
3035 // | T_CURLY_OPEN variable '}'
3037 case TokenNameVariable:
3039 if (token == TokenNameLBRACKET) {
3041 expr(); //encaps_var_offset();
3042 if (token != TokenNameRBRACKET) {
3043 throwSyntaxError("']' expected after variable.");
3045 // scanner.encapsedStringStack.pop();
3048 } else if (token == TokenNameMINUS_GREATER) {
3050 if (token != TokenNameIdentifier) {
3051 throwSyntaxError("Identifier expected after '->'.");
3053 // scanner.encapsedStringStack.pop();
3057 // // scanner.encapsedStringStack.pop();
3058 // int tempToken = TokenNameSTRING;
3059 // if (!scanner.encapsedStringStack.isEmpty()
3060 // && (token == TokenNameEncapsedString0
3061 // || token == TokenNameEncapsedString1
3062 // || token == TokenNameEncapsedString2 || token ==
3063 // TokenNameERROR)) {
3064 // char encapsedChar = ((Character)
3065 // scanner.encapsedStringStack.peek())
3068 // case TokenNameEncapsedString0 :
3069 // if (encapsedChar == '`') {
3070 // tempToken = TokenNameEncapsedString0;
3073 // case TokenNameEncapsedString1 :
3074 // if (encapsedChar == '\'') {
3075 // tempToken = TokenNameEncapsedString1;
3078 // case TokenNameEncapsedString2 :
3079 // if (encapsedChar == '"') {
3080 // tempToken = TokenNameEncapsedString2;
3083 // case TokenNameERROR :
3084 // if (scanner.source[scanner.currentPosition - 1] == '\\') {
3085 // scanner.currentPosition--;
3091 // token = tempToken;
3094 case TokenNameDOLLAR_LBRACE:
3096 if (token == TokenNameDOLLAR_LBRACE) {
3098 } else if (token == TokenNameIdentifier) {
3100 if (token == TokenNameLBRACKET) {
3102 // if (token == TokenNameRBRACKET) {
3106 if (token != TokenNameRBRACKET) {
3107 throwSyntaxError("']' expected after '${'.");
3115 if (token != TokenNameRBRACE) {
3116 throwSyntaxError("'}' expected.");
3120 case TokenNameLBRACE_DOLLAR:
3122 if (token == TokenNameLBRACE_DOLLAR) {
3124 } else if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
3126 if (token == TokenNameLBRACKET) {
3128 // if (token == TokenNameRBRACKET) {
3132 if (token != TokenNameRBRACKET) {
3133 throwSyntaxError("']' expected.");
3137 } else if (token == TokenNameMINUS_GREATER) {
3139 if (token != TokenNameIdentifier && token != TokenNameVariable) {
3140 throwSyntaxError("String or Variable token expected.");
3143 if (token == TokenNameLBRACKET) {
3145 // if (token == TokenNameRBRACKET) {
3149 if (token != TokenNameRBRACKET) {
3150 throwSyntaxError("']' expected after '${'.");
3156 // if (token != TokenNameRBRACE) {
3157 // throwSyntaxError("'}' expected after '{$'.");
3159 // // scanner.encapsedStringStack.pop();
3163 if (token != TokenNameRBRACE) {
3164 throwSyntaxError("'}' expected.");
3166 // scanner.encapsedStringStack.pop();
3173 private void encaps_var_offset() {
3178 case TokenNameSTRING:
3181 case TokenNameIntegerLiteral:
3184 case TokenNameVariable:
3187 case TokenNameIdentifier:
3191 throwSyntaxError("Variable or String token expected.");
3196 private void internal_functions_in_yacc() {
3198 ImportReference impt = null;
3200 case TokenNameisset:
3201 // T_ISSET '(' isset_variables ')'
3203 if (token != TokenNameLPAREN) {
3204 throwSyntaxError("'(' expected after keyword 'isset'");
3208 if (token != TokenNameRPAREN) {
3209 throwSyntaxError("')' expected after keyword 'isset'");
3213 case TokenNameempty:
3214 // T_EMPTY '(' variable ')'
3216 if (token != TokenNameLPAREN) {
3217 throwSyntaxError("'(' expected after keyword 'empty'");
3221 if (token != TokenNameRPAREN) {
3222 throwSyntaxError("')' expected after keyword 'empty'");
3226 case TokenNameinclude:
3228 start = scanner.getCurrentTokenStartPosition();
3232 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3233 impt.declarationSourceEnd = impt.sourceEnd;
3234 impt.declarationEnd = impt.declarationSourceEnd;
3235 //endPosition is just before the ;
3236 impt.declarationSourceStart = start;
3237 includesList.add(impt);
3239 case TokenNameinclude_once:
3240 // T_INCLUDE_ONCE expr
3241 start = scanner.getCurrentTokenStartPosition();
3244 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3245 impt.declarationSourceEnd = impt.sourceEnd;
3246 impt.declarationEnd = impt.declarationSourceEnd;
3247 //endPosition is just before the ;
3248 impt.declarationSourceStart = start;
3249 includesList.add(impt);
3252 // T_EVAL '(' expr ')'
3254 if (token != TokenNameLPAREN) {
3255 throwSyntaxError("'(' expected after keyword 'eval'");
3259 if (token != TokenNameRPAREN) {
3260 throwSyntaxError("')' expected after keyword 'eval'");
3264 case TokenNamerequire:
3266 start = scanner.getCurrentTokenStartPosition();
3269 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3270 impt.declarationSourceEnd = impt.sourceEnd;
3271 impt.declarationEnd = impt.declarationSourceEnd;
3272 //endPosition is just before the ;
3273 impt.declarationSourceStart = start;
3274 includesList.add(impt);
3276 case TokenNamerequire_once:
3277 // T_REQUIRE_ONCE expr
3278 start = scanner.getCurrentTokenStartPosition();
3281 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3282 impt.declarationSourceEnd = impt.sourceEnd;
3283 impt.declarationEnd = impt.declarationSourceEnd;
3284 //endPosition is just before the ;
3285 impt.declarationSourceStart = start;
3286 includesList.add(impt);
3291 private void isset_variables() {
3293 // | isset_variables ','
3294 if (token == TokenNameRPAREN) {
3295 throwSyntaxError("Variable expected after keyword 'isset'");
3299 if (token == TokenNameCOMMA) {
3307 private boolean common_scalar() {
3311 // | T_CONSTANT_ENCAPSED_STRING
3318 case TokenNameIntegerLiteral:
3321 case TokenNameDoubleLiteral:
3324 case TokenNameStringDoubleQuote:
3327 case TokenNameStringSingleQuote:
3330 case TokenNameStringInterpolated:
3339 case TokenNameCLASS_C:
3342 case TokenNameMETHOD_C:
3345 case TokenNameFUNC_C:
3352 private void scalar() {
3355 //| T_STRING_VARNAME
3358 //| '"' encaps_list '"'
3359 //| '\'' encaps_list '\''
3360 //| T_START_HEREDOC encaps_list T_END_HEREDOC
3361 throwSyntaxError("Not yet implemented (scalar).");
3364 private void static_scalar() {
3365 // static_scalar: /* compile-time evaluated scalars */
3368 // | '+' static_scalar
3369 // | '-' static_scalar
3370 // | T_ARRAY '(' static_array_pair_list ')'
3371 // | static_class_constant
3372 if (common_scalar()) {
3376 case TokenNameIdentifier:
3378 // static_class_constant:
3379 // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3380 if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3382 if (token == TokenNameIdentifier) {
3385 throwSyntaxError("Identifier expected after '::' operator.");
3389 case TokenNameEncapsedString0:
3391 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3392 while (scanner.currentCharacter != '`') {
3393 if (scanner.currentCharacter == '\\') {
3394 scanner.currentPosition++;
3396 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3399 } catch (IndexOutOfBoundsException e) {
3400 throwSyntaxError("'`' expected at end of static string.");
3403 case TokenNameEncapsedString1:
3405 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3406 while (scanner.currentCharacter != '\'') {
3407 if (scanner.currentCharacter == '\\') {
3408 scanner.currentPosition++;
3410 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3413 } catch (IndexOutOfBoundsException e) {
3414 throwSyntaxError("'\'' expected at end of static string.");
3417 case TokenNameEncapsedString2:
3419 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3420 while (scanner.currentCharacter != '"') {
3421 if (scanner.currentCharacter == '\\') {
3422 scanner.currentPosition++;
3424 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3427 } catch (IndexOutOfBoundsException e) {
3428 throwSyntaxError("'\"' expected at end of static string.");
3435 case TokenNameMINUS:
3439 case TokenNamearray:
3441 if (token != TokenNameLPAREN) {
3442 throwSyntaxError("'(' expected after keyword 'array'");
3445 if (token == TokenNameRPAREN) {
3449 non_empty_static_array_pair_list();
3450 if (token != TokenNameRPAREN) {
3451 throwSyntaxError("')' expected after keyword 'array'");
3455 // case TokenNamenull :
3458 // case TokenNamefalse :
3461 // case TokenNametrue :
3465 throwSyntaxError("Static scalar/constant expected.");
3469 private void non_empty_static_array_pair_list() {
3470 // non_empty_static_array_pair_list:
3471 // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3473 //| non_empty_static_array_pair_list ',' static_scalar
3474 //| static_scalar T_DOUBLE_ARROW static_scalar
3478 if (token == TokenNameEQUAL_GREATER) {
3482 if (token != TokenNameCOMMA) {
3486 if (token == TokenNameRPAREN) {
3492 public void reportSyntaxError() { //int act, int currentKind, int
3494 /* remember current scanner position */
3495 int startPos = scanner.startPosition;
3496 int currentPos = scanner.currentPosition;
3497 // String[] expectings;
3498 // String tokenName = name[symbol_index[currentKind]];
3499 //fetch all "accurate" possible terminals that could recover the error
3500 // int start, end = start = asi(stack[stateStackTop]);
3501 // while (asr[end] != 0)
3503 // int length = end - start;
3504 // expectings = new String[length];
3505 // if (length != 0) {
3506 // char[] indexes = new char[length];
3507 // System.arraycopy(asr, start, indexes, 0, length);
3508 // for (int i = 0; i < length; i++) {
3509 // expectings[i] = name[symbol_index[indexes[i]]];
3512 //if the pb is an EOF, try to tell the user that they are some
3513 // if (tokenName.equals(UNEXPECTED_EOF)) {
3514 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3515 // char[] tokenSource;
3517 // tokenSource = this.scanner.getCurrentTokenSource();
3518 // } catch (Exception e) {
3519 // tokenSource = new char[] {};
3521 // problemReporter().parseError(
3522 // this.scanner.startPosition,
3523 // this.scanner.currentPosition - 1,
3528 // } else { //the next test is HEAVILY grammar DEPENDENT.
3529 // if ((length == 14)
3530 // && (expectings[0] == "=") //$NON-NLS-1$
3531 // && (expectings[1] == "*=") //$NON-NLS-1$
3532 // && (expressionPtr > -1)) {
3533 // switch(currentKind) {
3534 // case TokenNameSEMICOLON:
3535 // case TokenNamePLUS:
3536 // case TokenNameMINUS:
3537 // case TokenNameDIVIDE:
3538 // case TokenNameREMAINDER:
3539 // case TokenNameMULTIPLY:
3540 // case TokenNameLEFT_SHIFT:
3541 // case TokenNameRIGHT_SHIFT:
3542 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3543 // case TokenNameLESS:
3544 // case TokenNameGREATER:
3545 // case TokenNameLESS_EQUAL:
3546 // case TokenNameGREATER_EQUAL:
3547 // case TokenNameEQUAL_EQUAL:
3548 // case TokenNameNOT_EQUAL:
3549 // case TokenNameXOR:
3550 // case TokenNameAND:
3551 // case TokenNameOR:
3552 // case TokenNameOR_OR:
3553 // case TokenNameAND_AND:
3554 // // the ; is not the expected token ==> it ends a statement when an
3555 // expression is not ended
3556 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3558 // case TokenNameRBRACE :
3559 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3562 // char[] tokenSource;
3564 // tokenSource = this.scanner.getCurrentTokenSource();
3565 // } catch (Exception e) {
3566 // tokenSource = new char[] {};
3568 // problemReporter().parseError(
3569 // this.scanner.startPosition,
3570 // this.scanner.currentPosition - 1,
3574 // this.checkAndReportBracketAnomalies(problemReporter());
3579 tokenSource = this.scanner.getCurrentTokenSource();
3580 } catch (Exception e) {
3581 tokenSource = new char[] {};
3583 // problemReporter().parseError(
3584 // this.scanner.startPosition,
3585 // this.scanner.currentPosition - 1,
3589 this.checkAndReportBracketAnomalies(problemReporter());
3592 /* reset scanner where it was */
3593 scanner.startPosition = startPos;
3594 scanner.currentPosition = currentPos;
3597 public static final int RoundBracket = 0;
3599 public static final int SquareBracket = 1;
3601 public static final int CurlyBracket = 2;
3603 public static final int BracketKinds = 3;
3605 protected int[] nestedMethod; //the ptr is nestedType
3607 protected int nestedType, dimensions;
3610 final static int AstStackIncrement = 100;
3612 protected int astPtr;
3614 protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
3616 protected int astLengthPtr;
3618 protected int[] astLengthStack;
3620 ASTNode[] noAstNodes = new ASTNode[AstStackIncrement];
3622 public CompilationUnitDeclaration compilationUnit; /*
3623 * the result from parse()
3626 protected ReferenceContext referenceContext;
3628 protected ProblemReporter problemReporter;
3630 protected CompilerOptions options;
3632 private ArrayList includesList;
3634 // protected CompilationResult compilationResult;
3636 * Returns this parser's problem reporter initialized with its reference context. Also it is assumed that a problem is going to be
3637 * reported, so initializes the compilation result's line positions.
3639 public ProblemReporter problemReporter() {
3640 if (scanner.recordLineSeparator) {
3641 compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
3643 problemReporter.referenceContext = referenceContext;
3644 return problemReporter;
3648 * Reconsider the entire source looking for inconsistencies in {} () []
3650 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3651 scanner.wasAcr = false;
3652 boolean anomaliesDetected = false;
3654 char[] source = scanner.source;
3655 int[] leftCount = { 0, 0, 0 };
3656 int[] rightCount = { 0, 0, 0 };
3657 int[] depths = { 0, 0, 0 };
3658 int[][] leftPositions = new int[][] { new int[10], new int[10], new int[10] };
3659 int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10] };
3660 int[][] rightPositions = new int[][] { new int[10], new int[10], new int[10] };
3661 int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10] };
3662 scanner.currentPosition = scanner.initialPosition; //starting
3664 // (first-zero-based
3666 while (scanner.currentPosition < scanner.eofPosition) { //loop for
3671 // ---------Consume white space and handles
3672 // startPosition---------
3673 boolean isWhiteSpace;
3675 scanner.startPosition = scanner.currentPosition;
3676 // if (((scanner.currentCharacter =
3677 // source[scanner.currentPosition++]) == '\\') &&
3678 // (source[scanner.currentPosition] == 'u')) {
3679 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3681 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3682 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3683 // only record line positions we have not
3685 scanner.pushLineSeparator();
3688 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3690 } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
3691 // -------consume token until } is found---------
3692 switch (scanner.currentCharacter) {
3694 int index = leftCount[CurlyBracket]++;
3695 if (index == leftPositions[CurlyBracket].length) {
3696 System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
3697 System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
3699 leftPositions[CurlyBracket][index] = scanner.startPosition;
3700 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3704 int index = rightCount[CurlyBracket]++;
3705 if (index == rightPositions[CurlyBracket].length) {
3706 System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
3707 System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
3709 rightPositions[CurlyBracket][index] = scanner.startPosition;
3710 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3714 int index = leftCount[RoundBracket]++;
3715 if (index == leftPositions[RoundBracket].length) {
3716 System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
3717 System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
3719 leftPositions[RoundBracket][index] = scanner.startPosition;
3720 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3724 int index = rightCount[RoundBracket]++;
3725 if (index == rightPositions[RoundBracket].length) {
3726 System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
3727 System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
3729 rightPositions[RoundBracket][index] = scanner.startPosition;
3730 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3734 int index = leftCount[SquareBracket]++;
3735 if (index == leftPositions[SquareBracket].length) {
3736 System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
3737 System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
3739 leftPositions[SquareBracket][index] = scanner.startPosition;
3740 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3744 int index = rightCount[SquareBracket]++;
3745 if (index == rightPositions[SquareBracket].length) {
3746 System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
3747 System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
3749 rightPositions[SquareBracket][index] = scanner.startPosition;
3750 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3754 if (scanner.getNextChar('\\')) {
3755 scanner.scanEscapeCharacter();
3756 } else { // consume next character
3757 scanner.unicodeAsBackSlash = false;
3758 // if (((scanner.currentCharacter =
3759 // source[scanner.currentPosition++]) ==
3761 // (source[scanner.currentPosition] ==
3763 // scanner.getNextUnicodeChar();
3765 if (scanner.withoutUnicodePtr != 0) {
3766 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3770 scanner.getNextChar('\'');
3774 // consume next character
3775 scanner.unicodeAsBackSlash = false;
3776 // if (((scanner.currentCharacter =
3777 // source[scanner.currentPosition++]) == '\\') &&
3778 // (source[scanner.currentPosition] == 'u')) {
3779 // scanner.getNextUnicodeChar();
3781 if (scanner.withoutUnicodePtr != 0) {
3782 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3785 while (scanner.currentCharacter != '"') {
3786 if (scanner.currentCharacter == '\r') {
3787 if (source[scanner.currentPosition] == '\n')
3788 scanner.currentPosition++;
3789 break; // the string cannot go further that
3792 if (scanner.currentCharacter == '\n') {
3793 break; // the string cannot go further that
3796 if (scanner.currentCharacter == '\\') {
3797 scanner.scanEscapeCharacter();
3799 // consume next character
3800 scanner.unicodeAsBackSlash = false;
3801 // if (((scanner.currentCharacter =
3802 // source[scanner.currentPosition++]) == '\\')
3803 // && (source[scanner.currentPosition] == 'u'))
3805 // scanner.getNextUnicodeChar();
3807 if (scanner.withoutUnicodePtr != 0) {
3808 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3815 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3818 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3819 && (source[scanner.currentPosition] == 'u')) {
3820 //-------------unicode traitement
3822 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3823 scanner.currentPosition++;
3824 while (source[scanner.currentPosition] == 'u') {
3825 scanner.currentPosition++;
3827 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3828 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3829 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3830 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3834 scanner.currentCharacter = 'A';
3835 } //something different from \n and \r
3837 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3840 while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
3842 scanner.startPosition = scanner.currentPosition;
3843 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3844 && (source[scanner.currentPosition] == 'u')) {
3845 //-------------unicode traitement
3847 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3848 scanner.currentPosition++;
3849 while (source[scanner.currentPosition] == 'u') {
3850 scanner.currentPosition++;
3852 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3853 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3854 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3855 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3859 scanner.currentCharacter = 'A';
3860 } //something different from \n
3863 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3867 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3868 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3869 // only record line positions we
3870 // have not recorded yet
3871 scanner.pushLineSeparator();
3872 if (this.scanner.taskTags != null) {
3873 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner
3874 .getCurrentTokenEndPosition());
3880 if (test > 0) { //traditional and annotation
3882 boolean star = false;
3883 // consume next character
3884 scanner.unicodeAsBackSlash = false;
3885 // if (((scanner.currentCharacter =
3886 // source[scanner.currentPosition++]) ==
3888 // (source[scanner.currentPosition] ==
3890 // scanner.getNextUnicodeChar();
3892 if (scanner.withoutUnicodePtr != 0) {
3893 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3896 if (scanner.currentCharacter == '*') {
3900 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3901 && (source[scanner.currentPosition] == 'u')) {
3902 //-------------unicode traitement
3904 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3905 scanner.currentPosition++;
3906 while (source[scanner.currentPosition] == 'u') {
3907 scanner.currentPosition++;
3909 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3910 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3911 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3912 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3916 scanner.currentCharacter = 'A';
3917 } //something different from * and /
3919 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3922 //loop until end of comment */
3923 while ((scanner.currentCharacter != '/') || (!star)) {
3924 star = scanner.currentCharacter == '*';
3926 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3927 && (source[scanner.currentPosition] == 'u')) {
3928 //-------------unicode traitement
3930 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3931 scanner.currentPosition++;
3932 while (source[scanner.currentPosition] == 'u') {
3933 scanner.currentPosition++;
3935 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3936 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3937 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3938 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3942 scanner.currentCharacter = 'A';
3943 } //something different from * and
3946 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3950 if (this.scanner.taskTags != null) {
3951 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
3958 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3959 scanner.scanIdentifierOrKeyword(false);
3962 if (Character.isDigit(scanner.currentCharacter)) {
3963 scanner.scanNumber(false);
3967 //-----------------end switch while
3968 // try--------------------
3969 } catch (IndexOutOfBoundsException e) {
3970 break; // read until EOF
3971 } catch (InvalidInputException e) {
3972 return false; // no clue
3975 if (scanner.recordLineSeparator) {
3976 // compilationUnit.compilationResult.lineSeparatorPositions =
3977 // scanner.getLineEnds();
3979 // check placement anomalies against other kinds of brackets
3980 for (int kind = 0; kind < BracketKinds; kind++) {
3981 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3982 int start = leftPositions[kind][leftIndex]; // deepest
3984 // find matching closing bracket
3985 int depth = leftDepths[kind][leftIndex];
3987 for (int i = 0; i < rightCount[kind]; i++) {
3988 int pos = rightPositions[kind][i];
3989 // want matching bracket further in source with same
3991 if ((pos > start) && (depth == rightDepths[kind][i])) {
3996 if (end < 0) { // did not find a good closing match
3997 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
4000 // check if even number of opening/closing other brackets
4001 // in between this pair of brackets
4003 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
4004 for (int i = 0; i < leftCount[otherKind]; i++) {
4005 int pos = leftPositions[otherKind][i];
4006 if ((pos > start) && (pos < end))
4009 for (int i = 0; i < rightCount[otherKind]; i++) {
4010 int pos = rightPositions[otherKind][i];
4011 if ((pos > start) && (pos < end))
4015 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket
4021 // too many opening brackets ?
4022 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
4023 anomaliesDetected = true;
4024 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext,
4025 compilationUnit.compilationResult);
4027 // too many closing brackets ?
4028 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
4029 anomaliesDetected = true;
4030 problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
4032 if (anomaliesDetected)
4035 return anomaliesDetected;
4036 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
4037 return anomaliesDetected;
4038 } catch (NullPointerException e) { // jdk1.2.2 jit bug
4039 return anomaliesDetected;
4043 protected void pushOnAstLengthStack(int pos) {
4045 astLengthStack[++astLengthPtr] = pos;
4046 } catch (IndexOutOfBoundsException e) {
4047 int oldStackLength = astLengthStack.length;
4048 int[] oldPos = astLengthStack;
4049 astLengthStack = new int[oldStackLength + StackIncrement];
4050 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
4051 astLengthStack[astLengthPtr] = pos;
4055 protected void pushOnAstStack(ASTNode node) {
4057 * add a new obj on top of the ast stack
4060 astStack[++astPtr] = node;
4061 } catch (IndexOutOfBoundsException e) {
4062 int oldStackLength = astStack.length;
4063 ASTNode[] oldStack = astStack;
4064 astStack = new ASTNode[oldStackLength + AstStackIncrement];
4065 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
4066 astPtr = oldStackLength;
4067 astStack[astPtr] = node;
4070 astLengthStack[++astLengthPtr] = 1;
4071 } catch (IndexOutOfBoundsException e) {
4072 int oldStackLength = astLengthStack.length;
4073 int[] oldPos = astLengthStack;
4074 astLengthStack = new int[oldStackLength + AstStackIncrement];
4075 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
4076 astLengthStack[astLengthPtr] = 1;
4080 protected void resetModifiers() {
4081 this.modifiers = AccDefault;
4082 this.modifiersSourceStart = -1; // <-- see comment into
4083 // modifiersFlag(int)
4084 this.scanner.commentPtr = -1;