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 methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
1469 methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
1470 if (Scanner.isIdentifierOrKeyword(token)) {
1471 methodDecl.selector = scanner.getCurrentIdentifierSource();
1472 if (token > TokenNameKEYWORD) {
1473 reportSyntaxWarning("Don't use keyword for function declaration [" + scanner.toStringAction(token) + "].",
1474 scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1475 // throwSyntaxError("Don't use keyword for function declaration [" + scanner.toStringAction(token) + "].");
1478 if (token == TokenNameLPAREN) {
1481 throwSyntaxError("'(' expected in function declaration.");
1483 if (token != TokenNameRPAREN) {
1486 if (token != TokenNameRPAREN) {
1487 throwSyntaxError("')' expected in function declaration.");
1489 methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
1493 methodDecl.selector = "<undefined>".toCharArray();
1494 throwSyntaxError("Function name expected after keyword 'function'.");
1498 private void parameter_list() {
1499 // non_empty_parameter_list
1501 non_empty_parameter_list(true);
1503 private void non_empty_parameter_list(boolean empty_allowed) {
1504 // optional_class_type T_VARIABLE
1505 // | optional_class_type '&' T_VARIABLE
1506 // | optional_class_type '&' T_VARIABLE '=' static_scalar
1507 // | optional_class_type T_VARIABLE '=' static_scalar
1508 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE
1509 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
1510 // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
1512 // | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
1514 if (token == TokenNameIdentifier || token == TokenNameVariable || token == TokenNameAND) {
1516 if (token == TokenNameIdentifier) {
1519 if (token == TokenNameAND) {
1522 if (token == TokenNameVariable) {
1524 if (token == TokenNameEQUAL) {
1529 throwSyntaxError("Variable expected in parameter list.");
1531 if (token != TokenNameCOMMA) {
1538 if (!empty_allowed) {
1539 throwSyntaxError("Identifier expected in parameter list.");
1542 private void optional_class_type() {
1546 private void parameterDeclaration() {
1548 //variable-reference
1549 if (token == TokenNameAND) {
1554 throwSyntaxError("Variable expected after reference operator '&'.");
1557 //variable '=' constant
1558 if (token == TokenNameVariable) {
1560 if (token == TokenNameEQUAL) {
1566 // if (token == TokenNamethis) {
1567 // throwSyntaxError("Reserved word '$this' not allowed in parameter
1571 private void labeledStatementList() {
1572 if (token != TokenNamecase && token != TokenNamedefault) {
1573 throwSyntaxError("'case' or 'default' expected.");
1576 if (token == TokenNamecase) {
1578 expr(); //constant();
1579 if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
1581 if (token == TokenNamecase || token == TokenNamedefault) {
1582 // empty case statement ?
1587 // else if (token == TokenNameSEMICOLON) {
1589 // "':' expected after 'case' keyword (Found token: " +
1590 // scanner.toStringAction(token) + ")",
1591 // scanner.getCurrentTokenStartPosition(),
1592 // scanner.getCurrentTokenEndPosition(),
1595 // if (token == TokenNamecase) { // empty case statement ?
1601 throwSyntaxError("':' character after 'case' constant expected (Found token: " + scanner.toStringAction(token) + ")");
1603 } else { // TokenNamedefault
1605 if (token == TokenNameCOLON) {
1607 if (token == TokenNameRBRACE) {
1608 // empty default case
1613 throwSyntaxError("':' character after 'default' expected.");
1616 } while (token == TokenNamecase || token == TokenNamedefault);
1618 // public void labeledStatement() {
1619 // if (token == TokenNamecase) {
1622 // if (token == TokenNameDDOT) {
1626 // throwSyntaxError("':' character after 'case' constant expected.");
1629 // } else if (token == TokenNamedefault) {
1631 // if (token == TokenNameDDOT) {
1635 // throwSyntaxError("':' character after 'default' expected.");
1640 // public void expressionStatement() {
1642 // private void inclusionStatement() {
1644 // public void compoundStatement() {
1646 // public void selectionStatement() {
1649 // public void iterationStatement() {
1652 // public void jumpStatement() {
1655 // public void outputStatement() {
1658 // public void scopeStatement() {
1661 // public void flowStatement() {
1664 // public void definitionStatement() {
1666 private void ifStatement() {
1667 // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1668 if (token == TokenNameCOLON) {
1670 if (token != TokenNameendif) {
1673 case TokenNameelse :
1675 if (token == TokenNameCOLON) {
1677 if (token != TokenNameendif) {
1681 if (token == TokenNameif) { //'else if'
1683 elseifStatementList();
1685 throwSyntaxError("':' expected after 'else'.");
1689 case TokenNameelseif :
1691 elseifStatementList();
1695 if (token != TokenNameendif) {
1696 throwSyntaxError("'endif' expected.");
1699 if (token != TokenNameSEMICOLON) {
1700 throwSyntaxError("';' expected after if-statement.");
1704 // statement [else-statement]
1705 statement(TokenNameEOF);
1706 if (token == TokenNameelseif) {
1708 if (token == TokenNameLPAREN) {
1711 throwSyntaxError("'(' expected after 'elseif' keyword.");
1714 if (token == TokenNameRPAREN) {
1717 throwSyntaxError("')' expected after 'elseif' condition.");
1720 } else if (token == TokenNameelse) {
1722 statement(TokenNameEOF);
1726 private void elseifStatementList() {
1730 case TokenNameelse :
1732 if (token == TokenNameCOLON) {
1734 if (token != TokenNameendif) {
1739 if (token == TokenNameif) { //'else if'
1742 throwSyntaxError("':' expected after 'else'.");
1746 case TokenNameelseif :
1754 private void elseifStatement() {
1755 if (token == TokenNameLPAREN) {
1758 if (token != TokenNameRPAREN) {
1759 throwSyntaxError("')' expected in else-if-statement.");
1762 if (token != TokenNameCOLON) {
1763 throwSyntaxError("':' expected in else-if-statement.");
1766 if (token != TokenNameendif) {
1771 private void switchStatement() {
1772 if (token == TokenNameCOLON) {
1773 // ':' [labeled-statement-list] 'endswitch' ';'
1775 labeledStatementList();
1776 if (token != TokenNameendswitch) {
1777 throwSyntaxError("'endswitch' expected.");
1780 if (token != TokenNameSEMICOLON) {
1781 throwSyntaxError("';' expected after switch-statement.");
1785 // '{' [labeled-statement-list] '}'
1786 if (token != TokenNameLBRACE) {
1787 throwSyntaxError("'{' expected in switch statement.");
1790 if (token != TokenNameRBRACE) {
1791 labeledStatementList();
1793 if (token != TokenNameRBRACE) {
1794 throwSyntaxError("'}' expected in switch statement.");
1799 private void forStatement() {
1800 if (token == TokenNameCOLON) {
1803 if (token != TokenNameendfor) {
1804 throwSyntaxError("'endfor' expected.");
1807 if (token != TokenNameSEMICOLON) {
1808 throwSyntaxError("';' expected after for-statement.");
1812 statement(TokenNameEOF);
1815 private void whileStatement() {
1816 // ':' statement-list 'endwhile' ';'
1817 if (token == TokenNameCOLON) {
1820 if (token != TokenNameendwhile) {
1821 throwSyntaxError("'endwhile' expected.");
1824 if (token != TokenNameSEMICOLON) {
1825 throwSyntaxError("';' expected after while-statement.");
1829 statement(TokenNameEOF);
1832 private void foreachStatement() {
1833 if (token == TokenNameCOLON) {
1836 if (token != TokenNameendforeach) {
1837 throwSyntaxError("'endforeach' expected.");
1840 if (token != TokenNameSEMICOLON) {
1841 throwSyntaxError("';' expected after foreach-statement.");
1845 statement(TokenNameEOF);
1848 // private void exitStatus() {
1849 // if (token == TokenNameLPAREN) {
1852 // throwSyntaxError("'(' expected in 'exit-status'.");
1854 // if (token != TokenNameRPAREN) {
1857 // if (token == TokenNameRPAREN) {
1860 // throwSyntaxError("')' expected after 'exit-status'.");
1863 private void expressionList() {
1866 if (token == TokenNameCOMMA) {
1873 private void expr() {
1875 // | expr_without_variable
1876 // if (token!=TokenNameEOF) {
1877 if (Scanner.TRACE) {
1878 System.out.println("TRACE: expr()");
1880 expr_without_variable(true);
1883 private void expr_without_variable(boolean only_variable) {
1884 // internal_functions_in_yacc
1893 // | T_INC rw_variable
1894 // | T_DEC rw_variable
1895 // | T_INT_CAST expr
1896 // | T_DOUBLE_CAST expr
1897 // | T_STRING_CAST expr
1898 // | T_ARRAY_CAST expr
1899 // | T_OBJECT_CAST expr
1900 // | T_BOOL_CAST expr
1901 // | T_UNSET_CAST expr
1902 // | T_EXIT exit_expr
1904 // | T_ARRAY '(' array_pair_list ')'
1905 // | '`' encaps_list '`'
1906 // | T_LIST '(' assignment_list ')' '=' expr
1907 // | T_NEW class_name_reference ctor_arguments
1908 // | variable '=' expr
1909 // | variable '=' '&' variable
1910 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
1911 // | variable T_PLUS_EQUAL expr
1912 // | variable T_MINUS_EQUAL expr
1913 // | variable T_MUL_EQUAL expr
1914 // | variable T_DIV_EQUAL expr
1915 // | variable T_CONCAT_EQUAL expr
1916 // | variable T_MOD_EQUAL expr
1917 // | variable T_AND_EQUAL expr
1918 // | variable T_OR_EQUAL expr
1919 // | variable T_XOR_EQUAL expr
1920 // | variable T_SL_EQUAL expr
1921 // | variable T_SR_EQUAL expr
1922 // | rw_variable T_INC
1923 // | rw_variable T_DEC
1924 // | expr T_BOOLEAN_OR expr
1925 // | expr T_BOOLEAN_AND expr
1926 // | expr T_LOGICAL_OR expr
1927 // | expr T_LOGICAL_AND expr
1928 // | expr T_LOGICAL_XOR expr
1940 // | expr T_IS_IDENTICAL expr
1941 // | expr T_IS_NOT_IDENTICAL expr
1942 // | expr T_IS_EQUAL expr
1943 // | expr T_IS_NOT_EQUAL expr
1945 // | expr T_IS_SMALLER_OR_EQUAL expr
1947 // | expr T_IS_GREATER_OR_EQUAL expr
1948 // | expr T_INSTANCEOF class_name_reference
1949 // | expr '?' expr ':' expr
1950 if (Scanner.TRACE) {
1951 System.out.println("TRACE: expr_without_variable() PART 1");
1954 case TokenNameisset :
1955 case TokenNameempty :
1956 case TokenNameeval :
1957 case TokenNameinclude :
1958 case TokenNameinclude_once :
1959 case TokenNamerequire :
1960 case TokenNamerequire_once :
1961 internal_functions_in_yacc();
1964 case TokenNameLPAREN :
1967 if (token == TokenNameRPAREN) {
1970 throwSyntaxError("')' expected in expression.");
1980 // | T_INT_CAST expr
1981 // | T_DOUBLE_CAST expr
1982 // | T_STRING_CAST expr
1983 // | T_ARRAY_CAST expr
1984 // | T_OBJECT_CAST expr
1985 // | T_BOOL_CAST expr
1986 // | T_UNSET_CAST expr
1987 case TokenNameclone :
1988 case TokenNameprint :
1990 case TokenNamePLUS :
1991 case TokenNameMINUS :
1993 case TokenNameTWIDDLE :
1994 case TokenNameintCAST :
1995 case TokenNamedoubleCAST :
1996 case TokenNamestringCAST :
1997 case TokenNamearrayCAST :
1998 case TokenNameobjectCAST :
1999 case TokenNameboolCAST :
2000 case TokenNameunsetCAST :
2004 case TokenNameexit :
2010 //| T_STRING_VARNAME
2012 //| T_START_HEREDOC encaps_list T_END_HEREDOC
2013 // | '`' encaps_list '`'
2015 // | '`' encaps_list '`'
2016 case TokenNameEncapsedString0 :
2017 scanner.encapsedStringStack.push(new Character('`'));
2020 if (token == TokenNameEncapsedString0) {
2023 if (token != TokenNameEncapsedString0) {
2024 throwSyntaxError("\'`\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2028 scanner.encapsedStringStack.pop();
2032 // | '\'' encaps_list '\''
2033 case TokenNameEncapsedString1 :
2034 scanner.encapsedStringStack.push(new Character('\''));
2037 if (token == TokenNameEncapsedString1) {
2040 if (token != TokenNameEncapsedString1) {
2041 throwSyntaxError("\'\'\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2045 scanner.encapsedStringStack.pop();
2049 //| '"' encaps_list '"'
2050 case TokenNameEncapsedString2 :
2051 scanner.encapsedStringStack.push(new Character('"'));
2054 if (token == TokenNameEncapsedString2) {
2057 if (token != TokenNameEncapsedString2) {
2058 throwSyntaxError("'\"' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
2062 scanner.encapsedStringStack.pop();
2066 case TokenNameIntegerLiteral :
2067 case TokenNameDoubleLiteral :
2068 case TokenNameStringDoubleQuote :
2069 case TokenNameStringSingleQuote :
2070 case TokenNameStringInterpolated :
2071 case TokenNameFILE :
2072 case TokenNameLINE :
2073 case TokenNameCLASS_C :
2074 case TokenNameMETHOD_C :
2075 case TokenNameFUNC_C :
2078 case TokenNameHEREDOC :
2081 case TokenNamearray :
2082 // T_ARRAY '(' array_pair_list ')'
2084 if (token == TokenNameLPAREN) {
2086 if (token == TokenNameRPAREN) {
2091 if (token != TokenNameRPAREN) {
2092 throwSyntaxError("')' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2096 throwSyntaxError("'(' expected after keyword 'array'" + "(Found token: " + scanner.toStringAction(token) + ")");
2099 case TokenNamelist :
2100 // | T_LIST '(' assignment_list ')' '=' expr
2102 if (token == TokenNameLPAREN) {
2105 if (token != TokenNameRPAREN) {
2106 throwSyntaxError("')' expected after 'list' keyword.");
2109 if (token != TokenNameEQUAL) {
2110 throwSyntaxError("'=' expected after 'list' keyword.");
2115 throwSyntaxError("'(' expected after 'list' keyword.");
2119 // | T_NEW class_name_reference ctor_arguments
2121 class_name_reference();
2124 // | T_INC rw_variable
2125 // | T_DEC rw_variable
2126 case TokenNamePLUS_PLUS :
2127 case TokenNameMINUS_MINUS :
2131 // | variable '=' expr
2132 // | variable '=' '&' variable
2133 // | variable '=' '&' T_NEW class_name_reference ctor_arguments
2134 // | variable T_PLUS_EQUAL expr
2135 // | variable T_MINUS_EQUAL expr
2136 // | variable T_MUL_EQUAL expr
2137 // | variable T_DIV_EQUAL expr
2138 // | variable T_CONCAT_EQUAL expr
2139 // | variable T_MOD_EQUAL expr
2140 // | variable T_AND_EQUAL expr
2141 // | variable T_OR_EQUAL expr
2142 // | variable T_XOR_EQUAL expr
2143 // | variable T_SL_EQUAL expr
2144 // | variable T_SR_EQUAL expr
2145 // | rw_variable T_INC
2146 // | rw_variable T_DEC
2147 case TokenNameIdentifier :
2148 case TokenNameVariable :
2149 case TokenNameDOLLAR :
2152 case TokenNameEQUAL :
2154 if (token == TokenNameAND) {
2156 if (token == TokenNamenew) {
2157 // | variable '=' '&' T_NEW class_name_reference
2160 class_name_reference();
2169 case TokenNamePLUS_EQUAL :
2170 case TokenNameMINUS_EQUAL :
2171 case TokenNameMULTIPLY_EQUAL :
2172 case TokenNameDIVIDE_EQUAL :
2173 case TokenNameDOT_EQUAL :
2174 case TokenNameREMAINDER_EQUAL :
2175 case TokenNameAND_EQUAL :
2176 case TokenNameOR_EQUAL :
2177 case TokenNameXOR_EQUAL :
2178 case TokenNameRIGHT_SHIFT_EQUAL :
2179 case TokenNameLEFT_SHIFT_EQUAL :
2183 case TokenNamePLUS_PLUS :
2184 case TokenNameMINUS_MINUS :
2188 if (!only_variable) {
2189 throwSyntaxError("Variable expression not allowed (found token '" + scanner.toStringAction(token) + "').");
2194 if (token != TokenNameINLINE_HTML) {
2195 if (token > TokenNameKEYWORD) {
2199 throwSyntaxError("Error in expression (found token '" + scanner.toStringAction(token) + "').");
2204 if (Scanner.TRACE) {
2205 System.out.println("TRACE: expr_without_variable() PART 2");
2207 // | expr T_BOOLEAN_OR expr
2208 // | expr T_BOOLEAN_AND expr
2209 // | expr T_LOGICAL_OR expr
2210 // | expr T_LOGICAL_AND expr
2211 // | expr T_LOGICAL_XOR expr
2223 // | expr T_IS_IDENTICAL expr
2224 // | expr T_IS_NOT_IDENTICAL expr
2225 // | expr T_IS_EQUAL expr
2226 // | expr T_IS_NOT_EQUAL expr
2228 // | expr T_IS_SMALLER_OR_EQUAL expr
2230 // | expr T_IS_GREATER_OR_EQUAL expr
2233 case TokenNameOR_OR :
2234 case TokenNameAND_AND :
2242 case TokenNamePLUS :
2243 case TokenNameMINUS :
2244 case TokenNameMULTIPLY :
2245 case TokenNameDIVIDE :
2246 case TokenNameREMAINDER :
2247 case TokenNameLEFT_SHIFT :
2248 case TokenNameRIGHT_SHIFT :
2249 case TokenNameEQUAL_EQUAL_EQUAL :
2250 case TokenNameNOT_EQUAL_EQUAL :
2251 case TokenNameEQUAL_EQUAL :
2252 case TokenNameNOT_EQUAL :
2253 case TokenNameLESS :
2254 case TokenNameLESS_EQUAL :
2255 case TokenNameGREATER :
2256 case TokenNameGREATER_EQUAL :
2260 // | expr T_INSTANCEOF class_name_reference
2261 // | expr '?' expr ':' expr
2262 case TokenNameinstanceof :
2264 class_name_reference();
2266 case TokenNameQUESTION :
2269 if (token == TokenNameCOLON) {
2279 private void class_name_reference() {
2280 // class_name_reference:
2282 //| dynamic_class_name_reference
2283 if (Scanner.TRACE) {
2284 System.out.println("TRACE: class_name_reference()");
2286 if (token == TokenNameIdentifier) {
2289 dynamic_class_name_reference();
2292 private void dynamic_class_name_reference() {
2293 //dynamic_class_name_reference:
2294 // base_variable T_OBJECT_OPERATOR object_property
2295 // dynamic_class_name_variable_properties
2297 if (Scanner.TRACE) {
2298 System.out.println("TRACE: dynamic_class_name_reference()");
2301 if (token == TokenNameMINUS_GREATER) {
2304 dynamic_class_name_variable_properties();
2307 private void dynamic_class_name_variable_properties() {
2308 // dynamic_class_name_variable_properties:
2309 // dynamic_class_name_variable_properties
2310 // dynamic_class_name_variable_property
2312 if (Scanner.TRACE) {
2313 System.out.println("TRACE: dynamic_class_name_variable_properties()");
2315 while (token == TokenNameMINUS_GREATER) {
2316 dynamic_class_name_variable_property();
2319 private void dynamic_class_name_variable_property() {
2320 // dynamic_class_name_variable_property:
2321 // T_OBJECT_OPERATOR object_property
2322 if (Scanner.TRACE) {
2323 System.out.println("TRACE: dynamic_class_name_variable_property()");
2325 if (token == TokenNameMINUS_GREATER) {
2330 private void ctor_arguments() {
2333 //| '(' function_call_parameter_list ')'
2334 if (token == TokenNameLPAREN) {
2336 if (token == TokenNameRPAREN) {
2340 non_empty_function_call_parameter_list();
2341 if (token != TokenNameRPAREN) {
2342 throwSyntaxError("')' expected in ctor_arguments.");
2347 private void assignment_list() {
2349 // assignment_list ',' assignment_list_element
2350 //| assignment_list_element
2352 assignment_list_element();
2353 if (token != TokenNameCOMMA) {
2359 private void assignment_list_element() {
2360 //assignment_list_element:
2362 //| T_LIST '(' assignment_list ')'
2364 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2367 if (token == TokenNamelist) {
2369 if (token == TokenNameLPAREN) {
2372 if (token != TokenNameRPAREN) {
2373 throwSyntaxError("')' expected after 'list' keyword.");
2377 throwSyntaxError("'(' expected after 'list' keyword.");
2382 private void array_pair_list() {
2385 //| non_empty_array_pair_list possible_comma
2386 non_empty_array_pair_list();
2387 if (token == TokenNameCOMMA) {
2391 private void non_empty_array_pair_list() {
2392 //non_empty_array_pair_list:
2393 // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
2394 //| non_empty_array_pair_list ',' expr
2395 //| expr T_DOUBLE_ARROW expr
2397 //| non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
2398 //| non_empty_array_pair_list ',' '&' w_variable
2399 //| expr T_DOUBLE_ARROW '&' w_variable
2402 if (token == TokenNameAND) {
2407 if (token == TokenNameAND) {
2410 } else if (token == TokenNameEQUAL_GREATER) {
2412 if (token == TokenNameAND) {
2420 if (token != TokenNameCOMMA) {
2424 if (token == TokenNameRPAREN) {
2429 // private void variableList() {
2432 // if (token == TokenNameCOMMA) {
2439 private void variable_without_objects() {
2440 // variable_without_objects:
2441 // reference_variable
2442 // | simple_indirect_reference reference_variable
2443 if (Scanner.TRACE) {
2444 System.out.println("TRACE: variable_without_objects()");
2446 while (token == TokenNameDOLLAR) {
2449 reference_variable();
2451 private void function_call() {
2453 // T_STRING '(' function_call_parameter_list ')'
2454 //| class_constant '(' function_call_parameter_list ')'
2455 //| static_member '(' function_call_parameter_list ')'
2456 //| variable_without_objects '(' function_call_parameter_list ')'
2457 if (Scanner.TRACE) {
2458 System.out.println("TRACE: function_call()");
2460 if (token == TokenNameIdentifier) {
2463 case TokenNamePAAMAYIM_NEKUDOTAYIM :
2466 if (token == TokenNameIdentifier) {
2471 variable_without_objects();
2476 variable_without_objects();
2478 if (token != TokenNameLPAREN) {
2479 // TODO is this ok ?
2481 // throwSyntaxError("'(' expected in function call.");
2484 if (token == TokenNameRPAREN) {
2488 non_empty_function_call_parameter_list();
2489 if (token != TokenNameRPAREN) {
2490 throwSyntaxError("')' expected in function call.");
2494 // private void function_call_parameter_list() {
2495 // function_call_parameter_list:
2496 // non_empty_function_call_parameter_list { $$ = $1; }
2499 private void non_empty_function_call_parameter_list() {
2500 //non_empty_function_call_parameter_list:
2501 // expr_without_variable
2504 // | non_empty_function_call_parameter_list ',' expr_without_variable
2505 // | non_empty_function_call_parameter_list ',' variable
2506 // | non_empty_function_call_parameter_list ',' '&' w_variable
2507 if (Scanner.TRACE) {
2508 System.out.println("TRACE: non_empty_function_call_parameter_list()");
2511 if (token == TokenNameAND) {
2515 // if (token == TokenNameIdentifier || token ==
2516 // TokenNameVariable
2517 // || token == TokenNameDOLLAR) {
2520 expr_without_variable(true);
2523 if (token != TokenNameCOMMA) {
2529 private void fully_qualified_class_name() {
2530 if (token == TokenNameIdentifier) {
2533 throwSyntaxError("Class name expected.");
2536 private void static_member() {
2538 // fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
2539 // variable_without_objects
2540 if (Scanner.TRACE) {
2541 System.out.println("TRACE: static_member()");
2543 fully_qualified_class_name();
2544 if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
2545 throwSyntaxError("'::' expected after class name (static_member).");
2548 variable_without_objects();
2550 private void base_variable_with_function_calls() {
2551 // base_variable_with_function_calls:
2554 boolean functionCall = false;
2555 if (Scanner.TRACE) {
2556 System.out.println("TRACE: base_variable_with_function_calls()");
2558 // if (token == TokenNameIdentifier) {
2559 // functionCall = true;
2560 // } else if (token == TokenNameVariable) {
2561 // int tempToken = token;
2562 // int tempPosition = scanner.currentPosition;
2564 // if (token == TokenNameLPAREN) {
2565 // functionCall = true;
2567 // token = tempToken;
2568 // scanner.currentPosition = tempPosition;
2569 // scanner.phpMode = true;
2571 // if (functionCall) {
2577 private void base_variable() {
2579 // reference_variable
2580 // | simple_indirect_reference reference_variable
2582 if (Scanner.TRACE) {
2583 System.out.println("TRACE: base_variable()");
2585 if (token == TokenNameIdentifier) {
2588 while (token == TokenNameDOLLAR) {
2591 reference_variable();
2594 // private void simple_indirect_reference() {
2595 // // simple_indirect_reference:
2597 // //| simple_indirect_reference '$'
2599 private void reference_variable() {
2600 // reference_variable:
2601 // reference_variable '[' dim_offset ']'
2602 // | reference_variable '{' expr '}'
2603 // | compound_variable
2604 if (Scanner.TRACE) {
2605 System.out.println("TRACE: reference_variable()");
2607 compound_variable();
2609 if (token == TokenNameLBRACE) {
2612 if (token != TokenNameRBRACE) {
2613 throwSyntaxError("'}' expected in reference variable.");
2616 } else if (token == TokenNameLBRACKET) {
2618 if (token != TokenNameRBRACKET) {
2621 if (token != TokenNameRBRACKET) {
2622 throwSyntaxError("']' expected in reference variable.");
2631 private void compound_variable() {
2632 // compound_variable:
2634 // | '$' '{' expr '}'
2635 if (Scanner.TRACE) {
2636 System.out.println("TRACE: compound_variable()");
2638 if (token == TokenNameVariable) {
2641 // because of simple_indirect_reference
2642 while (token == TokenNameDOLLAR) {
2645 if (token != TokenNameLBRACE) {
2646 throwSyntaxError("'{' expected after compound variable token '$'.");
2650 if (token != TokenNameRBRACE) {
2651 throwSyntaxError("'}' expected after compound variable token '$'.");
2656 // private void dim_offset() {
2662 private void object_property() {
2665 //| variable_without_objects
2666 if (Scanner.TRACE) {
2667 System.out.println("TRACE: object_property()");
2669 if (token == TokenNameVariable || token == TokenNameDOLLAR) {
2670 variable_without_objects();
2675 private void object_dim_list() {
2677 // object_dim_list '[' dim_offset ']'
2678 //| object_dim_list '{' expr '}'
2680 if (Scanner.TRACE) {
2681 System.out.println("TRACE: object_dim_list()");
2685 if (token == TokenNameLBRACE) {
2688 if (token != TokenNameRBRACE) {
2689 throwSyntaxError("'}' expected in object_dim_list.");
2692 } else if (token == TokenNameLBRACKET) {
2694 if (token == TokenNameRBRACKET) {
2699 if (token != TokenNameRBRACKET) {
2700 throwSyntaxError("']' expected in object_dim_list.");
2708 private void variable_name() {
2712 if (Scanner.TRACE) {
2713 System.out.println("TRACE: variable_name()");
2715 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
2716 if (token > TokenNameKEYWORD) {
2717 // TODO show a warning "Keyword used as variable" ?
2721 if (token != TokenNameLBRACE) {
2722 throwSyntaxError("'{' expected in variable name.");
2726 if (token != TokenNameRBRACE) {
2727 throwSyntaxError("'}' expected in variable name.");
2732 private void r_variable() {
2735 private void w_variable() {
2738 private void rw_variable() {
2741 private void variable() {
2743 // base_variable_with_function_calls T_OBJECT_OPERATOR
2744 // object_property method_or_not variable_properties
2745 // | base_variable_with_function_calls
2746 base_variable_with_function_calls();
2747 if (token == TokenNameMINUS_GREATER) {
2751 variable_properties();
2753 // if (token == TokenNameDOLLAR_LBRACE) {
2757 // if (token != TokenNameRBRACE) {
2758 // throwSyntaxError("'}' expected after indirect variable token '${'.");
2762 // if (token == TokenNameVariable) {
2764 // if (token == TokenNameLBRACKET) {
2767 // if (token != TokenNameRBRACKET) {
2768 // throwSyntaxError("']' expected in variable-list.");
2771 // } else if (token == TokenNameEQUAL) {
2776 // throwSyntaxError("$-variable expected in variable-list.");
2780 private void variable_properties() {
2781 // variable_properties:
2782 // variable_properties variable_property
2784 while (token == TokenNameMINUS_GREATER) {
2785 variable_property();
2788 private void variable_property() {
2789 // variable_property:
2790 // T_OBJECT_OPERATOR object_property method_or_not
2791 if (Scanner.TRACE) {
2792 System.out.println("TRACE: variable_property()");
2794 if (token == TokenNameMINUS_GREATER) {
2799 throwSyntaxError("'->' expected in variable_property.");
2802 private void method_or_not() {
2804 // '(' function_call_parameter_list ')'
2806 if (Scanner.TRACE) {
2807 System.out.println("TRACE: method_or_not()");
2809 if (token == TokenNameLPAREN) {
2811 if (token == TokenNameRPAREN) {
2815 non_empty_function_call_parameter_list();
2816 if (token != TokenNameRPAREN) {
2817 throwSyntaxError("')' expected in method_or_not.");
2822 private void exit_expr() {
2826 if (token != TokenNameLPAREN) {
2830 if (token == TokenNameRPAREN) {
2835 if (token != TokenNameRPAREN) {
2836 throwSyntaxError("')' expected after keyword 'exit'");
2840 private void encaps_list() {
2841 // encaps_list encaps_var
2842 // | encaps_list T_STRING
2843 // | encaps_list T_NUM_STRING
2844 // | encaps_list T_ENCAPSED_AND_WHITESPACE
2845 // | encaps_list T_CHARACTER
2846 // | encaps_list T_BAD_CHARACTER
2847 // | encaps_list '['
2848 // | encaps_list ']'
2849 // | encaps_list '{'
2850 // | encaps_list '}'
2851 // | encaps_list T_OBJECT_OPERATOR
2855 case TokenNameSTRING :
2858 case TokenNameLBRACE :
2859 // scanner.encapsedStringStack.pop();
2862 case TokenNameRBRACE :
2863 // scanner.encapsedStringStack.pop();
2866 case TokenNameLBRACKET :
2867 // scanner.encapsedStringStack.pop();
2870 case TokenNameRBRACKET :
2871 // scanner.encapsedStringStack.pop();
2874 case TokenNameMINUS_GREATER :
2875 // scanner.encapsedStringStack.pop();
2878 case TokenNameVariable :
2879 case TokenNameDOLLAR_LBRACE :
2880 case TokenNameCURLY_OPEN :
2883 // case TokenNameDOLLAR :
2885 // if (token == TokenNameLBRACE) {
2886 // token = TokenNameDOLLAR_LBRACE;
2891 char encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
2892 if (encapsedChar == '$') {
2893 scanner.encapsedStringStack.pop();
2894 encapsedChar = ((Character) scanner.encapsedStringStack.peek()).charValue();
2895 switch (encapsedChar) {
2897 if (token == TokenNameEncapsedString0) {
2900 token = TokenNameSTRING;
2903 if (token == TokenNameEncapsedString1) {
2906 token = TokenNameSTRING;
2909 if (token == TokenNameEncapsedString2) {
2912 token = TokenNameSTRING;
2920 private void encaps_var() {
2922 // | T_VARIABLE '[' encaps_var_offset ']'
2923 // | T_VARIABLE T_OBJECT_OPERATOR T_STRING
2924 // | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
2925 // | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
2926 // | T_CURLY_OPEN variable '}'
2928 case TokenNameVariable :
2930 if (token == TokenNameLBRACKET) {
2932 // if (token == TokenNameRBRACKET) {
2935 expr(); //encaps_var_offset();
2936 if (token != TokenNameRBRACKET) {
2937 throwSyntaxError("']' expected after variable.");
2939 // scanner.encapsedStringStack.pop();
2942 } else if (token == TokenNameMINUS_GREATER) {
2944 if (token != TokenNameIdentifier) {
2945 throwSyntaxError("Identifier expected after '->'.");
2947 // scanner.encapsedStringStack.pop();
2951 // // scanner.encapsedStringStack.pop();
2952 // int tempToken = TokenNameSTRING;
2953 // if (!scanner.encapsedStringStack.isEmpty()
2954 // && (token == TokenNameEncapsedString0
2955 // || token == TokenNameEncapsedString1
2956 // || token == TokenNameEncapsedString2 || token ==
2957 // TokenNameERROR)) {
2958 // char encapsedChar = ((Character)
2959 // scanner.encapsedStringStack.peek())
2962 // case TokenNameEncapsedString0 :
2963 // if (encapsedChar == '`') {
2964 // tempToken = TokenNameEncapsedString0;
2967 // case TokenNameEncapsedString1 :
2968 // if (encapsedChar == '\'') {
2969 // tempToken = TokenNameEncapsedString1;
2972 // case TokenNameEncapsedString2 :
2973 // if (encapsedChar == '"') {
2974 // tempToken = TokenNameEncapsedString2;
2977 // case TokenNameERROR :
2978 // if (scanner.source[scanner.currentPosition - 1] == '\\') {
2979 // scanner.currentPosition--;
2985 // token = tempToken;
2988 case TokenNameDOLLAR_LBRACE :
2990 if (token == TokenNameIdentifier) {
2992 if (token == TokenNameLBRACKET) {
2994 // if (token == TokenNameRBRACKET) {
2998 if (token != TokenNameRBRACKET) {
2999 throwSyntaxError("']' expected after '${'.");
3004 if (token != TokenNameRBRACE) {
3005 throwSyntaxError("'}' expected after '${'.");
3007 // scanner.encapsedStringStack.pop();
3011 if (token != TokenNameRBRACE) {
3012 throwSyntaxError("'}' expected.");
3014 // scanner.encapsedStringStack.pop();
3018 case TokenNameCURLY_OPEN :
3020 if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
3022 if (token == TokenNameLBRACKET) {
3024 // if (token == TokenNameRBRACKET) {
3028 if (token != TokenNameRBRACKET) {
3029 throwSyntaxError("']' expected after '{$'.");
3033 } else if (token == TokenNameMINUS_GREATER) {
3035 if (token != TokenNameIdentifier) {
3036 throwSyntaxError("String token expected.");
3040 // if (token != TokenNameRBRACE) {
3041 // throwSyntaxError("'}' expected after '{$'.");
3043 // // scanner.encapsedStringStack.pop();
3047 if (token != TokenNameRBRACE) {
3048 throwSyntaxError("'}' expected.");
3050 // scanner.encapsedStringStack.pop();
3056 private void encaps_var_offset() {
3061 case TokenNameSTRING :
3064 case TokenNameIntegerLiteral :
3067 case TokenNameVariable :
3070 case TokenNameIdentifier :
3074 throwSyntaxError("Variable or String token expected.");
3078 private void internal_functions_in_yacc() {
3080 ImportReference impt = null;
3082 case TokenNameisset :
3083 // T_ISSET '(' isset_variables ')'
3085 if (token != TokenNameLPAREN) {
3086 throwSyntaxError("'(' expected after keyword 'isset'");
3090 if (token != TokenNameRPAREN) {
3091 throwSyntaxError("')' expected after keyword 'isset'");
3095 case TokenNameempty :
3096 // T_EMPTY '(' variable ')'
3098 if (token != TokenNameLPAREN) {
3099 throwSyntaxError("'(' expected after keyword 'empty'");
3103 if (token != TokenNameRPAREN) {
3104 throwSyntaxError("')' expected after keyword 'empty'");
3108 case TokenNameinclude :
3110 start = scanner.getCurrentTokenStartPosition();
3114 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3115 impt.declarationSourceEnd = impt.sourceEnd;
3116 impt.declarationEnd = impt.declarationSourceEnd;
3117 //endPosition is just before the ;
3118 impt.declarationSourceStart = start;
3119 includesList.add(impt);
3121 case TokenNameinclude_once :
3122 // T_INCLUDE_ONCE expr
3123 start = scanner.getCurrentTokenStartPosition();
3126 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3127 impt.declarationSourceEnd = impt.sourceEnd;
3128 impt.declarationEnd = impt.declarationSourceEnd;
3129 //endPosition is just before the ;
3130 impt.declarationSourceStart = start;
3131 includesList.add(impt);
3133 case TokenNameeval :
3134 // T_EVAL '(' expr ')'
3136 if (token != TokenNameLPAREN) {
3137 throwSyntaxError("'(' expected after keyword 'eval'");
3141 if (token != TokenNameRPAREN) {
3142 throwSyntaxError("')' expected after keyword 'eval'");
3146 case TokenNamerequire :
3148 start = scanner.getCurrentTokenStartPosition();
3151 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3152 impt.declarationSourceEnd = impt.sourceEnd;
3153 impt.declarationEnd = impt.declarationSourceEnd;
3154 //endPosition is just before the ;
3155 impt.declarationSourceStart = start;
3156 includesList.add(impt);
3158 case TokenNamerequire_once :
3159 // T_REQUIRE_ONCE expr
3160 start = scanner.getCurrentTokenStartPosition();
3163 impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
3164 impt.declarationSourceEnd = impt.sourceEnd;
3165 impt.declarationEnd = impt.declarationSourceEnd;
3166 //endPosition is just before the ;
3167 impt.declarationSourceStart = start;
3168 includesList.add(impt);
3172 private void isset_variables() {
3174 // | isset_variables ','
3175 if (token == TokenNameRPAREN) {
3176 throwSyntaxError("Variable expected after keyword 'isset'");
3180 if (token == TokenNameCOMMA) {
3187 private boolean common_scalar() {
3191 // | T_CONSTANT_ENCAPSED_STRING
3198 case TokenNameIntegerLiteral :
3201 case TokenNameDoubleLiteral :
3204 case TokenNameStringDoubleQuote :
3207 case TokenNameStringSingleQuote :
3210 case TokenNameStringInterpolated :
3213 case TokenNameFILE :
3216 case TokenNameLINE :
3219 case TokenNameCLASS_C :
3222 case TokenNameMETHOD_C :
3225 case TokenNameFUNC_C :
3231 private void scalar() {
3234 //| T_STRING_VARNAME
3237 //| '"' encaps_list '"'
3238 //| '\'' encaps_list '\''
3239 //| T_START_HEREDOC encaps_list T_END_HEREDOC
3240 throwSyntaxError("Not yet implemented (scalar).");
3242 private void static_scalar() {
3243 // static_scalar: /* compile-time evaluated scalars */
3246 // | '+' static_scalar
3247 // | '-' static_scalar
3248 // | T_ARRAY '(' static_array_pair_list ')'
3249 // | static_class_constant
3250 if (common_scalar()) {
3254 case TokenNameIdentifier :
3256 // static_class_constant:
3257 // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
3258 if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
3260 if (token == TokenNameIdentifier) {
3263 throwSyntaxError("Identifier expected after '::' operator.");
3267 case TokenNameEncapsedString0 :
3269 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3270 while (scanner.currentCharacter != '`') {
3271 if (scanner.currentCharacter == '\\') {
3272 scanner.currentPosition++;
3274 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3277 } catch (IndexOutOfBoundsException e) {
3278 throwSyntaxError("'`' expected at end of static string.");
3281 case TokenNameEncapsedString1 :
3283 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3284 while (scanner.currentCharacter != '\'') {
3285 if (scanner.currentCharacter == '\\') {
3286 scanner.currentPosition++;
3288 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3291 } catch (IndexOutOfBoundsException e) {
3292 throwSyntaxError("'\'' expected at end of static string.");
3295 case TokenNameEncapsedString2 :
3297 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3298 while (scanner.currentCharacter != '"') {
3299 if (scanner.currentCharacter == '\\') {
3300 scanner.currentPosition++;
3302 scanner.currentCharacter = scanner.source[scanner.currentPosition++];
3305 } catch (IndexOutOfBoundsException e) {
3306 throwSyntaxError("'\"' expected at end of static string.");
3309 case TokenNamePLUS :
3313 case TokenNameMINUS :
3317 case TokenNamearray :
3319 if (token != TokenNameLPAREN) {
3320 throwSyntaxError("'(' expected after keyword 'array'");
3323 if (token == TokenNameRPAREN) {
3327 non_empty_static_array_pair_list();
3328 if (token != TokenNameRPAREN) {
3329 throwSyntaxError("')' expected after keyword 'array'");
3333 // case TokenNamenull :
3336 // case TokenNamefalse :
3339 // case TokenNametrue :
3343 throwSyntaxError("Static scalar/constant expected.");
3346 private void non_empty_static_array_pair_list() {
3347 // non_empty_static_array_pair_list:
3348 // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
3350 //| non_empty_static_array_pair_list ',' static_scalar
3351 //| static_scalar T_DOUBLE_ARROW static_scalar
3355 if (token == TokenNameEQUAL_GREATER) {
3359 if (token != TokenNameCOMMA) {
3363 if (token == TokenNameRPAREN) {
3368 public void reportSyntaxError() { //int act, int currentKind, int
3370 /* remember current scanner position */
3371 int startPos = scanner.startPosition;
3372 int currentPos = scanner.currentPosition;
3373 // String[] expectings;
3374 // String tokenName = name[symbol_index[currentKind]];
3375 //fetch all "accurate" possible terminals that could recover the error
3376 // int start, end = start = asi(stack[stateStackTop]);
3377 // while (asr[end] != 0)
3379 // int length = end - start;
3380 // expectings = new String[length];
3381 // if (length != 0) {
3382 // char[] indexes = new char[length];
3383 // System.arraycopy(asr, start, indexes, 0, length);
3384 // for (int i = 0; i < length; i++) {
3385 // expectings[i] = name[symbol_index[indexes[i]]];
3388 //if the pb is an EOF, try to tell the user that they are some
3389 // if (tokenName.equals(UNEXPECTED_EOF)) {
3390 // if (!this.checkAndReportBracketAnomalies(problemReporter())) {
3391 // char[] tokenSource;
3393 // tokenSource = this.scanner.getCurrentTokenSource();
3394 // } catch (Exception e) {
3395 // tokenSource = new char[] {};
3397 // problemReporter().parseError(
3398 // this.scanner.startPosition,
3399 // this.scanner.currentPosition - 1,
3404 // } else { //the next test is HEAVILY grammar DEPENDENT.
3405 // if ((length == 14)
3406 // && (expectings[0] == "=") //$NON-NLS-1$
3407 // && (expectings[1] == "*=") //$NON-NLS-1$
3408 // && (expressionPtr > -1)) {
3409 // switch(currentKind) {
3410 // case TokenNameSEMICOLON:
3411 // case TokenNamePLUS:
3412 // case TokenNameMINUS:
3413 // case TokenNameDIVIDE:
3414 // case TokenNameREMAINDER:
3415 // case TokenNameMULTIPLY:
3416 // case TokenNameLEFT_SHIFT:
3417 // case TokenNameRIGHT_SHIFT:
3418 //// case TokenNameUNSIGNED_RIGHT_SHIFT:
3419 // case TokenNameLESS:
3420 // case TokenNameGREATER:
3421 // case TokenNameLESS_EQUAL:
3422 // case TokenNameGREATER_EQUAL:
3423 // case TokenNameEQUAL_EQUAL:
3424 // case TokenNameNOT_EQUAL:
3425 // case TokenNameXOR:
3426 // case TokenNameAND:
3427 // case TokenNameOR:
3428 // case TokenNameOR_OR:
3429 // case TokenNameAND_AND:
3430 // // the ; is not the expected token ==> it ends a statement when an
3431 // expression is not ended
3432 // problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
3434 // case TokenNameRBRACE :
3435 // problemReporter().missingSemiColon(expressionStack[expressionPtr]);
3438 // char[] tokenSource;
3440 // tokenSource = this.scanner.getCurrentTokenSource();
3441 // } catch (Exception e) {
3442 // tokenSource = new char[] {};
3444 // problemReporter().parseError(
3445 // this.scanner.startPosition,
3446 // this.scanner.currentPosition - 1,
3450 // this.checkAndReportBracketAnomalies(problemReporter());
3455 tokenSource = this.scanner.getCurrentTokenSource();
3456 } catch (Exception e) {
3457 tokenSource = new char[]{};
3459 // problemReporter().parseError(
3460 // this.scanner.startPosition,
3461 // this.scanner.currentPosition - 1,
3465 this.checkAndReportBracketAnomalies(problemReporter());
3468 /* reset scanner where it was */
3469 scanner.startPosition = startPos;
3470 scanner.currentPosition = currentPos;
3472 public static final int RoundBracket = 0;
3473 public static final int SquareBracket = 1;
3474 public static final int CurlyBracket = 2;
3475 public static final int BracketKinds = 3;
3476 protected int[] nestedMethod; //the ptr is nestedType
3477 protected int nestedType, dimensions;
3479 final static int AstStackIncrement = 100;
3480 protected int astPtr;
3481 protected AstNode[] astStack = new AstNode[AstStackIncrement];
3482 protected int astLengthPtr;
3483 protected int[] astLengthStack;
3484 AstNode[] noAstNodes = new AstNode[AstStackIncrement];
3485 public CompilationUnitDeclaration compilationUnit; /*
3486 * the result from parse()
3488 protected ReferenceContext referenceContext;
3489 protected ProblemReporter problemReporter;
3490 protected CompilerOptions options;
3491 private ArrayList includesList;
3492 // protected CompilationResult compilationResult;
3494 * Returns this parser's problem reporter initialized with its reference
3495 * context. Also it is assumed that a problem is going to be reported, so
3496 * initializes the compilation result's line positions.
3498 public ProblemReporter problemReporter() {
3499 if (scanner.recordLineSeparator) {
3500 compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
3502 problemReporter.referenceContext = referenceContext;
3503 return problemReporter;
3506 * Reconsider the entire source looking for inconsistencies in {} () []
3508 public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
3509 scanner.wasAcr = false;
3510 boolean anomaliesDetected = false;
3512 char[] source = scanner.source;
3513 int[] leftCount = {0, 0, 0};
3514 int[] rightCount = {0, 0, 0};
3515 int[] depths = {0, 0, 0};
3516 int[][] leftPositions = new int[][]{new int[10], new int[10], new int[10]};
3517 int[][] leftDepths = new int[][]{new int[10], new int[10], new int[10]};
3518 int[][] rightPositions = new int[][]{new int[10], new int[10], new int[10]};
3519 int[][] rightDepths = new int[][]{new int[10], new int[10], new int[10]};
3520 scanner.currentPosition = scanner.initialPosition; //starting
3522 // (first-zero-based
3524 while (scanner.currentPosition < scanner.eofPosition) { //loop for
3529 // ---------Consume white space and handles
3530 // startPosition---------
3531 boolean isWhiteSpace;
3533 scanner.startPosition = scanner.currentPosition;
3534 // if (((scanner.currentCharacter =
3535 // source[scanner.currentPosition++]) == '\\') &&
3536 // (source[scanner.currentPosition] == 'u')) {
3537 // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
3539 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3540 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3541 // only record line positions we have not
3543 scanner.pushLineSeparator();
3546 isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
3548 } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
3549 // -------consume token until } is found---------
3550 switch (scanner.currentCharacter) {
3552 int index = leftCount[CurlyBracket]++;
3553 if (index == leftPositions[CurlyBracket].length) {
3554 System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
3555 System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
3557 leftPositions[CurlyBracket][index] = scanner.startPosition;
3558 leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
3562 int index = rightCount[CurlyBracket]++;
3563 if (index == rightPositions[CurlyBracket].length) {
3564 System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
3565 System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
3567 rightPositions[CurlyBracket][index] = scanner.startPosition;
3568 rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
3572 int index = leftCount[RoundBracket]++;
3573 if (index == leftPositions[RoundBracket].length) {
3574 System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
3575 System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
3577 leftPositions[RoundBracket][index] = scanner.startPosition;
3578 leftDepths[RoundBracket][index] = depths[RoundBracket]++;
3582 int index = rightCount[RoundBracket]++;
3583 if (index == rightPositions[RoundBracket].length) {
3584 System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
3585 System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
3587 rightPositions[RoundBracket][index] = scanner.startPosition;
3588 rightDepths[RoundBracket][index] = --depths[RoundBracket];
3592 int index = leftCount[SquareBracket]++;
3593 if (index == leftPositions[SquareBracket].length) {
3594 System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
3595 System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
3597 leftPositions[SquareBracket][index] = scanner.startPosition;
3598 leftDepths[SquareBracket][index] = depths[SquareBracket]++;
3602 int index = rightCount[SquareBracket]++;
3603 if (index == rightPositions[SquareBracket].length) {
3604 System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
3605 System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
3607 rightPositions[SquareBracket][index] = scanner.startPosition;
3608 rightDepths[SquareBracket][index] = --depths[SquareBracket];
3612 if (scanner.getNextChar('\\')) {
3613 scanner.scanEscapeCharacter();
3614 } else { // consume next character
3615 scanner.unicodeAsBackSlash = false;
3616 // if (((scanner.currentCharacter =
3617 // source[scanner.currentPosition++]) ==
3619 // (source[scanner.currentPosition] ==
3621 // scanner.getNextUnicodeChar();
3623 if (scanner.withoutUnicodePtr != 0) {
3624 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3628 scanner.getNextChar('\'');
3632 // consume next character
3633 scanner.unicodeAsBackSlash = false;
3634 // if (((scanner.currentCharacter =
3635 // source[scanner.currentPosition++]) == '\\') &&
3636 // (source[scanner.currentPosition] == 'u')) {
3637 // scanner.getNextUnicodeChar();
3639 if (scanner.withoutUnicodePtr != 0) {
3640 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3643 while (scanner.currentCharacter != '"') {
3644 if (scanner.currentCharacter == '\r') {
3645 if (source[scanner.currentPosition] == '\n')
3646 scanner.currentPosition++;
3647 break; // the string cannot go further that
3650 if (scanner.currentCharacter == '\n') {
3651 break; // the string cannot go further that
3654 if (scanner.currentCharacter == '\\') {
3655 scanner.scanEscapeCharacter();
3657 // consume next character
3658 scanner.unicodeAsBackSlash = false;
3659 // if (((scanner.currentCharacter =
3660 // source[scanner.currentPosition++]) == '\\')
3661 // && (source[scanner.currentPosition] == 'u'))
3663 // scanner.getNextUnicodeChar();
3665 if (scanner.withoutUnicodePtr != 0) {
3666 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3673 if ((test = scanner.getNextChar('/', '*')) == 0) { //line
3676 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3677 && (source[scanner.currentPosition] == 'u')) {
3678 //-------------unicode traitement
3680 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3681 scanner.currentPosition++;
3682 while (source[scanner.currentPosition] == 'u') {
3683 scanner.currentPosition++;
3685 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3686 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3687 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3688 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3692 scanner.currentCharacter = 'A';
3693 } //something different from \n and \r
3695 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3698 while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
3700 scanner.startPosition = scanner.currentPosition;
3701 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3702 && (source[scanner.currentPosition] == 'u')) {
3703 //-------------unicode traitement
3705 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3706 scanner.currentPosition++;
3707 while (source[scanner.currentPosition] == 'u') {
3708 scanner.currentPosition++;
3710 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3711 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3712 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3713 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3717 scanner.currentCharacter = 'A';
3718 } //something different from \n
3721 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3725 if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
3726 if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
3727 // only record line positions we
3728 // have not recorded yet
3729 scanner.pushLineSeparator();
3730 if (this.scanner.taskTags != null) {
3731 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner
3732 .getCurrentTokenEndPosition());
3738 if (test > 0) { //traditional and annotation
3740 boolean star = false;
3741 // consume next character
3742 scanner.unicodeAsBackSlash = false;
3743 // if (((scanner.currentCharacter =
3744 // source[scanner.currentPosition++]) ==
3746 // (source[scanner.currentPosition] ==
3748 // scanner.getNextUnicodeChar();
3750 if (scanner.withoutUnicodePtr != 0) {
3751 scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
3754 if (scanner.currentCharacter == '*') {
3758 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3759 && (source[scanner.currentPosition] == 'u')) {
3760 //-------------unicode traitement
3762 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3763 scanner.currentPosition++;
3764 while (source[scanner.currentPosition] == 'u') {
3765 scanner.currentPosition++;
3767 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3768 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3769 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3770 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3774 scanner.currentCharacter = 'A';
3775 } //something different from * and /
3777 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3780 //loop until end of comment */
3781 while ((scanner.currentCharacter != '/') || (!star)) {
3782 star = scanner.currentCharacter == '*';
3784 if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\')
3785 && (source[scanner.currentPosition] == 'u')) {
3786 //-------------unicode traitement
3788 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3789 scanner.currentPosition++;
3790 while (source[scanner.currentPosition] == 'u') {
3791 scanner.currentPosition++;
3793 if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0
3794 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0
3795 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0
3796 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error
3800 scanner.currentCharacter = 'A';
3801 } //something different from * and
3804 scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
3808 if (this.scanner.taskTags != null) {
3809 this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
3816 if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
3817 scanner.scanIdentifierOrKeyword(false);
3820 if (Character.isDigit(scanner.currentCharacter)) {
3821 scanner.scanNumber(false);
3825 //-----------------end switch while
3826 // try--------------------
3827 } catch (IndexOutOfBoundsException e) {
3828 break; // read until EOF
3829 } catch (InvalidInputException e) {
3830 return false; // no clue
3833 if (scanner.recordLineSeparator) {
3834 // compilationUnit.compilationResult.lineSeparatorPositions =
3835 // scanner.getLineEnds();
3837 // check placement anomalies against other kinds of brackets
3838 for (int kind = 0; kind < BracketKinds; kind++) {
3839 for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
3840 int start = leftPositions[kind][leftIndex]; // deepest
3842 // find matching closing bracket
3843 int depth = leftDepths[kind][leftIndex];
3845 for (int i = 0; i < rightCount[kind]; i++) {
3846 int pos = rightPositions[kind][i];
3847 // want matching bracket further in source with same
3849 if ((pos > start) && (depth == rightDepths[kind][i])) {
3854 if (end < 0) { // did not find a good closing match
3855 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
3858 // check if even number of opening/closing other brackets
3859 // in between this pair of brackets
3861 for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds); otherKind++) {
3862 for (int i = 0; i < leftCount[otherKind]; i++) {
3863 int pos = leftPositions[otherKind][i];
3864 if ((pos > start) && (pos < end))
3867 for (int i = 0; i < rightCount[otherKind]; i++) {
3868 int pos = rightPositions[otherKind][i];
3869 if ((pos > start) && (pos < end))
3873 problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket
3879 // too many opening brackets ?
3880 for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
3881 anomaliesDetected = true;
3882 problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext,
3883 compilationUnit.compilationResult);
3885 // too many closing brackets ?
3886 for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
3887 anomaliesDetected = true;
3888 problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
3890 if (anomaliesDetected)
3893 return anomaliesDetected;
3894 } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
3895 return anomaliesDetected;
3896 } catch (NullPointerException e) { // jdk1.2.2 jit bug
3897 return anomaliesDetected;
3900 protected void pushOnAstLengthStack(int pos) {
3902 astLengthStack[++astLengthPtr] = pos;
3903 } catch (IndexOutOfBoundsException e) {
3904 int oldStackLength = astLengthStack.length;
3905 int[] oldPos = astLengthStack;
3906 astLengthStack = new int[oldStackLength + StackIncrement];
3907 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3908 astLengthStack[astLengthPtr] = pos;
3911 protected void pushOnAstStack(AstNode node) {
3913 * add a new obj on top of the ast stack
3916 astStack[++astPtr] = node;
3917 } catch (IndexOutOfBoundsException e) {
3918 int oldStackLength = astStack.length;
3919 AstNode[] oldStack = astStack;
3920 astStack = new AstNode[oldStackLength + AstStackIncrement];
3921 System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
3922 astPtr = oldStackLength;
3923 astStack[astPtr] = node;
3926 astLengthStack[++astLengthPtr] = 1;
3927 } catch (IndexOutOfBoundsException e) {
3928 int oldStackLength = astLengthStack.length;
3929 int[] oldPos = astLengthStack;
3930 astLengthStack = new int[oldStackLength + AstStackIncrement];
3931 System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
3932 astLengthStack[astLengthPtr] = 1;
3936 protected void resetModifiers() {
3937 this.modifiers = AccDefault;
3938 this.modifiersSourceStart = -1; // <-- see comment into
3939 // modifiersFlag(int)
3940 this.scanner.commentPtr = -1;