1 /*******************************************************************************
2 * Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de All rights
3 * reserved. This program and the accompanying material are made available under
4 * the terms of the Common Public License v1.0 which accompanies this
5 * distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html
7 * Contributors: Klaus Hartlage - www.eclipseproject.de
8 ******************************************************************************/
9 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.AbstractMethodDeclaration;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
28 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
29 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
30 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
32 import org.eclipse.core.resources.IFile;
33 public class Parser //extends PHPParserSuperclass
34 implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
35 //internal data for the automat
36 protected final static int StackIncrement = 255;
37 protected int stateStackTop;
38 protected int[] stack = new int[StackIncrement];
39 public int firstToken; // handle for multiple parsing goals
40 public int lastAct; //handle for multiple parsing goals
41 protected RecoveredElement currentElement;
42 public static boolean VERBOSE_RECOVERY = false;
43 protected boolean diet = false; //tells the scanner to jump over some
44 // parts of the code/expressions like
47 public Scanner scanner;
48 private ArrayList phpList;
49 private int currentPHPString;
50 private boolean phpEnd;
51 // private static HashMap keywordMap = null;
57 // row counter for syntax errors:
59 // column counter for syntax errors:
63 // // current identifier
67 private String stringValue;
68 /** Contains the current expression. */
69 // private StringBuffer expression;
70 //private boolean phpMode;
71 protected int modifiers;
72 protected int modifiersSourceStart;
73 // protected IdentifierIndexManager indexManager;
75 protected Parser(ProblemReporter problemReporter) {
76 this.problemReporter = problemReporter;
77 this.options = problemReporter.options;
78 this.currentPHPString = 0;
79 // PHPParserSuperclass.fileToParse = fileToParse;
81 // this.indexManager = null;
83 this.token = TokenNameEOF;
86 // this.columnCount = 0;
89 this.initializeScanner();
91 public void setFileToParse(IFile fileToParse) {
92 this.currentPHPString = 0;
93 // PHPParserSuperclass.fileToParse = fileToParse;
95 // this.indexManager = null;
97 this.token = TokenNameEOF;
99 this.initializeScanner();
102 * ClassDeclaration Constructor.
106 * Description of Parameter
109 public Parser(IFile fileToParse) {
110 // if (keywordMap == null) {
111 // keywordMap = new HashMap();
112 // for (int i = 0; i < PHP_KEYWORS.length; i++) {
113 // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
116 this.currentPHPString = 0;
117 // PHPParserSuperclass.fileToParse = fileToParse;
119 this.includesList = null;
121 this.token = TokenNameEOF;
123 // this.rowCount = 1;
124 // this.columnCount = 0;
127 this.initializeScanner();
129 public void initializeScanner() {
130 this.scanner = new Scanner(false /* comment */, false /* whitespace */, this.options
131 .getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /* nls */, false, false,
132 this.options.taskTags/* taskTags */, this.options.taskPriorites/* taskPriorities */);
135 * Create marker for the parse error
137 // private void setMarker(String message, int charStart, int charEnd, int
139 // setMarker(fileToParse, message, charStart, charEnd, errorLevel);
142 * This method will throw the SyntaxError. It will add the good lines and
143 * columns to the Error
147 * @throws SyntaxError
150 private void throwSyntaxError(String error) {
151 int problemStartPosition = scanner.getCurrentTokenStartPosition();
152 int problemEndPosition = scanner.getCurrentTokenEndPosition();
153 throwSyntaxError(error, problemStartPosition, problemEndPosition + 1);
156 * This method will throw the SyntaxError. It will add the good lines and
157 * columns to the Error
161 * @throws SyntaxError
164 // private void throwSyntaxError(String error, int startRow) {
165 // throw new SyntaxError(startRow, 0, " ", error);
167 private void throwSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
168 problemReporter.phpParsingError(new String[]{error}, problemStartPosition, problemEndPosition, referenceContext,
169 compilationUnit.compilationResult);
170 throw new SyntaxError(1, 0, " ", error);
172 private void reportSyntaxError(String error, int problemStartPosition, int problemEndPosition) {
173 problemReporter.phpParsingError(new String[]{error}, problemStartPosition, problemEndPosition, referenceContext,
174 compilationUnit.compilationResult);
176 private void reportSyntaxWarning(String error, int problemStartPosition, int problemEndPosition) {
177 problemReporter.phpParsingWarning(new String[]{error}, problemStartPosition, problemEndPosition, referenceContext,
178 compilationUnit.compilationResult);
181 * Method Declaration.
185 // private void getChar() {
186 // if (str.length() > chIndx) {
187 // ch = str.charAt(chIndx++);
192 // chIndx = str.length() + 1;
194 // // token = TokenNameEOF;
198 * gets the next token from input
200 private void getNextToken() {
202 token = scanner.getNextToken();
204 int currentEndPosition = scanner.getCurrentTokenEndPosition();
205 int currentStartPosition = scanner.getCurrentTokenStartPosition();
206 System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
207 System.out.println(scanner.toStringAction(token));
209 } catch (InvalidInputException e) {
210 token = TokenNameERROR;
214 public void init(String s) {
216 this.token = TokenNameEOF;
218 // this.rowCount = 1;
219 // this.columnCount = 0;
221 // this.phpMode = false;
222 /* scanner initialization */
223 scanner.setSource(s.toCharArray());
224 scanner.setPHPMode(false);
226 protected void initialize(boolean phpMode) {
227 initialize(phpMode, null);
229 protected void initialize(boolean phpMode, IdentifierIndexManager indexManager) {
230 compilationUnit = null;
231 referenceContext = null;
232 includesList = new ArrayList();
233 // this.indexManager = indexManager;
235 this.token = TokenNameEOF;
237 // this.rowCount = 1;
238 // this.columnCount = 0;
240 // this.phpMode = phpMode;
241 scanner.setPHPMode(phpMode);
244 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
247 public void parse(String s) {
252 * Parses a string with php tags i.e. '<body> <?php phpinfo() ?>
255 protected void parse() {
259 if (token != TokenNameEOF && token != TokenNameERROR) {
262 if (token != TokenNameEOF) {
263 if (token == TokenNameERROR) {
264 throwSyntaxError("Scanner error (Found unknown token: " + scanner.toStringAction(token) + ")");
266 if (token == TokenNameRPAREN) {
267 throwSyntaxError("Too many closing ')'; end-of-file not reached.");
269 if (token == TokenNameRBRACE) {
270 throwSyntaxError("Too many closing '}'; end-of-file not reached.");
272 if (token == TokenNameRBRACKET) {
273 throwSyntaxError("Too many closing ']'; end-of-file not reached.");
275 if (token == TokenNameLPAREN) {
276 throwSyntaxError("Read character '('; end-of-file not reached.");
278 if (token == TokenNameLBRACE) {
279 throwSyntaxError("Read character '{'; end-of-file not reached.");
281 if (token == TokenNameLBRACKET) {
282 throwSyntaxError("Read character '['; end-of-file not reached.");
284 throwSyntaxError("End-of-file not reached.");
287 } catch (SyntaxError sytaxErr1) {
288 // setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(),
290 // setMarker(sytaxErr1.getMessage(),
291 // scanner.getCurrentTokenStartPosition(),
292 // scanner.getCurrentTokenEndPosition(), ERROR);
294 // if an error occured,
295 // try to find keywords 'class' or 'function'
296 // to parse the rest of the string
297 while (token != TokenNameEOF && token != TokenNameERROR) {
298 if (token == TokenNameabstract || token == TokenNamefinal || token == TokenNameclass || token == TokenNamefunction) {
303 if (token == TokenNameEOF || token == TokenNameERROR) {
306 } catch (SyntaxError sytaxErr2) {
307 // setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(),
309 // setMarker(sytaxErr2.getMessage(),
310 // scanner.getCurrentTokenStartPosition(),
311 // scanner.getCurrentTokenEndPosition(), ERROR);
320 protected CompilationUnitDeclaration endParse(int act) {
324 if (currentElement != null) {
325 currentElement.topElement().updateParseTree();
326 if (VERBOSE_RECOVERY) {
327 System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
328 System.out.println("--------------------------"); //$NON-NLS-1$
329 System.out.println(compilationUnit);
330 System.out.println("----------------------------------"); //$NON-NLS-1$
333 if (diet & VERBOSE_RECOVERY) {
334 System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
335 System.out.println("--------------------------"); //$NON-NLS-1$
336 System.out.println(compilationUnit);
337 System.out.println("----------------------------------"); //$NON-NLS-1$
340 if (scanner.recordLineSeparator) {
341 compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
343 if (scanner.taskTags != null) {
344 for (int i = 0; i < scanner.foundTaskCount; i++) {
345 problemReporter().task(new String(scanner.foundTaskTags[i]), new String(scanner.foundTaskMessages[i]),
346 scanner.foundTaskPriorities[i] == null ? null : new String(scanner.foundTaskPriorities[i]),
347 scanner.foundTaskPositions[i][0], scanner.foundTaskPositions[i][1]);
350 compilationUnit.imports = new ImportReference[includesList.size()];
351 for (int i = 0; i < includesList.size(); i++) {
352 compilationUnit.imports[i] = (ImportReference) includesList.get(i);
354 return compilationUnit;
356 // public PHPOutlineInfo parseInfo(Object parent, String s) {
357 // PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
358 // // Stack stack = new Stack();
359 // // stack.push(outlineInfo.getDeclarations());
361 // this.token = TokenNameEOF;
362 // // this.chIndx = 0;
363 // // this.rowCount = 1;
364 // // this.columnCount = 0;
365 // this.phpEnd = false;
366 // this.phpMode = false;
367 // scanner.setSource(s.toCharArray());
368 // scanner.setPHPMode(false);
371 // parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
373 // return outlineInfo;
375 private boolean isVariable() {
376 return token == TokenNameVariable; // || token == TokenNamethis;
378 // private void parseDeclarations(PHPOutlineInfo outlineInfo,
379 // OutlineableWithChildren current, boolean goBack) {
381 // // PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
382 // PHPSegmentWithChildren temp;
384 // IPreferenceStore store =
385 // PHPeclipsePlugin.getDefault().getPreferenceStore();
387 // while (token != TokenNameEOF && token != TokenNameERROR) {
388 // if (token == TokenNameVariable) {
389 // ident = scanner.getCurrentIdentifierSource();
390 // outlineInfo.addVariable(new String(ident));
392 // } else if (token == TokenNamevar) {
394 // if (token == TokenNameVariable
395 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_VAR)) {
396 // ident = scanner.getCurrentIdentifierSource();
397 // //substring(1) added because PHPVarDeclaration doesn't
398 // // need the $ anymore
399 // String variableName = new String(ident).substring(1);
400 // outlineInfo.addVariable(variableName);
402 // if (token != TokenNameSEMICOLON) {
404 // ident = scanner.getCurrentTokenSource();
405 // if (token > TokenNameKEYWORD) {
406 // current.add(new PHPVarDeclaration(current, variableName,
407 // // chIndx - ident.length,
408 // scanner.getCurrentTokenStartPosition(), new String(ident)));
411 // case TokenNameVariable :
412 // case TokenNamethis :
413 // current.add(new PHPVarDeclaration(current, variableName,
416 // scanner.getCurrentTokenStartPosition(), new String(
419 // case TokenNameIdentifier :
420 // current.add(new PHPVarDeclaration(current, variableName,
423 // scanner.getCurrentTokenStartPosition(), new String(
426 // case TokenNameDoubleLiteral :
427 // current.add(new PHPVarDeclaration(current, variableName
431 // scanner.getCurrentTokenStartPosition(), new String(
434 // case TokenNameIntegerLiteral :
435 // current.add(new PHPVarDeclaration(current, variableName,
438 // scanner.getCurrentTokenStartPosition(), new String(
441 // case TokenNameStringInterpolated :
442 // case TokenNameStringLiteral :
443 // current.add(new PHPVarDeclaration(current, variableName,
446 // scanner.getCurrentTokenStartPosition(), new String(
449 // case TokenNameStringConstant :
450 // current.add(new PHPVarDeclaration(current, variableName,
453 // scanner.getCurrentTokenStartPosition(), new String(
457 // current.add(new PHPVarDeclaration(current, variableName,
460 // scanner.getCurrentTokenStartPosition()));
465 // ident = scanner.getCurrentIdentifierSource();
466 // current.add(new PHPVarDeclaration(current, variableName,
467 // // chIndx - ident.length
468 // scanner.getCurrentTokenStartPosition()));
471 // } else if (token == TokenNamefunction) {
473 // if (token == TokenNameAND) {
476 // if (token == TokenNameIdentifier
477 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_FUNC)) {
478 // ident = scanner.getCurrentIdentifierSource();
479 // outlineInfo.addVariable(new String(ident));
480 // temp = new PHPFunctionDeclaration(current, new String(ident),
481 // // chIndx - ident.length
482 // scanner.getCurrentTokenStartPosition());
483 // current.add(temp);
485 // parseDeclarations(outlineInfo, temp, true);
487 // } else if (token == TokenNameclass) {
489 // if (token == TokenNameIdentifier
490 // && store.getBoolean(PHPeclipsePlugin.PHP_OUTLINE_CLASS)) {
491 // ident = scanner.getCurrentIdentifierSource();
492 // outlineInfo.addVariable(new String(ident));
493 // temp = new PHPClassDeclaration(current, new String(ident),
494 // // chIndx - ident.len
495 // scanner.getCurrentTokenStartPosition());
496 // current.add(temp);
497 // // stack.push(temp);
499 // //skip tokens for classname, extends and others until
500 // // we have the opening '{'
501 // while (token != TokenNameLBRACE && token != TokenNameEOF
502 // && token != TokenNameERROR) {
505 // parseDeclarations(outlineInfo, temp, true);
508 // } else if ((token == TokenNameLBRACE)
509 // || (token == TokenNameDOLLAR_LBRACE)) {
512 // } else if (token == TokenNameRBRACE) {
515 // if (counter == 0 && goBack) {
518 // } else if (token == TokenNamerequire || token == TokenNamerequire_once
519 // || token == TokenNameinclude || token == TokenNameinclude_once) {
520 // ident = scanner.getCurrentTokenSource();
522 // int startPosition = scanner.getCurrentTokenStartPosition();
524 // char[] expr = scanner.getCurrentTokenSource(startPosition);
525 // outlineInfo.addVariable(new String(ident));
526 // current.add(new PHPReqIncDeclaration(current, new String(ident),
527 // // chIndx - ident.length,
528 // startPosition, new String(expr)));
534 // } catch (SyntaxError sytaxErr) {
536 // // // setMarker(sytaxErr.getMessage(), sytaxErr.getLine(), ERROR);
537 // // setMarker(sytaxErr.getMessage(),
538 // // scanner.getCurrentTokenStartPosition(),
539 // // scanner.getCurrentTokenEndPosition(), ERROR);
540 // // } catch (CoreException e) {
544 private void statementList() {
546 statement(TokenNameEOF);
547 if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse)
548 || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor)
549 || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch)
550 || (token == TokenNameEOF) || (token == TokenNameERROR)) {
555 private void functionBody(MethodDeclaration methodDecl) {
556 // '{' [statement-list] '}'
557 if (token == TokenNameLBRACE) {
560 throwSyntaxError("'{' expected in compound-statement.");
562 if (token != TokenNameRBRACE) {
565 if (token == TokenNameRBRACE) {
566 methodDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
569 throwSyntaxError("'}' expected in compound-statement.");
572 private void statement(int previousToken) {
573 // if (token > TokenNameKEYWORD && token != TokenNamelist && token !=
575 // char[] ident = scanner.getCurrentIdentifierSource();
576 // String keyword = new String(ident);
577 // if (token == TokenNameAT) {
579 // if (token != TokenNamerequire && token != TokenNamerequire_once
580 // && token != TokenNameinclude && token != TokenNameinclude_once
581 // && token != TokenNameIdentifier && token != TokenNameVariable
582 // && token != TokenNameStringInterpolated) {
583 // throwSyntaxError("identifier expected after '@'.");
586 // if (token == TokenNameinclude || token == TokenNameinclude_once) {
588 // if (token == TokenNameLPAREN) {
590 // if (token == TokenNameSEMICOLON) {
593 // if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
594 // throwSyntaxError("';' expected after 'include' or 'include_once'.");
596 // // getNextToken();
599 // concatenationExpression();
602 // } else if (token == TokenNamerequire || token ==
603 // TokenNamerequire_once)
607 // if (token == TokenNameLPAREN) {
609 // if (token == TokenNameSEMICOLON) {
612 // if (previousToken != TokenNameAT && token != TokenNameStopPHP) {
613 // throwSyntaxError("';' expected after 'require' or 'require_once'.");
615 // // getNextToken();
618 // concatenationExpression();
622 if (token == TokenNameif) {
624 if (token == TokenNameLPAREN) {
627 throwSyntaxError("'(' expected after 'if' keyword.");
630 if (token == TokenNameRPAREN) {
633 throwSyntaxError("')' expected after 'if' condition.");
637 } else if (token == TokenNameswitch) {
639 if (token == TokenNameLPAREN) {
642 throwSyntaxError("'(' expected after 'switch' keyword.");
645 if (token == TokenNameRPAREN) {
648 throwSyntaxError("')' expected after 'switch' condition.");
652 } else if (token == TokenNamefor) {
654 if (token == TokenNameLPAREN) {
657 throwSyntaxError("'(' expected after 'for' keyword.");
659 if (token == TokenNameSEMICOLON) {
663 if (token == TokenNameSEMICOLON) {
666 throwSyntaxError("';' expected after 'for'.");
669 if (token == TokenNameSEMICOLON) {
673 if (token == TokenNameSEMICOLON) {
676 throwSyntaxError("';' expected after 'for'.");
679 if (token == TokenNameRPAREN) {
683 if (token == TokenNameRPAREN) {
686 throwSyntaxError("')' expected after 'for'.");
691 } else if (token == TokenNamewhile) {
693 if (token == TokenNameLPAREN) {
696 throwSyntaxError("'(' expected after 'while' keyword.");
699 if (token == TokenNameRPAREN) {
702 throwSyntaxError("')' expected after 'while' condition.");
706 } else if (token == TokenNamedo) {
708 if (token == TokenNameLBRACE) {
710 if (token != TokenNameRBRACE) {
713 if (token == TokenNameRBRACE) {
716 throwSyntaxError("'}' expected after 'do' keyword.");
719 statement(TokenNameEOF);
721 if (token == TokenNamewhile) {
723 if (token == TokenNameLPAREN) {
726 throwSyntaxError("'(' expected after 'while' keyword.");
729 if (token == TokenNameRPAREN) {
732 throwSyntaxError("')' expected after 'while' condition.");
735 throwSyntaxError("'while' expected after 'do' keyword.");
737 if (token == TokenNameSEMICOLON) {
740 if (token != TokenNameINLINE_HTML) {
741 throwSyntaxError("';' expected after do-while statement.");
746 } else if (token == TokenNameforeach) {
748 if (token == TokenNameLPAREN) {
751 throwSyntaxError("'(' expected after 'foreach' keyword.");
754 if (token == TokenNameas) {
757 throwSyntaxError("'as' expected after 'foreach' exxpression.");
761 foreach_optional_arg();
762 if (token == TokenNameEQUAL_GREATER) {
766 if (token == TokenNameRPAREN) {
769 throwSyntaxError("')' expected after 'foreach' expression.");
773 } else if (token == TokenNamecontinue || token == TokenNamebreak || token == TokenNamereturn) {
775 if (token != TokenNameSEMICOLON) {
778 if (token == TokenNameSEMICOLON) {
781 if (token != TokenNameINLINE_HTML) {
782 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
787 } else if (token == TokenNameecho) {
790 if (token == TokenNameSEMICOLON) {
793 if (token != TokenNameINLINE_HTML) {
794 throwSyntaxError("';' expected after 'echo' statement.");
799 } else if (token == TokenNameINLINE_HTML) {
802 // } else if (token == TokenNameprint) {
805 // if (token == TokenNameSEMICOLON) {
808 // if (token != TokenNameStopPHP) {
809 // throwSyntaxError("';' expected after 'print' statement.");
814 } else if (token == TokenNameglobal) {
817 if (token == TokenNameSEMICOLON) {
820 if (token != TokenNameINLINE_HTML) {
821 throwSyntaxError("';' expected after 'global' statement.");
826 } else if (token == TokenNamestatic) {
829 if (token == TokenNameSEMICOLON) {
832 if (token != TokenNameINLINE_HTML) {
833 throwSyntaxError("';' expected after 'static' statement.");
838 } else if (token == TokenNameunset) {
840 if (token == TokenNameLPAREN) {
843 throwSyntaxError("'(' expected after 'unset' statement.");
846 if (token == TokenNameRPAREN) {
849 throwSyntaxError("')' expected after 'unset' statement.");
851 if (token == TokenNameSEMICOLON) {
854 if (token != TokenNameINLINE_HTML) {
855 throwSyntaxError("';' expected after 'unset' statement.");
860 } else if (token == TokenNamefunction) {
861 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
862 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
863 methodDecl.modifiers = AccDefault;
865 functionDefinition(methodDecl);
867 } else if (token == TokenNametry) {
869 if (token != TokenNameLBRACE) {
870 throwSyntaxError("'{' expected in 'try' statement.");
874 if (token != TokenNameRBRACE) {
875 throwSyntaxError("'}' expected in 'try' statement.");
879 } else if (token == TokenNamecatch) {
881 if (token != TokenNameLPAREN) {
882 throwSyntaxError("'(' expected in 'catch' statement.");
885 fully_qualified_class_name();
886 if (token != TokenNameVariable) {
887 throwSyntaxError("Variable expected in 'catch' statement.");
890 if (token != TokenNameRPAREN) {
891 throwSyntaxError("')' expected in 'catch' statement.");
894 if (token != TokenNameLBRACE) {
895 throwSyntaxError("'{' expected in 'catch' statement.");
898 if (token != TokenNameRBRACE) {
900 if (token != TokenNameRBRACE) {
901 throwSyntaxError("'}' expected in 'catch' statement.");
905 additional_catches();
907 } else if (token == TokenNamethrow) {
910 if (token == TokenNameSEMICOLON) {
913 throwSyntaxError("';' expected after 'throw' exxpression.");
916 } else if (token == TokenNamefinal || token == TokenNameabstract || token == TokenNameclass || token == TokenNameinterface) {
917 TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
918 typeDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
919 // default super class
920 typeDecl.superclass = new SingleTypeReference(TypeConstants.OBJECT, 0);
921 compilationUnit.types.add(typeDecl);
923 pushOnAstStack(typeDecl);
924 unticked_class_declaration_statement(typeDecl);
925 // classBody(typeDecl);
932 // throwSyntaxError("Unexpected keyword '" + keyword + "'");
933 } else if (token == TokenNameLBRACE) {
935 if (token != TokenNameRBRACE) {
938 if (token == TokenNameRBRACE) {
942 throwSyntaxError("'}' expected.");
945 if (token != TokenNameSEMICOLON) {
948 if (token == TokenNameSEMICOLON) {
952 if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
953 throwSyntaxError("';' expected after expression (Found token: " + scanner.toStringAction(token) + ")");
959 private void additional_catches() {
960 while (token == TokenNamecatch) {
962 if (token != TokenNameLPAREN) {
963 throwSyntaxError("'(' expected in 'catch' statement.");
966 fully_qualified_class_name();
967 if (token != TokenNameVariable) {
968 throwSyntaxError("Variable expected in 'catch' statement.");
971 if (token != TokenNameRPAREN) {
972 throwSyntaxError("')' expected in 'catch' statement.");
975 if (token != TokenNameLBRACE) {
976 throwSyntaxError("'{' expected in 'catch' statement.");
980 if (token != TokenNameRBRACE) {
981 throwSyntaxError("'}' expected in 'catch' statement.");
986 private void foreach_variable() {
989 if (token == TokenNameAND) {
994 private void foreach_optional_arg() {
996 //| T_DOUBLE_ARROW foreach_variable
997 if (token == TokenNameEQUAL_GREATER) {
1002 private void global_var_list() {
1004 // global_var_list ',' global_var
1008 if (token != TokenNameCOMMA) {
1014 private void global_var() {
1018 //| '$' '{' expr '}'
1019 if (token == TokenNameVariable) {
1021 } else if (token == TokenNameDOLLAR) {
1023 if (token == TokenNameLPAREN) {
1026 if (token != TokenNameLPAREN) {
1027 throwSyntaxError("')' expected in global variable.");
1035 private void static_var_list() {
1037 // static_var_list ',' T_VARIABLE
1038 //| static_var_list ',' T_VARIABLE '=' static_scalar
1040 //| T_VARIABLE '=' static_scalar
1042 if (token == TokenNameVariable) {
1044 if (token == TokenNameEQUAL) {
1048 if (token != TokenNameCOMMA) {
1057 private void unset_variables() {
1060 // | unset_variables ',' unset_variable
1065 if (token != TokenNameCOMMA) {
1071 private final void initializeModifiers() {
1073 this.modifiersSourceStart = -1;
1075 private final void checkAndSetModifiers(int flag) {
1076 this.modifiers |= flag;
1077 if (this.modifiersSourceStart < 0)
1078 this.modifiersSourceStart = this.scanner.startPosition;
1080 private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
1081 initializeModifiers();
1082 if (token == TokenNameinterface) {
1083 // interface_entry T_STRING
1084 // interface_extends_list
1085 // '{' class_statement_list '}'
1086 checkAndSetModifiers(AccInterface);
1088 typeDecl.modifiers = this.modifiers;
1089 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1090 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1091 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1092 typeDecl.name = scanner.getCurrentIdentifierSource();
1093 if (token > TokenNameKEYWORD) {
1094 throwSyntaxError("Don't use a keyword for interface declaration [" + scanner.toStringAction(token) + "].",
1095 typeDecl.sourceStart, typeDecl.sourceEnd);
1098 interface_extends_list();
1100 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1101 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1102 typeDecl.name = new char[]{' '};
1103 throwSyntaxError("Interface name expected after keyword 'interface'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1107 // class_entry_type T_STRING extends_from
1109 // '{' class_statement_list'}'
1111 typeDecl.modifiers = this.modifiers;
1113 //identifier 'extends' identifier
1114 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
1115 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1116 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1117 typeDecl.name = scanner.getCurrentIdentifierSource();
1118 if (token > TokenNameKEYWORD) {
1119 throwSyntaxError("Don't use a keyword for class declaration [" + scanner.toStringAction(token) + "].",
1120 typeDecl.sourceStart, typeDecl.sourceEnd);
1125 // | T_EXTENDS fully_qualified_class_name
1126 if (token == TokenNameextends) {
1127 interface_extends_list();
1129 // if (token != TokenNameIdentifier) {
1130 // throwSyntaxError("Class name expected after keyword
1132 // scanner.getCurrentTokenStartPosition(), scanner
1133 // .getCurrentTokenEndPosition());
1138 typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1139 typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1140 typeDecl.name = new char[]{' '};
1141 throwSyntaxError("Class name expected after keyword 'class'.", typeDecl.sourceStart, typeDecl.sourceEnd);
1145 // '{' class_statement_list '}'
1146 if (token == TokenNameLBRACE) {
1148 if (token != TokenNameRBRACE) {
1149 ArrayList list = new ArrayList();
1150 class_statement_list(list);
1151 typeDecl.fields = new FieldDeclaration[list.size()];
1152 for (int i = 0; i < list.size(); i++) {
1153 typeDecl.fields[i] = (FieldDeclaration) list.get(i);
1156 if (token == TokenNameRBRACE) {
1157 typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1160 throwSyntaxError("'}' expected at end of class body.");
1163 throwSyntaxError("'{' expected at start of class body.");
1166 private void class_entry_type() {
1168 // | T_ABSTRACT T_CLASS
1169 // | T_FINAL T_CLASS
1170 if (token == TokenNameclass) {
1172 } else if (token == TokenNameabstract) {
1173 checkAndSetModifiers(AccAbstract);
1175 if (token != TokenNameclass) {
1176 throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
1179 } else if (token == TokenNamefinal) {
1180 checkAndSetModifiers(AccFinal);
1182 if (token != TokenNameclass) {
1183 throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
1187 throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
1190 private void interface_extends_list() {
1192 // | T_EXTENDS interface_list
1193 if (token == TokenNameextends) {
1198 private void implements_list() {
1200 // | T_IMPLEMENTS interface_list
1201 if (token == TokenNameimplements) {
1206 private void interface_list() {
1208 // fully_qualified_class_name
1209 //| interface_list ',' fully_qualified_class_name
1211 if (token == TokenNameIdentifier) {
1214 throwSyntaxError("Interface name expected after keyword 'implements'.");
1216 if (token != TokenNameCOMMA) {
1222 // private void classBody(TypeDeclaration typeDecl) {
1223 // //'{' [class-element-list] '}'
1224 // if (token == TokenNameLBRACE) {
1226 // if (token != TokenNameRBRACE) {
1227 // class_statement_list();
1229 // if (token == TokenNameRBRACE) {
1230 // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1233 // throwSyntaxError("'}' expected at end of class body.");
1236 // throwSyntaxError("'{' expected at start of class body.");
1239 private void class_statement_list(ArrayList list) {
1241 class_statement(list);
1242 } while (token == TokenNamepublic || token == TokenNameprotected || token == TokenNameprivate || token == TokenNamestatic
1243 || token == TokenNameabstract || token == TokenNamefinal || token == TokenNamefunction || token == TokenNamevar
1244 || token == TokenNameconst);
1246 private void class_statement(ArrayList list) {
1248 // variable_modifiers class_variable_declaration ';'
1249 // | class_constant_declaration ';'
1250 // | method_modifiers T_FUNCTION is_reference T_STRING
1251 // '(' parameter_list ')' method_body
1252 initializeModifiers();
1253 int declarationSourceStart = scanner.getCurrentTokenStartPosition();
1255 if (token == TokenNamevar) {
1256 checkAndSetModifiers(AccPublic);
1257 problemReporter.phpVarDeprecatedWarning(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
1258 referenceContext, compilationUnit.compilationResult);
1260 class_variable_declaration(declarationSourceStart, list);
1261 } else if (token == TokenNameconst) {
1262 checkAndSetModifiers(AccFinal|AccPublic);
1263 class_constant_declaration(declarationSourceStart, list);
1264 if (token != TokenNameSEMICOLON) {
1265 throwSyntaxError("';' expected after class const declaration.");
1269 boolean hasModifiers = member_modifiers();
1270 if (token == TokenNamefunction) {
1271 if (!hasModifiers) {
1272 checkAndSetModifiers(AccPublic);
1274 MethodDeclaration methodDecl = new MethodDeclaration(this.compilationUnit.compilationResult);
1275 methodDecl.declarationSourceStart = scanner.getCurrentTokenStartPosition();
1276 methodDecl.modifiers = this.modifiers;
1278 functionDefinition(methodDecl);
1280 if (!hasModifiers) {
1281 throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
1283 class_variable_declaration(declarationSourceStart, list);
1287 private void class_constant_declaration(int declarationSourceStart, ArrayList list) {
1288 // class_constant_declaration ',' T_STRING '=' static_scalar
1289 // | T_CONST T_STRING '=' static_scalar
1290 if (token != TokenNameconst) {
1291 throwSyntaxError("'const' keyword expected in class declaration.");
1296 if (token != TokenNameIdentifier) {
1297 throwSyntaxError("Identifier expected in class const declaration.");
1299 FieldDeclaration fieldDeclaration = new FieldDeclaration(scanner.getCurrentIdentifierSource(), scanner
1300 .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1301 fieldDeclaration.modifiers = this.modifiers;
1302 fieldDeclaration.declarationSourceStart = declarationSourceStart;
1303 fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1304 fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1305 // fieldDeclaration.type
1306 list.add(fieldDeclaration);
1308 if (token != TokenNameEQUAL) {
1309 throwSyntaxError("'=' expected in class const declaration.");
1313 if (token != TokenNameCOMMA) {
1314 break; // while(true)-loop
1319 // private void variable_modifiers() {
1320 // // variable_modifiers:
1321 // // non_empty_member_modifiers
1323 // initializeModifiers();
1324 // if (token == TokenNamevar) {
1325 // checkAndSetModifiers(AccPublic);
1326 // reportSyntaxError(
1327 // "Keyword 'var' is deprecated. Please use 'public' 'private' or
1329 // modifier for field declarations.",
1330 // scanner.getCurrentTokenStartPosition(), scanner
1331 // .getCurrentTokenEndPosition());
1334 // if (!member_modifiers()) {
1335 // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
1336 // field declarations.");
1340 // private void method_modifiers() {
1341 // //method_modifiers:
1343 // //| non_empty_member_modifiers
1344 // initializeModifiers();
1345 // if (!member_modifiers()) {
1346 // checkAndSetModifiers(AccPublic);
1349 private boolean member_modifiers() {
1356 boolean foundToken = false;
1358 if (token == TokenNamepublic) {
1359 checkAndSetModifiers(AccPublic);
1362 } else if (token == TokenNameprotected) {
1363 checkAndSetModifiers(AccProtected);
1366 } else if (token == TokenNameprivate) {
1367 checkAndSetModifiers(AccPrivate);
1370 } else if (token == TokenNamestatic) {
1371 checkAndSetModifiers(AccStatic);
1374 } else if (token == TokenNameabstract) {
1375 checkAndSetModifiers(AccAbstract);
1378 } else if (token == TokenNamefinal) {
1379 checkAndSetModifiers(AccFinal);
1388 private void class_variable_declaration(int declarationSourceStart, ArrayList list) {
1389 // class_variable_declaration:
1390 // class_variable_declaration ',' T_VARIABLE
1391 // | class_variable_declaration ',' T_VARIABLE '=' static_scalar
1393 // | T_VARIABLE '=' static_scalar
1394 char[] classVariable;
1396 if (token == TokenNameVariable) {
1397 classVariable = scanner.getCurrentIdentifierSource();
1398 // indexManager.addIdentifierInformation('v', classVariable, buf, -1, -1);
1399 FieldDeclaration fieldDeclaration = new FieldDeclaration(classVariable, scanner
1400 .getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1401 fieldDeclaration.modifiers = this.modifiers;
1402 fieldDeclaration.declarationSourceStart = declarationSourceStart;
1403 fieldDeclaration.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
1404 fieldDeclaration.modifiersSourceStart = declarationSourceStart;
1405 // fieldDeclaration.type
1406 list.add(fieldDeclaration);
1408 if (token == TokenNameEQUAL) {
1413 // if (token == TokenNamethis) {
1414 // throwSyntaxError("'$this' not allowed after keyword 'public'
1415 // 'protected' 'private' 'var'.");
1417 throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
1419 if (token != TokenNameCOMMA) {
1424 if (token != TokenNameSEMICOLON) {
1425 throwSyntaxError("';' expected after field declaration.");
1429 private void functionDefinition(MethodDeclaration methodDecl) {
1430 boolean isAbstract = false;
1432 compilationUnit.types.add(methodDecl);
1434 AstNode node = astStack[astPtr];
1435 if (node instanceof TypeDeclaration) {
1436 TypeDeclaration typeDecl = ((TypeDeclaration) node);
1437 if (typeDecl.methods == null) {
1438 typeDecl.methods = new AbstractMethodDeclaration[]{methodDecl};
1440 AbstractMethodDeclaration[] newMethods;
1441 System.arraycopy(typeDecl.methods, 0, newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1], 1,
1442 typeDecl.methods.length);
1443 newMethods[0] = methodDecl;
1444 typeDecl.methods = newMethods;
1446 if ((typeDecl.modifiers & AccAbstract) == AccAbstract) {
1448 } else if ((typeDecl.modifiers & AccInterface) == AccInterface) {
1453 functionDeclarator(methodDecl);
1454 if (token == TokenNameSEMICOLON) {
1456 throwSyntaxError("Body declaration expected for method: " + new String(methodDecl.selector));
1461 functionBody(methodDecl);
1463 private void functionDeclarator(MethodDeclaration methodDecl) {
1464 //identifier '(' [parameter-list] ')'
1465 if (token == TokenNameAND) {
1468 if (token == TokenNameIdentifier) {
1469 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1470 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1471 methodDecl.selector = scanner.getCurrentIdentifierSource();
1473 if (token == TokenNameLPAREN) {
1476 throwSyntaxError("'(' expected in function declaration.");
1478 if (token != TokenNameRPAREN) {
1481 if (token != TokenNameRPAREN) {
1482 throwSyntaxError("')' expected in function declaration.");
1484 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1488 if (token > TokenNameKEYWORD) {
1489 throwSyntaxError("Don't use keyword for function declaration [" + token + "].");
1491 throwSyntaxError("Function name expected after keyword 'function'.");
1495 private void parameter_list() {
1496 // non_empty_parameter_list
1498 non_empty_parameter_list(true);
1500 private void non_empty_parameter_list(boolean empty_allowed) {
1501 // optional_class_type T_VARIABLE
1502 // | optional_class_type '&' T_VARIABLE
1503 // | optional_class_type '&' T_VARIABLE '=' static_scalar
1504 // | optional_class_type T_VARIABLE '=' static_scalar
1505 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE
1506 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
1507 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
1509 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
1511 if (token == TokenNameIdentifier || token == TokenNameVariable || token == TokenNameAND) {
1513 if (token == TokenNameIdentifier) {
1516 if (token == TokenNameAND) {
1519 if (token == TokenNameVariable) {
1521 if (token == TokenNameEQUAL) {
1526 throwSyntaxError("Variable expected in parameter list.");
1528 if (token != TokenNameCOMMA) {
1535 if (!empty_allowed) {
1536 throwSyntaxError("Identifier expected in parameter list.");
1539 private void optional_class_type() {
1543 private void parameterDeclaration() {
1545 //variable-reference
1546 if (token == TokenNameAND) {
1551 throwSyntaxError("Variable expected after reference operator '&'.");
1554 //variable '=' constant
1555 if (token == TokenNameVariable) {
1557 if (token == TokenNameEQUAL) {
1563 // if (token == TokenNamethis) {
1564 // throwSyntaxError("Reserved word '$this' not allowed in parameter
1568 private void labeledStatementList() {
1569 if (token != TokenNamecase && token != TokenNamedefault) {
1570 throwSyntaxError("'case' or 'default' expected.");
1573 if (token == TokenNamecase) {
1575 expr(); //constant();
1576 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1578 if (token == TokenNamecase || token == TokenNamedefault) {
1579 // empty case statement ?
1584 // else if (token == TokenNameSEMICOLON) {
1586 // "':' expected after 'case' keyword (Found token: " +
1587 // scanner.toStringAction(token) + ")",
1588 // scanner.getCurrentTokenStartPosition(),
1589 // scanner.getCurrentTokenEndPosition(),
1592 // if (token == TokenNamecase) { // empty case statement ?
1598 throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
1600 } else { // TokenNamedefault
1602 if (token == TokenNameCOLON) {
1604 if (token == TokenNameRBRACE) {
1605 // empty default case
1610 throwSyntaxError("':' character after 'default' expected.");
1613 } while (token == TokenNamecase || token == TokenNamedefault);
1615 // public void labeledStatement() {
1616 // if (token == TokenNamecase) {
1619 // if (token == TokenNameDDOT) {
1623 // throwSyntaxError("':' character after 'case' constant expected.");
1626 // } else if (token == TokenNamedefault) {
1628 // if (token == TokenNameDDOT) {
1632 // throwSyntaxError("':' character after 'default' expected.");
1637 // public void expressionStatement() {
1639 // private void inclusionStatement() {
1641 // public void compoundStatement() {
1643 // public void selectionStatement() {
1646 // public void iterationStatement() {
1649 // public void jumpStatement() {
1652 // public void outputStatement() {
1655 // public void scopeStatement() {
1658 // public void flowStatement() {
1661 // public void definitionStatement() {
1663 private void ifStatement() {
1664 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1665 if (token == TokenNameCOLON) {
1667 if (token != TokenNameendif) {
1670 case TokenNameelse :
1672 if (token == TokenNameCOLON) {
1674 if (token != TokenNameendif) {
1678 if (token == TokenNameif) { //'else if'
1680 elseifStatementList();
1682 throwSyntaxError("':' expected after 'else'.");
1686 case TokenNameelseif :
1688 elseifStatementList();
1692 if (token != TokenNameendif) {
1693 throwSyntaxError("'endif' expected.");
1696 if (token != TokenNameSEMICOLON) {
1697 throwSyntaxError("';' expected after if-statement.");
1701 // statement [else-statement]
1702 statement(TokenNameEOF);
1703 if (token == TokenNameelseif) {
1705 if (token == TokenNameLPAREN) {
1708 throwSyntaxError("'(' expected after 'elseif' keyword.");
1711 if (token == TokenNameRPAREN) {
1714 throwSyntaxError("')' expected after 'elseif' condition.");
1717 } else if (token == TokenNameelse) {
1719 statement(TokenNameEOF);
1723 private void elseifStatementList() {
1727 case TokenNameelse :
1729 if (token == TokenNameCOLON) {
1731 if (token != TokenNameendif) {
1736 if (token == TokenNameif) { //'else if'
1739 throwSyntaxError("':' expected after 'else'.");
1743 case TokenNameelseif :
1751 private void elseifStatement() {
1752 if (token == TokenNameLPAREN) {
1755 if (token != TokenNameRPAREN) {
1756 throwSyntaxError("')' expected in else-if-statement.");
1759 if (token != TokenNameCOLON) {
1760 throwSyntaxError("':' expected in else-if-statement.");
1763 if (token != TokenNameendif) {
1768 private void switchStatement() {
1769 if (token == TokenNameCOLON) {
1770 // ':' [labeled-statement-list] 'endswitch' ';'
1772 labeledStatementList();
1773 if (token != TokenNameendswitch) {
1774 throwSyntaxError("'endswitch' expected.");
1777 if (token != TokenNameSEMICOLON) {
1778 throwSyntaxError("';' expected after switch-statement.");
1782 // '{' [labeled-statement-list] '}'
1783 if (token != TokenNameLBRACE) {
1784 throwSyntaxError("'{' expected in switch statement.");
1787 if (token != TokenNameRBRACE) {
1788 labeledStatementList();
1790 if (token != TokenNameRBRACE) {
1791 throwSyntaxError("'}' expected in switch statement.");
1796 private void forStatement() {
1797 if (token == TokenNameCOLON) {
1800 if (token != TokenNameendfor) {
1801 throwSyntaxError("'endfor' expected.");
1804 if (token != TokenNameSEMICOLON) {
1805 throwSyntaxError("';' expected after for-statement.");
1809 statement(TokenNameEOF);
1812 private void whileStatement() {
1813 // ':' statement-list 'endwhile' ';'
1814 if (token == TokenNameCOLON) {
1817 if (token != TokenNameendwhile) {
1818 throwSyntaxError("'endwhile' expected.");
1821 if (token != TokenNameSEMICOLON) {
1822 throwSyntaxError("';' expected after while-statement.");
1826 statement(TokenNameEOF);
1829 private void foreachStatement() {
1830 if (token == TokenNameCOLON) {
1833 if (token != TokenNameendforeach) {
1834 throwSyntaxError("'endforeach' expected.");
1837 if (token != TokenNameSEMICOLON) {
1838 throwSyntaxError("';' expected after foreach-statement.");
1842 statement(TokenNameEOF);
1845 // private void exitStatus() {
1846 // if (token == TokenNameLPAREN) {
1849 // throwSyntaxError("'(' expected in 'exit-status'.");
1851 // if (token != TokenNameRPAREN) {
1854 // if (token == TokenNameRPAREN) {
1857 // throwSyntaxError("')' expected after 'exit-status'.");
1860 private void expressionList() {
1863 if (token == TokenNameCOMMA) {
1870 private void expr() {
1872 // | expr_without_variable
1873 // if (token!=TokenNameEOF) {
1874 if (Scanner.TRACE) {
1875 System.out.println("TRACE: expr()");
1877 expr_without_variable(true);
1880 private void expr_without_variable(boolean only_variable) {
1881 // internal_functions_in_yacc
1890 // | T_INC rw_variable
1891 // | T_DEC rw_variable
1892 // | T_INT_CAST expr
1893 // | T_DOUBLE_CAST expr
1894 // | T_STRING_CAST expr
1895 // | T_ARRAY_CAST expr
1896 // | T_OBJECT_CAST expr
1897 // | T_BOOL_CAST expr
1898 // | T_UNSET_CAST expr
1899 // | T_EXIT exit_expr
1901 // | T_ARRAY '(' array_pair_list ')'
1902 // | '`' encaps_list '`'
1903 // | T_LIST '(' assignment_list ')' '=' expr
1904 // | T_NEW class_name_reference ctor_arguments
1905 // | variable '=' expr
1906 // | variable '=' '&' variable
1907 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
1908 // | variable T_PLUS_EQUAL expr
1909 // | variable T_MINUS_EQUAL expr
1910 // | variable T_MUL_EQUAL expr
1911 // | variable T_DIV_EQUAL expr
1912 // | variable T_CONCAT_EQUAL expr
1913 // | variable T_MOD_EQUAL expr
1914 // | variable T_AND_EQUAL expr
1915 // | variable T_OR_EQUAL expr
1916 // | variable T_XOR_EQUAL expr
1917 // | variable T_SL_EQUAL expr
1918 // | variable T_SR_EQUAL expr
1919 // | rw_variable T_INC
1920 // | rw_variable T_DEC
1921 // | expr T_BOOLEAN_OR expr
1922 // | expr T_BOOLEAN_AND expr
1923 // | expr T_LOGICAL_OR expr
1924 // | expr T_LOGICAL_AND expr
1925 // | expr T_LOGICAL_XOR expr
1937 // | expr T_IS_IDENTICAL expr
1938 // | expr T_IS_NOT_IDENTICAL expr
1939 // | expr T_IS_EQUAL expr
1940 // | expr T_IS_NOT_EQUAL expr
1942 // | expr T_IS_SMALLER_OR_EQUAL expr
1944 // | expr T_IS_GREATER_OR_EQUAL expr
1945 // | expr T_INSTANCEOF class_name_reference
1946 // | expr '?' expr ':' expr
1947 if (Scanner.TRACE) {
1948 System.out.println("TRACE: expr_without_variable() PART 1");
1951 case TokenNameisset :
1952 case TokenNameempty :
1953 case TokenNameeval :
1954 case TokenNameinclude :
1955 case TokenNameinclude_once :
1956 case TokenNamerequire :
1957 case TokenNamerequire_once :
1958 internal_functions_in_yacc();
1961 case TokenNameLPAREN :
1964 if (token == TokenNameRPAREN) {
1967 throwSyntaxError("')' expected in expression.");
1977 // | T_INT_CAST expr
1978 // | T_DOUBLE_CAST expr
1979 // | T_STRING_CAST expr
1980 // | T_ARRAY_CAST expr
1981 // | T_OBJECT_CAST expr
1982 // | T_BOOL_CAST expr
1983 // | T_UNSET_CAST expr
1984 case TokenNameclone :
1985 case TokenNameprint :
1987 case TokenNamePLUS :
1988 case TokenNameMINUS :
1990 case TokenNameTWIDDLE :
1991 case TokenNameintCAST :
1992 case TokenNamedoubleCAST :
1993 case TokenNamestringCAST :
1994 case TokenNamearrayCAST :
1995 case TokenNameobjectCAST :
1996 case TokenNameboolCAST :
1997 case TokenNameunsetCAST :
2001 case TokenNameexit :
2007 //| T_STRING_VARNAME
2009 //| T_START_HEREDOC encaps_list T_END_HEREDOC
2010 // | '`' encaps_list '`'
2012 // | '`' encaps_list '`'
2013 case TokenNameEncapsedString0 :
2014 scanner.encapsedStringStack.push(new Character('`'));
2017 if (token == TokenNameEncapsedString0) {
2020 if (token != TokenNameEncapsedString0) {
2021 throwSyntaxError("\'`\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2025 scanner.encapsedStringStack.pop();
2029 // | '\'' encaps_list '\''
2030 case TokenNameEncapsedString1 :
2031 scanner.encapsedStringStack.push(new Character('\''));
2034 if (token == TokenNameEncapsedString1) {
2037 if (token != TokenNameEncapsedString1) {
2038 throwSyntaxError("\'\'\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2042 scanner.encapsedStringStack.pop();
2046 //| '"' encaps_list '"'
2047 case TokenNameEncapsedString2 :
2048 scanner.encapsedStringStack.push(new Character('"'));
2051 if (token == TokenNameEncapsedString2) {
2054 if (token != TokenNameEncapsedString2) {
2055 throwSyntaxError("'\"' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2059 scanner.encapsedStringStack.pop();
2063 case TokenNameIntegerLiteral :
2064 case TokenNameDoubleLiteral :
2065 case TokenNameStringDoubleQuote :
2066 case TokenNameStringSingleQuote :
2067 case TokenNameStringInterpolated :
2068 case TokenNameFILE :
2069 case TokenNameLINE :
2070 case TokenNameCLASS_C :
2071 case TokenNameMETHOD_C :
2072 case TokenNameFUNC_C :
2075 case TokenNameHEREDOC :
2078 case TokenNamearray :
2079 // T_ARRAY '(' array_pair_list ')'
2081 if (token == TokenNameLPAREN) {
2083 if (token == TokenNameRPAREN) {
2088 if (token != TokenNameRPAREN) {
2089 throwSyntaxError("')' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2093 throwSyntaxError("'(' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2096 case TokenNamelist :
2097 // | T_LIST '(' assignment_list ')' '=' expr
2099 if (token == TokenNameLPAREN) {
2102 if (token != TokenNameRPAREN) {
2103 throwSyntaxError("')' expected after 'list' keyword.");
2106 if (token != TokenNameEQUAL) {
2107 throwSyntaxError("'=' expected after 'list' keyword.");
2112 throwSyntaxError("'(' expected after 'list' keyword.");
2116 // | T_NEW class_name_reference ctor_arguments
2118 class_name_reference();
2121 // | T_INC rw_variable
2122 // | T_DEC rw_variable
2123 case TokenNamePLUS_PLUS :
2124 case TokenNameMINUS_MINUS :
2128 // | variable '=' expr
2129 // | variable '=' '&' variable
2130 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2131 // | variable T_PLUS_EQUAL expr
2132 // | variable T_MINUS_EQUAL expr
2133 // | variable T_MUL_EQUAL expr
2134 // | variable T_DIV_EQUAL expr
2135 // | variable T_CONCAT_EQUAL expr
2136 // | variable T_MOD_EQUAL expr
2137 // | variable T_AND_EQUAL expr
2138 // | variable T_OR_EQUAL expr
2139 // | variable T_XOR_EQUAL expr
2140 // | variable T_SL_EQUAL expr
2141 // | variable T_SR_EQUAL expr
2142 // | rw_variable T_INC
2143 // | rw_variable T_DEC
2144 case TokenNameIdentifier :
2145 case TokenNameVariable :
2146 case TokenNameDOLLAR :
2149 case TokenNameEQUAL :
2151 if (token == TokenNameAND) {
2153 if (token == TokenNamenew) {
2154 // | variable '=' '&' T_NEW class_name_reference
2157 class_name_reference();
2166 case TokenNamePLUS_EQUAL :
2167 case TokenNameMINUS_EQUAL :
2168 case TokenNameMULTIPLY_EQUAL :
2169 case TokenNameDIVIDE_EQUAL :
2170 case TokenNameDOT_EQUAL :
2171 case TokenNameREMAINDER_EQUAL :
2172 case TokenNameAND_EQUAL :
2173 case TokenNameOR_EQUAL :
2174 case TokenNameXOR_EQUAL :
2175 case TokenNameRIGHT_SHIFT_EQUAL :
2176 case TokenNameLEFT_SHIFT_EQUAL :
2180 case TokenNamePLUS_PLUS :
2181 case TokenNameMINUS_MINUS :
2185 if (!only_variable) {
2186 throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "').");
2191 if (token != TokenNameINLINE_HTML) {
2192 if (token > TokenNameKEYWORD) {
2196 throwSyntaxError("Error in expression (found token '" + scanner.toStringAction(token) + "').");
2201 if (Scanner.TRACE) {
2202 System.out.println("TRACE: expr_without_variable() PART 2");
2204 // | expr T_BOOLEAN_OR expr
2205 // | expr T_BOOLEAN_AND expr
2206 // | expr T_LOGICAL_OR expr
2207 // | expr T_LOGICAL_AND expr
2208 // | expr T_LOGICAL_XOR expr
2220 // | expr T_IS_IDENTICAL expr
2221 // | expr T_IS_NOT_IDENTICAL expr
2222 // | expr T_IS_EQUAL expr
2223 // | expr T_IS_NOT_EQUAL expr
2225 // | expr T_IS_SMALLER_OR_EQUAL expr
2227 // | expr T_IS_GREATER_OR_EQUAL expr
2230 case TokenNameOR_OR :
2231 case TokenNameAND_AND :
2239 case TokenNamePLUS :
2240 case TokenNameMINUS :
2241 case TokenNameMULTIPLY :
2242 case TokenNameDIVIDE :
2243 case TokenNameREMAINDER :
2244 case TokenNameLEFT_SHIFT :
2245 case TokenNameRIGHT_SHIFT :
2246 case TokenNameEQUAL_EQUAL_EQUAL :
2247 case TokenNameNOT_EQUAL_EQUAL :
2248 case TokenNameEQUAL_EQUAL :
2249 case TokenNameNOT_EQUAL :
2250 case TokenNameLESS :
2251 case TokenNameLESS_EQUAL :
2252 case TokenNameGREATER :
2253 case TokenNameGREATER_EQUAL :
2257 // | expr T_INSTANCEOF class_name_reference
2258 // | expr '?' expr ':' expr
2259 case TokenNameinstanceof :
2261 class_name_reference();
2263 case TokenNameQUESTION :
2266 if (token == TokenNameCOLON) {
2276 private void class_name_reference() {
2277 // class_name_reference:
2279 //| dynamic_class_name_reference
2280 if (Scanner.TRACE) {
2281 System.out.println("TRACE: class_name_reference()");
2283 if (token == TokenNameIdentifier) {
2286 dynamic_class_name_reference();
2289 private void dynamic_class_name_reference() {
2290 //dynamic_class_name_reference:
2291 // base_variable T_OBJECT_OPERATOR object_property
2292 // dynamic_class_name_variable_properties
2294 if (Scanner.TRACE) {
2295 System.out.println("TRACE: dynamic_class_name_reference()");
2298 if (token == TokenNameMINUS_GREATER) {
2301 dynamic_class_name_variable_properties();
2304 private void dynamic_class_name_variable_properties() {
2305 // dynamic_class_name_variable_properties:
2306 // dynamic_class_name_variable_properties
2307 // dynamic_class_name_variable_property
2309 if (Scanner.TRACE) {
2310 System.out.println("TRACE: dynamic_class_name_variable_properties()");
2312 while (token == TokenNameMINUS_GREATER) {
2313 dynamic_class_name_variable_property();
2316 private void dynamic_class_name_variable_property() {
2317 // dynamic_class_name_variable_property:
2318 // T_OBJECT_OPERATOR object_property
2319 if (Scanner.TRACE) {
2320 System.out.println("TRACE: dynamic_class_name_variable_property()");
2322 if (token == TokenNameMINUS_GREATER) {
2327 private void ctor_arguments() {
2330 //| '(' function_call_parameter_list ')'
2331 if (token == TokenNameLPAREN) {
2333 if (token == TokenNameRPAREN) {
2337 non_empty_function_call_parameter_list();
2338 if (token != TokenNameRPAREN) {
2339 throwSyntaxError("')' expected in ctor_arguments.");
2344 private void assignment_list() {
2346 // assignment_list ',' assignment_list_element
2347 //| assignment_list_element
2349 assignment_list_element();
2350 if (token != TokenNameCOMMA) {
2356 private void assignment_list_element() {
2357 //assignment_list_element:
2359 //| T_LIST '(' assignment_list ')'
2361 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2364 if (token == TokenNamelist) {
2366 if (token == TokenNameLPAREN) {
2369 if (token != TokenNameRPAREN) {
2370 throwSyntaxError("')' expected after 'list' keyword.");
2374 throwSyntaxError("'(' expected after 'list' keyword.");
2379 private void array_pair_list() {
2382 //| non_empty_array_pair_list possible_comma
2383 non_empty_array_pair_list();
2384 if (token == TokenNameCOMMA) {
2388 private void non_empty_array_pair_list() {
2389 //non_empty_array_pair_list:
2390 // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2391 //| non_empty_array_pair_list ',' expr
2392 //| expr T_DOUBLE_ARROW expr
2394 //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2395 //| non_empty_array_pair_list ',' '&' w_variable
2396 //| expr T_DOUBLE_ARROW '&' w_variable
2399 if (token == TokenNameAND) {
2404 if (token == TokenNameAND) {
2407 } else if (token == TokenNameEQUAL_GREATER) {
2409 if (token == TokenNameAND) {
2417 if (token != TokenNameCOMMA) {
2421 if (token == TokenNameRPAREN) {
2426 // private void variableList() {
2429 // if (token == TokenNameCOMMA) {
2436 private void variable_without_objects() {
2437 // variable_without_objects:
2438 // reference_variable
2439 // | simple_indirect_reference reference_variable
2440 if (Scanner.TRACE) {
2441 System.out.println("TRACE: variable_without_objects()");
2443 while (token == TokenNameDOLLAR) {
2446 reference_variable();
2448 private void function_call() {
2450 // T_STRING '(' function_call_parameter_list ')'
2451 //| class_constant '(' function_call_parameter_list ')'
2452 //| static_member '(' function_call_parameter_list ')'
2453 //| variable_without_objects '(' function_call_parameter_list ')'
2454 if (Scanner.TRACE) {
2455 System.out.println("TRACE: function_call()");
2457 if (token == TokenNameIdentifier) {
2460 case TokenNamePAAMAYIM_NEKUDOTAYIM :
2463 if (token == TokenNameIdentifier) {
2468 variable_without_objects();
2473 variable_without_objects();
2475 if (token != TokenNameLPAREN) {
2476 // TODO is this ok ?
2478 // throwSyntaxError("'(' expected in function call.");
2481 if (token == TokenNameRPAREN) {
2485 non_empty_function_call_parameter_list();
2486 if (token != TokenNameRPAREN) {
2487 throwSyntaxError("')' expected in function call.");
2491 // private void function_call_parameter_list() {
2492 // function_call_parameter_list:
2493 // non_empty_function_call_parameter_list { $$ = $1; }
2496 private void non_empty_function_call_parameter_list() {
2497 //non_empty_function_call_parameter_list:
2498 // expr_without_variable
2501 // | non_empty_function_call_parameter_list ',' expr_without_variable
2502 // | non_empty_function_call_parameter_list ',' variable
2503 // | non_empty_function_call_parameter_list ',' '&' w_variable
2504 if (Scanner.TRACE) {
2505 System.out.println("TRACE: non_empty_function_call_parameter_list()");
2508 if (token == TokenNameAND) {
2512 // if (token == TokenNameIdentifier || token ==
2513 // TokenNameVariable
2514 // || token == TokenNameDOLLAR) {
2517 expr_without_variable(true);
2520 if (token != TokenNameCOMMA) {
2526 private void fully_qualified_class_name() {
2527 if (token == TokenNameIdentifier) {
2530 throwSyntaxError("Class name expected.");
2533 private void static_member() {
2535 // fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
2536 // variable_without_objects
2537 if (Scanner.TRACE) {
2538 System.out.println("TRACE: static_member()");
2540 fully_qualified_class_name();
2541 if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
2542 throwSyntaxError("'::' expected after class name (static_member).");
2545 variable_without_objects();
2547 private void base_variable_with_function_calls() {
2548 // base_variable_with_function_calls:
2551 boolean functionCall = false;
2552 if (Scanner.TRACE) {
2553 System.out.println("TRACE: base_variable_with_function_calls()");
2555 // if (token == TokenNameIdentifier) {
2556 // functionCall = true;
2557 // } else if (token == TokenNameVariable) {
2558 // int tempToken = token;
2559 // int tempPosition = scanner.currentPosition;
2561 // if (token == TokenNameLPAREN) {
2562 // functionCall = true;
2564 // token = tempToken;
2565 // scanner.currentPosition = tempPosition;
2566 // scanner.phpMode = true;
2568 // if (functionCall) {
2574 private void base_variable() {
2576 // reference_variable
2577 // | simple_indirect_reference reference_variable
2579 if (Scanner.TRACE) {
2580 System.out.println("TRACE: base_variable()");
2582 if (token == TokenNameIdentifier) {
2585 while (token == TokenNameDOLLAR) {
2588 reference_variable();
2591 // private void simple_indirect_reference() {
2592 // // simple_indirect_reference:
2594 // //| simple_indirect_reference '$'
2596 private void reference_variable() {
2597 // reference_variable:
2598 // reference_variable '[' dim_offset ']'
2599 // | reference_variable '{' expr '}'
2600 // | compound_variable
2601 if (Scanner.TRACE) {
2602 System.out.println("TRACE: reference_variable()");
2604 compound_variable();
2606 if (token == TokenNameLBRACE) {
2609 if (token != TokenNameRBRACE) {
2610 throwSyntaxError("'}' expected in reference variable.");
2613 } else if (token == TokenNameLBRACKET) {
2615 if (token != TokenNameRBRACKET) {
2618 if (token != TokenNameRBRACKET) {
2619 throwSyntaxError("']' expected in reference variable.");
2628 private void compound_variable() {
2629 // compound_variable:
2631 // | '$' '{' expr '}'
2632 if (Scanner.TRACE) {
2633 System.out.println("TRACE: compound_variable()");
2635 if (token == TokenNameVariable) {
2638 // because of simple_indirect_reference
2639 while (token == TokenNameDOLLAR) {
2642 if (token != TokenNameLBRACE) {
2643 throwSyntaxError("'{' expected after compound variable token '$'.");
2647 if (token != TokenNameRBRACE) {
2648 throwSyntaxError("'}' expected after compound variable token '$'.");
2653 // private void dim_offset() {
2659 private void object_property() {
2662 //| variable_without_objects
2663 if (Scanner.TRACE) {
2664 System.out.println("TRACE: object_property()");
2666 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2667 variable_without_objects();
2672 private void object_dim_list() {
2674 // object_dim_list '[' dim_offset ']'
2675 //| object_dim_list '{' expr '}'
2677 if (Scanner.TRACE) {
2678 System.out.println("TRACE: object_dim_list()");
2682 if (token == TokenNameLBRACE) {
2685 if (token != TokenNameRBRACE) {
2686 throwSyntaxError("'}' expected in object_dim_list.");
2689 } else if (token == TokenNameLBRACKET) {
2691 if (token == TokenNameRBRACKET) {
2696 if (token != TokenNameRBRACKET) {
2697 throwSyntaxError("']' expected in object_dim_list.");
2705 private void variable_name() {
2709 if (Scanner.TRACE) {
2710 System.out.println("TRACE: variable_name()");
2712 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
2713 if (token > TokenNameKEYWORD) {
2714 // TODO show a warning "Keyword used as variable" ?
2718 if (token != TokenNameLBRACE) {
2719 throwSyntaxError("'{' expected in variable name.");
2723 if (token != TokenNameRBRACE) {
2724 throwSyntaxError("'}' expected in variable name.");
2729 private void r_variable() {
2732 private void w_variable() {
2735 private void rw_variable() {
2738 private void variable() {
2740 // base_variable_with_function_calls T_OBJECT_OPERATOR
2741 // object_property method_or_not variable_properties
2742 // | base_variable_with_function_calls
2743 base_variable_with_function_calls();
2744 if (token == TokenNameMINUS_GREATER) {
2748 variable_properties();
2750 // if (token == TokenNameDOLLAR_LBRACE) {
2754 // if (token != TokenNameRBRACE) {
2755 // throwSyntaxError("'}' expected after indirect variable token '${'.");
2759 // if (token == TokenNameVariable) {
2761 // if (token == TokenNameLBRACKET) {
2764 // if (token != TokenNameRBRACKET) {
2765 // throwSyntaxError("']' expected in variable-list.");
2768 // } else if (token == TokenNameEQUAL) {
2773 // throwSyntaxError("$-variable expected in variable-list.");
2777 private void variable_properties() {
2778 // variable_properties:
2779 // variable_properties variable_property
2781 while (token == TokenNameMINUS_GREATER) {
2782 variable_property();
2785 private void variable_property() {
2786 // variable_property:
2787 // T_OBJECT_OPERATOR object_property method_or_not
2788 if (Scanner.TRACE) {
2789 System.out.println("TRACE: variable_property()");
2791 if (token == TokenNameMINUS_GREATER) {
2796 throwSyntaxError("'->' expected in variable_property.");
2799 private void method_or_not() {
2801 // '(' function_call_parameter_list ')'
2803 if (Scanner.TRACE) {
2804 System.out.println("TRACE: method_or_not()");
2806 if (token == TokenNameLPAREN) {
2808 if (token == TokenNameRPAREN) {
2812 non_empty_function_call_parameter_list();
2813 if (token != TokenNameRPAREN) {
2814 throwSyntaxError("')' expected in method_or_not.");
2819 private void exit_expr() {
2823 if (token != TokenNameLPAREN) {
2827 if (token == TokenNameRPAREN) {
2832 if (token != TokenNameRPAREN) {
2833 throwSyntaxError("')' expected after keyword 'exit'");
2837 private void encaps_list() {
2838 // encaps_list encaps_var
2839 // | encaps_list T_STRING
2840 // | encaps_list T_NUM_STRING
2841 // | encaps_list T_ENCAPSED_AND_WHITESPACE
2842 // | encaps_list T_CHARACTER
2843 // | encaps_list T_BAD_CHARACTER
2844 // | encaps_list '['
2845 // | encaps_list ']'
2846 // | encaps_list '{'
2847 // | encaps_list '}'
2848 // | encaps_list T_OBJECT_OPERATOR
2852 case TokenNameSTRING :
2855 case TokenNameLBRACE :
2856 // scanner.encapsedStringStack.pop();
2859 case TokenNameRBRACE :
2860 // scanner.encapsedStringStack.pop();
2863 case TokenNameLBRACKET :
2864 // scanner.encapsedStringStack.pop();
2867 case TokenNameRBRACKET :
2868 // scanner.encapsedStringStack.pop();
2871 case TokenNameMINUS_GREATER :
2872 // scanner.encapsedStringStack.pop();
2875 case TokenNameVariable :
2876 case TokenNameDOLLAR_LBRACE :
2877 case TokenNameCURLY_OPEN :
2880 // case TokenNameDOLLAR :
2882 // if (token == TokenNameLBRACE) {
2883 // token = TokenNameDOLLAR_LBRACE;
2888 char encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
2889 if (encapsedChar == '$') {
2890 scanner.encapsedStringStack.pop();
2891 encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
2892 switch (encapsedChar) {
2894 if (token == TokenNameEncapsedString0) {
2897 token = TokenNameSTRING;
2900 if (token == TokenNameEncapsedString1) {
2903 token = TokenNameSTRING;
2906 if (token == TokenNameEncapsedString2) {
2909 token = TokenNameSTRING;
2917 private void encaps_var() {
2919 // | T_VARIABLE '[' encaps_var_offset ']'
2920 // | T_VARIABLE T_OBJECT_OPERATOR T_STRING
2921 // | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
2922 // | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
2923 // | T_CURLY_OPEN variable '}'
2925 case TokenNameVariable :
2927 if (token == TokenNameLBRACKET) {
2929 // if (token == TokenNameRBRACKET) {
2932 expr(); //encaps_var_offset();
2933 if (token != TokenNameRBRACKET) {
2934 throwSyntaxError("']' expected after variable.");
2936 // scanner.encapsedStringStack.pop();
2939 } else if (token == TokenNameMINUS_GREATER) {
2941 if (token != TokenNameIdentifier) {
2942 throwSyntaxError("Identifier expected after '->'.");
2944 // scanner.encapsedStringStack.pop();
2948 // // scanner.encapsedStringStack.pop();
2949 // int tempToken = TokenNameSTRING;
2950 // if (!scanner.encapsedStringStack.isEmpty()
2951 // && (token == TokenNameEncapsedString0
2952 // || token == TokenNameEncapsedString1
2953 // || token == TokenNameEncapsedString2 || token ==
2954 // TokenNameERROR)) {
2955 // char encapsedChar = ((Character)
2956 // scanner.encapsedStringStack.peek())
2959 // case TokenNameEncapsedString0 :
2960 // if (encapsedChar == '`') {
2961 // tempToken = TokenNameEncapsedString0;
2964 // case TokenNameEncapsedString1 :
2965 // if (encapsedChar == '\'') {
2966 // tempToken = TokenNameEncapsedString1;
2969 // case TokenNameEncapsedString2 :
2970 // if (encapsedChar == '"') {
2971 // tempToken = TokenNameEncapsedString2;
2974 // case TokenNameERROR :
2975 // if (scanner.source[scanner.currentPosition - 1] == '\\') {
2976 // scanner.currentPosition--;
2982 // token = tempToken;
2985 case TokenNameDOLLAR_LBRACE :
2987 if (token == TokenNameIdentifier) {
2989 if (token == TokenNameLBRACKET) {
2991 // if (token == TokenNameRBRACKET) {
2995 if (token != TokenNameRBRACKET) {
2996 throwSyntaxError("']' expected after '${'.");
3001 if (token != TokenNameRBRACE) {
3002 throwSyntaxError("'}' expected after '${'.");
3004 // scanner.encapsedStringStack.pop();
3008 if (token != TokenNameRBRACE) {
3009 throwSyntaxError("'}' expected.");
3011 // scanner.encapsedStringStack.pop();
3015 case TokenNameCURLY_OPEN :
3017 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
3019 if (token == TokenNameLBRACKET) {
3021 // if (token == TokenNameRBRACKET) {
3025 if (token != TokenNameRBRACKET) {
3026 throwSyntaxError("']' expected after '{$'.");
3030 } else if (token == TokenNameMINUS_GREATER) {
3032 if (token != TokenNameIdentifier) {
3033 throwSyntaxError("String token expected.");
3037 // if (token != TokenNameRBRACE) {
3038 // throwSyntaxError("'}' expected after '{$'.");
3040 // // scanner.encapsedStringStack.pop();
3044 if (token != TokenNameRBRACE) {
3045 throwSyntaxError("'}' expected.");
3047 // scanner.encapsedStringStack.pop();
3053 private void encaps_var_offset() {
3058 case TokenNameSTRING :
3061 case TokenNameIntegerLiteral :
3064 case TokenNameVariable :
3067 case TokenNameIdentifier :
3071 throwSyntaxError("Variable or String token expected.");
3075 private void internal_functions_in_yacc() {
3077 ImportReference impt = null;
3079 case TokenNameisset :
3080 // T_ISSET '(' isset_variables ')'
3082 if (token != TokenNameLPAREN) {
3083 throwSyntaxError("'(' expected after keyword 'isset'");
3087 if (token != TokenNameRPAREN) {
3088 throwSyntaxError("')' expected after keyword 'isset'");
3092 case TokenNameempty :
3093 // T_EMPTY '(' variable ')'
3095 if (token != TokenNameLPAREN) {
3096 throwSyntaxError("'(' expected after keyword 'empty'");
3100 if (token != TokenNameRPAREN) {
3101 throwSyntaxError("')' expected after keyword 'empty'");
3105 case TokenNameinclude :
3107 start = scanner.getCurrentTokenStartPosition();
3111 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3112 impt.declarationSourceEnd = impt.sourceEnd;
3113 impt.declarationEnd = impt.declarationSourceEnd;
3114 //endPosition is just before the ;
3115 impt.declarationSourceStart = start;
3116 includesList.add(impt);
3118 case TokenNameinclude_once :
3119 // T_INCLUDE_ONCE expr
3120 start = scanner.getCurrentTokenStartPosition();
3123 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3124 impt.declarationSourceEnd = impt.sourceEnd;
3125 impt.declarationEnd = impt.declarationSourceEnd;
3126 //endPosition is just before the ;
3127 impt.declarationSourceStart = start;
3128 includesList.add(impt);
3130 case TokenNameeval :
3131 // T_EVAL '(' expr ')'
3133 if (token != TokenNameLPAREN) {
3134 throwSyntaxError("'(' expected after keyword 'eval'");
3138 if (token != TokenNameRPAREN) {
3139 throwSyntaxError("')' expected after keyword 'eval'");
3143 case TokenNamerequire :
3145 start = scanner.getCurrentTokenStartPosition();
3148 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3149 impt.declarationSourceEnd = impt.sourceEnd;
3150 impt.declarationEnd = impt.declarationSourceEnd;
3151 //endPosition is just before the ;
3152 impt.declarationSourceStart = start;
3153 includesList.add(impt);
3155 case TokenNamerequire_once :
3156 // T_REQUIRE_ONCE expr
3157 start = scanner.getCurrentTokenStartPosition();
3160 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3161 impt.declarationSourceEnd = impt.sourceEnd;
3162 impt.declarationEnd = impt.declarationSourceEnd;
3163 //endPosition is just before the ;
3164 impt.declarationSourceStart = start;
3165 includesList.add(impt);
3169 private void isset_variables() {
3171 // | isset_variables ','
3172 if (token == TokenNameRPAREN) {
3173 throwSyntaxError("Variable expected after keyword 'isset'");
3177 if (token == TokenNameCOMMA) {
3184 private boolean common_scalar() {
3188 // | T_CONSTANT_ENCAPSED_STRING
3195 case TokenNameIntegerLiteral :
3198 case TokenNameDoubleLiteral :
3201 case TokenNameStringDoubleQuote :
3204 case TokenNameStringSingleQuote :
3207 case TokenNameStringInterpolated :
3210 case TokenNameFILE :
3213 case TokenNameLINE :
3216 case TokenNameCLASS_C :
3219 case TokenNameMETHOD_C :
3222 case TokenNameFUNC_C :
3228 private void scalar() {
3231 //| T_STRING_VARNAME
3234 //| '"' encaps_list '"'
3235 //| '\'' encaps_list '\''
3236 //| T_START_HEREDOC encaps_list T_END_HEREDOC
3237 throwSyntaxError("Not yet implemented (scalar).");
3239 private void static_scalar() {
3240 // static_scalar: /* compile-time evaluated scalars */
3243 // | '+' static_scalar
3244 // | '-' static_scalar
3245 // | T_ARRAY '(' static_array_pair_list ')'
3246 // | static_class_constant
3247 if (common_scalar()) {
3251 case TokenNameIdentifier :
3253 // static_class_constant:
3254 // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3255 if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3257 if (token == TokenNameIdentifier) {
3260 throwSyntaxError("Identifier expected after '::' operator.");
3264 case TokenNameEncapsedString0 :
3266 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3267 while (scanner.currentCharacter != '`') {
3268 if (scanner.currentCharacter == '\\') {
3269 scanner.currentPosition++;
3271 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3274 } catch (IndexOutOfBoundsException e) {
3275 throwSyntaxError("'`' expected at end of static string.");
3278 case TokenNameEncapsedString1 :
3280 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3281 while (scanner.currentCharacter != '\'') {
3282 if (scanner.currentCharacter == '\\') {
3283 scanner.currentPosition++;
3285 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3288 } catch (IndexOutOfBoundsException e) {
3289 throwSyntaxError("'\'' expected at end of static string.");
3292 case TokenNameEncapsedString2 :
3294 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3295 while (scanner.currentCharacter != '"') {
3296 if (scanner.currentCharacter == '\\') {
3297 scanner.currentPosition++;
3299 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3302 } catch (IndexOutOfBoundsException e) {
3303 throwSyntaxError("'\"' expected at end of static string.");
3306 case TokenNamePLUS :
3310 case TokenNameMINUS :
3314 case TokenNamearray :
3316 if (token != TokenNameLPAREN) {
3317 throwSyntaxError("'(' expected after keyword 'array'");
3320 if (token == TokenNameRPAREN) {
3324 non_empty_static_array_pair_list();
3325 if (token != TokenNameRPAREN) {
3326 throwSyntaxError("')' expected after keyword 'array'");
3330 // case TokenNamenull :
3333 // case TokenNamefalse :
3336 // case TokenNametrue :
3340 throwSyntaxError("Static scalar/constant expected.");
3343 private void non_empty_static_array_pair_list() {
3344 // non_empty_static_array_pair_list:
3345 // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3347 //| non_empty_static_array_pair_list ',' static_scalar
3348 //| static_scalar T_DOUBLE_ARROW static_scalar
3352 if (token == TokenNameEQUAL_GREATER) {
3356 if (token != TokenNameCOMMA) {
3360 if (token == TokenNameRPAREN) {
3365 public void reportSyntaxError() { //int act, int currentKind, int
3367 /* remember current scanner position */
3368 int startPos = scanner.startPosition;
3369 int currentPos = scanner.currentPosition;
3370 // String[] expectings;
3371 // String tokenName = name[symbol_index[currentKind]];
3372 //fetch all "accurate" possible terminals that could recover the error
3373 // int start, end = start = asi(stack[stateStackTop]);
3374 // while (asr[end] != 0)
3376 // int length = end - start;
3377 // expectings = new String[length];
3378 // if (length != 0) {
3379 // char[] indexes = new char[length];
3380 // System.arraycopy(asr, start, indexes, 0, length);
3381 // for (int i = 0; i < length; i++) {
3382 // expectings[i] = name[symbol_index[indexes[i]]];
3385 //if the pb is an EOF, try to tell the user that they are some
3386 // if (tokenName.equals(UNEXPECTED_EOF)) {
3387 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3388 // char[] tokenSource;
3390 // tokenSource = this.scanner.getCurrentTokenSource();
3391 // } catch (Exception e) {
3392 // tokenSource = new char[] {};
3394 // problemReporter().parseError(
3395 // this.scanner.startPosition,
3396 // this.scanner.currentPosition - 1,
3401 // } else { //the next test is HEAVILY grammar DEPENDENT.
3402 // if ((length == 14)
3403 // && (expectings[0] == "=") //$NON-NLS-1$
3404 // && (expectings[1] == "*=") //$NON-NLS-1$
3405 // && (expressionPtr > -1)) {
3406 // switch(currentKind) {
3407 // case TokenNameSEMICOLON:
3408 // case TokenNamePLUS:
3409 // case TokenNameMINUS:
3410 // case TokenNameDIVIDE:
3411 // case TokenNameREMAINDER:
3412 // case TokenNameMULTIPLY:
3413 // case TokenNameLEFT_SHIFT:
3414 // case TokenNameRIGHT_SHIFT:
3415 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3416 // case TokenNameLESS:
3417 // case TokenNameGREATER:
3418 // case TokenNameLESS_EQUAL:
3419 // case TokenNameGREATER_EQUAL:
3420 // case TokenNameEQUAL_EQUAL:
3421 // case TokenNameNOT_EQUAL:
3422 // case TokenNameXOR:
3423 // case TokenNameAND:
3424 // case TokenNameOR:
3425 // case TokenNameOR_OR:
3426 // case TokenNameAND_AND:
3427 // // the ; is not the expected token ==> it ends a statement when an
3428 // expression is not ended
3429 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3431 // case TokenNameRBRACE :
3432 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3435 // char[] tokenSource;
3437 // tokenSource = this.scanner.getCurrentTokenSource();
3438 // } catch (Exception e) {
3439 // tokenSource = new char[] {};
3441 // problemReporter().parseError(
3442 // this.scanner.startPosition,
3443 // this.scanner.currentPosition - 1,
3447 // this.checkAndReportBracketAnomalies(problemReporter());
3452 tokenSource = this.scanner.getCurrentTokenSource();
3453 } catch (Exception e) {
3454 tokenSource = new char[]{};
3456 // problemReporter().parseError(
3457 // this.scanner.startPosition,
3458 // this.scanner.currentPosition - 1,
3462 this.checkAndReportBracketAnomalies(problemReporter());
3465 /* reset scanner where it was */
3466 scanner.startPosition = startPos;
3467 scanner.currentPosition = currentPos;
3469 public static final int RoundBracket = 0;
3470 public static final int SquareBracket = 1;
3471 public static final int CurlyBracket = 2;
3472 public static final int BracketKinds = 3;
3473 protected int[] nestedMethod; //the ptr is nestedType
3474 protected int nestedType, dimensions;
3476 final static int AstStackIncrement = 100;
3477 protected int astPtr;
3478 protected AstNode[] astStack = new AstNode[AstStackIncrement];
3479 protected int astLengthPtr;
3480 protected int[] astLengthStack;
3481 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
3482 public CompilationUnitDeclaration compilationUnit; /*
3483 * the result from parse()
3485 protected ReferenceContext referenceContext;
3486 protected ProblemReporter problemReporter;
3487 protected CompilerOptions options;
3488 private ArrayList includesList;
3489 // protected CompilationResult compilationResult;
3491 * Returns this parser's problem reporter initialized with its reference
3492 * context. Also it is assumed that a problem is going to be reported, so
3493 * initializes the compilation result's line positions.
3495 public ProblemReporter problemReporter() {
3496 if (scanner.recordLineSeparator) {
3497 compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
3499 problemReporter.referenceContext = referenceContext;
3500 return problemReporter;
3503 * Reconsider the entire source looking for inconsistencies in {} () []
3505 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3506 scanner.wasAcr = false;
3507 boolean anomaliesDetected = false;
3509 char[] source = scanner.source;
3510 int[] leftCount = {0, 0, 0};
3511 int[] rightCount = {0, 0, 0};
3512 int[] depths = {0, 0, 0};
3513 int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
3514 int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
3515 int[][] rightPositions = new int[][]{new int[10], new int[10], new int[10]};
3516 int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
3517 scanner.currentPosition = scanner.initialPosition; //starting
3519 // (first-zero-based
3521 while (scanner.currentPosition < scanner.eofPosition) { //loop for
3526 // ---------Consume white space and handles
3527 // startPosition---------
3528 boolean isWhiteSpace;
3530 scanner.startPosition = scanner.currentPosition;
3531 // if (((scanner.currentCharacter =
3532 // source[scanner.currentPosition++]) == '\\') &&
3533 // (source[scanner.currentPosition] == 'u')) {
3534 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3536 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3537 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3538 // only record line positions we have not
3540 scanner.pushLineSeparator();
3543 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3545 } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
3546 // -------consume token until } is found---------
3547 switch (scanner.currentCharacter) {
3549 int index = leftCount[CurlyBracket]++;
3550 if (index == leftPositions[CurlyBracket].length) {
3551 System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
3552 System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
3554 leftPositions[CurlyBracket][index] = scanner.startPosition;
3555 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3559 int index = rightCount[CurlyBracket]++;
3560 if (index == rightPositions[CurlyBracket].length) {
3561 System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
3562 System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
3564 rightPositions[CurlyBracket][index] = scanner.startPosition;
3565 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3569 int index = leftCount[RoundBracket]++;
3570 if (index == leftPositions[RoundBracket].length) {
3571 System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
3572 System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
3574 leftPositions[RoundBracket][index] = scanner.startPosition;
3575 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3579 int index = rightCount[RoundBracket]++;
3580 if (index == rightPositions[RoundBracket].length) {
3581 System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
3582 System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
3584 rightPositions[RoundBracket][index] = scanner.startPosition;
3585 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3589 int index = leftCount[SquareBracket]++;
3590 if (index == leftPositions[SquareBracket].length) {
3591 System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
3592 System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
3594 leftPositions[SquareBracket][index] = scanner.startPosition;
3595 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3599 int index = rightCount[SquareBracket]++;
3600 if (index == rightPositions[SquareBracket].length) {
3601 System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
3602 System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
3604 rightPositions[SquareBracket][index] = scanner.startPosition;
3605 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3609 if (scanner.getNextChar('\\')) {
3610 scanner.scanEscapeCharacter();
3611 } else { // consume next character
3612 scanner.unicodeAsBackSlash = false;
3613 // if (((scanner.currentCharacter =
3614 // source[scanner.currentPosition++]) ==
3616 // (source[scanner.currentPosition] ==
3618 // scanner.getNextUnicodeChar();
3620 if (scanner.withoutUnicodePtr != 0) {
3621 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3625 scanner.getNextChar('\'');
3629 // consume next character
3630 scanner.unicodeAsBackSlash = false;
3631 // if (((scanner.currentCharacter =
3632 // source[scanner.currentPosition++]) == '\\') &&
3633 // (source[scanner.currentPosition] == 'u')) {
3634 // scanner.getNextUnicodeChar();
3636 if (scanner.withoutUnicodePtr != 0) {
3637 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3640 while (scanner.currentCharacter != '"') {
3641 if (scanner.currentCharacter == '\r') {
3642 if (source[scanner.currentPosition] == '\n')
3643 scanner.currentPosition++;
3644 break; // the string cannot go further that
3647 if (scanner.currentCharacter == '\n') {
3648 break; // the string cannot go further that
3651 if (scanner.currentCharacter == '\\') {
3652 scanner.scanEscapeCharacter();
3654 // consume next character
3655 scanner.unicodeAsBackSlash = false;
3656 // if (((scanner.currentCharacter =
3657 // source[scanner.currentPosition++]) == '\\')
3658 // && (source[scanner.currentPosition] == 'u'))
3660 // scanner.getNextUnicodeChar();
3662 if (scanner.withoutUnicodePtr != 0) {
3663 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3670 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3673 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3674 && (source[scanner.currentPosition] == 'u')) {
3675 //-------------unicode traitement
3677 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3678 scanner.currentPosition++;
3679 while (source[scanner.currentPosition] == 'u') {
3680 scanner.currentPosition++;
3682 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3683 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3684 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3685 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3689 scanner.currentCharacter = 'A';
3690 } //something different from \n and \r
3692 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3695 while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
3697 scanner.startPosition = scanner.currentPosition;
3698 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3699 && (source[scanner.currentPosition] == 'u')) {
3700 //-------------unicode traitement
3702 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3703 scanner.currentPosition++;
3704 while (source[scanner.currentPosition] == 'u') {
3705 scanner.currentPosition++;
3707 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3708 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3709 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3710 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3714 scanner.currentCharacter = 'A';
3715 } //something different from \n
3718 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3722 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3723 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3724 // only record line positions we
3725 // have not recorded yet
3726 scanner.pushLineSeparator();
3727 if (this.scanner.taskTags != null) {
3728 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner
3729 .getCurrentTokenEndPosition());
3735 if (test > 0) { //traditional and annotation
3737 boolean star = false;
3738 // consume next character
3739 scanner.unicodeAsBackSlash = false;
3740 // if (((scanner.currentCharacter =
3741 // source[scanner.currentPosition++]) ==
3743 // (source[scanner.currentPosition] ==
3745 // scanner.getNextUnicodeChar();
3747 if (scanner.withoutUnicodePtr != 0) {
3748 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3751 if (scanner.currentCharacter == '*') {
3755 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3756 && (source[scanner.currentPosition] == 'u')) {
3757 //-------------unicode traitement
3759 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3760 scanner.currentPosition++;
3761 while (source[scanner.currentPosition] == 'u') {
3762 scanner.currentPosition++;
3764 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3765 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3766 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3767 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3771 scanner.currentCharacter = 'A';
3772 } //something different from * and /
3774 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3777 //loop until end of comment */
3778 while ((scanner.currentCharacter != '/') || (!star)) {
3779 star = scanner.currentCharacter == '*';
3781 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3782 && (source[scanner.currentPosition] == 'u')) {
3783 //-------------unicode traitement
3785 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3786 scanner.currentPosition++;
3787 while (source[scanner.currentPosition] == 'u') {
3788 scanner.currentPosition++;
3790 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3791 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3792 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3793 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3797 scanner.currentCharacter = 'A';
3798 } //something different from * and
3801 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3805 if (this.scanner.taskTags != null) {
3806 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
3813 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3814 scanner.scanIdentifierOrKeyword(false);
3817 if (Character.isDigit(scanner.currentCharacter)) {
3818 scanner.scanNumber(false);
3822 //-----------------end switch while
3823 // try--------------------
3824 } catch (IndexOutOfBoundsException e) {
3825 break; // read until EOF
3826 } catch (InvalidInputException e) {
3827 return false; // no clue
3830 if (scanner.recordLineSeparator) {
3831 // compilationUnit.compilationResult.lineSeparatorPositions =
3832 // scanner.getLineEnds();
3834 // check placement anomalies against other kinds of brackets
3835 for (int kind = 0; kind < BracketKinds; kind++) {
3836 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3837 int start = leftPositions[kind][leftIndex]; // deepest
3839 // find matching closing bracket
3840 int depth = leftDepths[kind][leftIndex];
3842 for (int i = 0; i < rightCount[kind]; i++) {
3843 int pos = rightPositions[kind][i];
3844 // want matching bracket further in source with same
3846 if ((pos > start) && (depth == rightDepths[kind][i])) {
3851 if (end < 0) { // did not find a good closing match
3852 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
3855 // check if even number of opening/closing other brackets
3856 // in between this pair of brackets
3858 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3859 for (int i = 0; i < leftCount[otherKind]; i++) {
3860 int pos = leftPositions[otherKind][i];
3861 if ((pos > start) && (pos < end))
3864 for (int i = 0; i < rightCount[otherKind]; i++) {
3865 int pos = rightPositions[otherKind][i];
3866 if ((pos > start) && (pos < end))
3870 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket
3876 // too many opening brackets ?
3877 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3878 anomaliesDetected = true;
3879 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext,
3880 compilationUnit.compilationResult);
3882 // too many closing brackets ?
3883 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3884 anomaliesDetected = true;
3885 problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
3887 if (anomaliesDetected)
3890 return anomaliesDetected;
3891 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3892 return anomaliesDetected;
3893 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3894 return anomaliesDetected;
3897 protected void pushOnAstLengthStack(int pos) {
3899 astLengthStack[++astLengthPtr] = pos;
3900 } catch (IndexOutOfBoundsException e) {
3901 int oldStackLength = astLengthStack.length;
3902 int[] oldPos = astLengthStack;
3903 astLengthStack = new int[oldStackLength + StackIncrement];
3904 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3905 astLengthStack[astLengthPtr] = pos;
3908 protected void pushOnAstStack(AstNode node) {
3910 * add a new obj on top of the ast stack
3913 astStack[++astPtr] = node;
3914 } catch (IndexOutOfBoundsException e) {
3915 int oldStackLength = astStack.length;
3916 AstNode[] oldStack = astStack;
3917 astStack = new AstNode[oldStackLength + AstStackIncrement];
3918 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3919 astPtr = oldStackLength;
3920 astStack[astPtr] = node;
3923 astLengthStack[++astLengthPtr] = 1;
3924 } catch (IndexOutOfBoundsException e) {
3925 int oldStackLength = astLengthStack.length;
3926 int[] oldPos = astLengthStack;
3927 astLengthStack = new int[oldStackLength + AstStackIncrement];
3928 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3929 astLengthStack[astLengthPtr] = 1;
3933 protected void resetModifiers() {
3934 this.modifiers = AccDefault;
3935 this.modifiersSourceStart = -1; // <-- see comment into
3936 // modifiersFlag(int)
3937 this.scanner.commentPtr = -1;