4 CHOICE_AMBIGUITY_CHECK = 2;
5 OTHER_AMBIGUITY_CHECK = 1;
8 DEBUG_LOOKAHEAD = false;
9 DEBUG_TOKEN_MANAGER = false;
10 OPTIMIZE_TOKEN_MANAGER = false;
11 ERROR_REPORTING = true;
12 JAVA_UNICODE_ESCAPE = false;
13 UNICODE_INPUT = false;
15 USER_TOKEN_MANAGER = false;
16 USER_CHAR_STREAM = false;
18 BUILD_TOKEN_MANAGER = true;
20 FORCE_LA_CHECK = false;
21 COMMON_TOKEN_ACTION = true;
24 PARSER_BEGIN(PHPParser)
27 import org.eclipse.core.resources.IFile;
28 import org.eclipse.core.resources.IMarker;
29 import org.eclipse.core.runtime.CoreException;
30 import org.eclipse.ui.texteditor.MarkerUtilities;
31 import org.eclipse.jface.preference.IPreferenceStore;
33 import java.util.Hashtable;
34 import java.util.ArrayList;
35 import java.io.StringReader;
37 import java.text.MessageFormat;
39 import net.sourceforge.phpeclipse.actions.PHPStartApacheAction;
40 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
41 import net.sourceforge.phpdt.internal.compiler.ast.*;
42 import net.sourceforge.phpdt.internal.compiler.parser.OutlineableWithChildren;
43 import net.sourceforge.phpdt.internal.compiler.parser.Outlineable;
44 import net.sourceforge.phpdt.internal.compiler.parser.PHPOutlineInfo;
45 import net.sourceforge.phpdt.internal.corext.Assert;
49 * This php parser is inspired by the Java 1.2 grammar example
50 * given with JavaCC. You can get JavaCC at http://www.webgain.com
51 * You can test the parser with the PHPParserTestCase2.java
52 * @author Matthieu Casanova
54 public final class PHPParser extends PHPParserSuperclass {
56 //todo : fix the variables names bug
57 //todo : handle tilde operator
60 /** The current segment. */
61 private static OutlineableWithChildren currentSegment;
63 private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$
64 private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$
65 static PHPOutlineInfo outlineInfo;
67 /** The error level of the current ParseException. */
68 private static int errorLevel = ERROR;
69 /** The message of the current ParseException. If it's null it's because the parse exception wasn't handled */
70 private static String errorMessage;
72 private static int errorStart = -1;
73 private static int errorEnd = -1;
74 private static PHPDocument phpDocument;
76 private static final String SYNTAX_ERROR_CHAR = "syntax error";
78 * The point where html starts.
79 * It will be used by the token manager to create HTMLCode objects
81 public static int htmlStart;
84 private final static int AstStackIncrement = 100;
85 /** The stack of node. */
86 private static AstNode[] nodes;
87 /** The cursor in expression stack. */
88 private static int nodePtr;
90 private static final boolean PARSER_DEBUG = true;
92 public final void setFileToParse(final IFile fileToParse) {
93 PHPParser.fileToParse = fileToParse;
99 public PHPParser(final IFile fileToParse) {
100 this(new StringReader(""));
101 PHPParser.fileToParse = fileToParse;
104 public static final void phpParserTester(final String strEval) throws ParseException {
105 final StringReader stream = new StringReader(strEval);
106 if (jj_input_stream == null) {
107 jj_input_stream = new SimpleCharStream(stream, 1, 1);
109 ReInit(new StringReader(strEval));
111 phpDocument = new PHPDocument(null,"_root".toCharArray());
112 currentSegment = phpDocument;
113 outlineInfo = new PHPOutlineInfo(null, currentSegment);
114 PHPParserTokenManager.SwitchTo(PHPParserTokenManager.PHPPARSING);
118 public static final void htmlParserTester(final File fileName) throws FileNotFoundException, ParseException {
119 final Reader stream = new FileReader(fileName);
120 if (jj_input_stream == null) {
121 jj_input_stream = new SimpleCharStream(stream, 1, 1);
125 phpDocument = new PHPDocument(null,"_root".toCharArray());
126 currentSegment = phpDocument;
127 outlineInfo = new PHPOutlineInfo(null, currentSegment);
131 public static final void htmlParserTester(final String strEval) throws ParseException {
132 final StringReader stream = new StringReader(strEval);
133 if (jj_input_stream == null) {
134 jj_input_stream = new SimpleCharStream(stream, 1, 1);
138 phpDocument = new PHPDocument(null,"_root".toCharArray());
139 currentSegment = phpDocument;
140 outlineInfo = new PHPOutlineInfo(null, currentSegment);
145 * Reinitialize the parser.
147 private static final void init() {
148 nodes = new AstNode[AstStackIncrement];
154 * Add an php node on the stack.
155 * @param node the node that will be added to the stack
157 private static final void pushOnAstNodes(final AstNode node) {
159 nodes[++nodePtr] = node;
160 } catch (IndexOutOfBoundsException e) {
161 final int oldStackLength = nodes.length;
162 final AstNode[] oldStack = nodes;
163 nodes = new AstNode[oldStackLength + AstStackIncrement];
164 System.arraycopy(oldStack, 0, nodes, 0, oldStackLength);
165 nodePtr = oldStackLength;
166 nodes[nodePtr] = node;
170 public final PHPOutlineInfo parseInfo(final Object parent, final String s) {
171 phpDocument = new PHPDocument(parent,"_root".toCharArray());
172 currentSegment = phpDocument;
173 outlineInfo = new PHPOutlineInfo(parent, currentSegment);
174 final StringReader stream = new StringReader(s);
175 if (jj_input_stream == null) {
176 jj_input_stream = new SimpleCharStream(stream, 1, 1);
182 phpDocument.nodes = new AstNode[nodes.length];
183 System.arraycopy(nodes,0,phpDocument.nodes,0,nodes.length);
184 if (PHPeclipsePlugin.DEBUG) {
185 PHPeclipsePlugin.log(1,phpDocument.toString());
187 } catch (ParseException e) {
188 processParseException(e);
193 private static void processParseExceptionDebug(final ParseException e) throws ParseException {
197 processParseException(e);
200 * This method will process the parse exception.
201 * If the error message is null, the parse exception wasn't catched and a trace is written in the log
202 * @param e the ParseException
204 private static void processParseException(final ParseException e) {
205 if (errorMessage == null) {
206 PHPeclipsePlugin.log(e);
207 errorMessage = "this exception wasn't handled by the parser please tell us how to reproduce it";
208 errorStart = e.currentToken.sourceStart;
209 errorEnd = e.currentToken.sourceEnd;
213 // if (PHPeclipsePlugin.DEBUG) PHPeclipsePlugin.log(e);
217 * Create marker for the parse error.
218 * @param e the ParseException
220 private static void setMarker(final ParseException e) {
222 if (errorStart == -1) {
223 setMarker(fileToParse,
225 e.currentToken.sourceStart,
226 e.currentToken.sourceEnd,
228 "Line " + e.currentToken.beginLine);
230 setMarker(fileToParse,
235 "Line " + e.currentToken.beginLine);
239 } catch (CoreException e2) {
240 PHPeclipsePlugin.log(e2);
244 private static void scanLine(final String output,
247 final int brIndx) throws CoreException {
249 final StringBuffer lineNumberBuffer = new StringBuffer(10);
251 current = output.substring(indx, brIndx);
253 if (current.indexOf(PARSE_WARNING_STRING) != -1 || current.indexOf(PARSE_ERROR_STRING) != -1) {
254 final int onLine = current.indexOf("on line <b>");
256 lineNumberBuffer.delete(0, lineNumberBuffer.length());
257 for (int i = onLine; i < current.length(); i++) {
258 ch = current.charAt(i);
259 if ('0' <= ch && '9' >= ch) {
260 lineNumberBuffer.append(ch);
264 final int lineNumber = Integer.parseInt(lineNumberBuffer.toString());
266 final Hashtable attributes = new Hashtable();
268 current = current.replaceAll("\n", "");
269 current = current.replaceAll("<b>", "");
270 current = current.replaceAll("</b>", "");
271 MarkerUtilities.setMessage(attributes, current);
273 if (current.indexOf(PARSE_ERROR_STRING) != -1)
274 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
275 else if (current.indexOf(PARSE_WARNING_STRING) != -1)
276 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
278 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
279 MarkerUtilities.setLineNumber(attributes, lineNumber);
280 MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
285 public final void parse(final String s) {
286 final StringReader stream = new StringReader(s);
287 if (jj_input_stream == null) {
288 jj_input_stream = new SimpleCharStream(stream, 1, 1);
294 } catch (ParseException e) {
295 processParseException(e);
300 * Call the php parse command ( php -l -f <filename> )
301 * and create markers according to the external parser output
303 public static void phpExternalParse(final IFile file) {
304 final IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
305 final String filename = file.getLocation().toString();
307 final String[] arguments = { filename };
308 final MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF));
309 final String command = form.format(arguments);
311 final String parserResult = PHPStartApacheAction.getParserOutput(command, "External parser: ");
314 // parse the buffer to find the errors and warnings
315 createMarkers(parserResult, file);
316 } catch (CoreException e) {
317 PHPeclipsePlugin.log(e);
322 * Put a new html block in the stack.
324 public static final void createNewHTMLCode() {
325 final int currentPosition = token.sourceStart;
326 if (currentPosition == htmlStart ||
327 currentPosition > SimpleCharStream.currentBuffer.length()) {
330 final char[] chars = SimpleCharStream.currentBuffer.substring(htmlStart,currentPosition+1).toCharArray();
331 pushOnAstNodes(new HTMLCode(chars, htmlStart,currentPosition));
334 /** Create a new task. */
335 public static final void createNewTask() {
336 final int currentPosition = token.sourceStart;
337 final String todo = SimpleCharStream.currentBuffer.substring(currentPosition-3,
338 SimpleCharStream.currentBuffer.indexOf("\n",
342 setMarker(fileToParse,
344 SimpleCharStream.getBeginLine(),
346 "Line "+SimpleCharStream.getBeginLine());
347 } catch (CoreException e) {
348 PHPeclipsePlugin.log(e);
353 private static final void parse() throws ParseException {
358 PARSER_END(PHPParser)
362 // CommonTokenAction: use the begins/ends fields added to the Jack
363 // CharStream class to set corresponding fields in each Token (which was
364 // also extended with new fields). By default Jack doesn't supply absolute
365 // offsets, just line/column offsets
366 static void CommonTokenAction(Token t) {
367 t.sourceStart = input_stream.beginOffset;
368 t.sourceEnd = input_stream.endOffset;
369 } // CommonTokenAction
374 <PHPSTARTSHORT : "<?"> {PHPParser.createNewHTMLCode();} : PHPPARSING
375 | <PHPSTARTLONG : "<?php"> {PHPParser.createNewHTMLCode();} : PHPPARSING
376 | <PHPECHOSTART : "<?="> {PHPParser.createNewHTMLCode();} : PHPPARSING
379 <PHPPARSING, IN_SINGLE_LINE_COMMENT> TOKEN :
381 <PHPEND :"?>"> {PHPParser.htmlStart = PHPParser.token.sourceEnd;} : DEFAULT
384 /* Skip any character if we are not in php mode */
402 <PHPPARSING> SPECIAL_TOKEN :
404 "//" : IN_SINGLE_LINE_COMMENT
405 | "#" : IN_SINGLE_LINE_COMMENT
406 | <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
407 | "/*" : IN_MULTI_LINE_COMMENT
410 <IN_SINGLE_LINE_COMMENT> SPECIAL_TOKEN :
412 <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : PHPPARSING
416 <IN_SINGLE_LINE_COMMENT,IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT> SPECIAL_TOKEN :
418 "todo" {PHPParser.createNewTask();}
421 <IN_FORMAL_COMMENT> SPECIAL_TOKEN :
426 <IN_MULTI_LINE_COMMENT> SPECIAL_TOKEN :
431 <IN_SINGLE_LINE_COMMENT,IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT>
441 | <FUNCTION : "function">
444 | <ELSEIF : "elseif">
451 /* LANGUAGE CONSTRUCT */
456 | <INCLUDE : "include">
457 | <REQUIRE : "require">
458 | <INCLUDE_ONCE : "include_once">
459 | <REQUIRE_ONCE : "require_once">
460 | <GLOBAL : "global">
461 | <DEFINE : "define">
462 | <STATIC : "static">
463 | <CLASSACCESS : "->">
464 | <STATICCLASSACCESS : "::">
465 | <ARRAYASSIGN : "=>">
468 /* RESERVED WORDS AND LITERALS */
474 | <CONTINUE : "continue">
475 | <_DEFAULT : "default">
477 | <EXTENDS : "extends">
482 | <RETURN : "return">
484 | <SWITCH : "switch">
489 | <ENDWHILE : "endwhile">
490 | <ENDSWITCH: "endswitch">
492 | <ENDFOR : "endfor">
493 | <FOREACH : "foreach">
501 | <OBJECT : "object">
503 | <BOOLEAN : "boolean">
505 | <DOUBLE : "double">
508 | <INTEGER : "integer">
528 | <MINUS_MINUS : "--">
538 | <RSIGNEDSHIFT : ">>">
539 | <RUNSIGNEDSHIFT : ">>>">
548 <DECIMAL_LITERAL> (["l","L"])?
549 | <HEX_LITERAL> (["l","L"])?
550 | <OCTAL_LITERAL> (["l","L"])?
553 <#DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
555 <#HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
557 <#OCTAL_LITERAL: "0" (["0"-"7"])* >
559 <FLOATING_POINT_LITERAL:
560 (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?
561 | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
562 | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
563 | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]
566 <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
568 <STRING_LITERAL: (<STRING_1> | <STRING_2> | <STRING_3>)>
569 | <STRING_1: "\"" ( ~["\"","\\"] | "\\" ~[] )* "\"">
570 | <STRING_2: "'" ( ~["'","\\"] | "\\" ~[] )* "'">
571 | <STRING_3: "`" ( ~["`","\\"] | "\\" ~[] )* "`">
578 <IDENTIFIER: (<LETTER>|<SPECIAL>) (<LETTER>|<DIGIT>|<SPECIAL>)* >
581 ["a"-"z"] | ["A"-"Z"]
589 "_" | ["\u007f"-"\u00ff"]
614 | <EQUAL_EQUAL : "==">
619 | <BANGDOUBLEEQUAL : "!==">
620 | <TRIPLEEQUAL : "===">
627 | <PLUSASSIGN : "+=">
628 | <MINUSASSIGN : "-=">
629 | <STARASSIGN : "*=">
630 | <SLASHASSIGN : "/=">
636 | <TILDEEQUAL : "~=">
637 | <LSHIFTASSIGN : "<<=">
638 | <RSIGNEDSHIFTASSIGN : ">>=">
643 <DOLLAR_ID: <DOLLAR> <IDENTIFIER>>
658 {PHPParser.createNewHTMLCode();}
659 } catch (TokenMgrError e) {
660 PHPeclipsePlugin.log(e);
661 errorStart = SimpleCharStream.getPosition();
662 errorEnd = errorStart + 1;
663 errorMessage = e.getMessage();
665 throw generateParseException();
670 * A php block is a <?= expression [;]?>
671 * or <?php somephpcode ?>
672 * or <? somephpcode ?>
676 final PHPEchoBlock phpEchoBlock;
680 phpEchoBlock = phpEchoBlock()
681 {pushOnAstNodes(phpEchoBlock);}
684 | token = <PHPSTARTSHORT>
686 setMarker(fileToParse,
687 "You should use '<?php' instead of '<?' it will avoid some problems with XML",
691 "Line " + token.beginLine);
692 } catch (CoreException e) {
693 PHPeclipsePlugin.log(e);
699 } catch (ParseException e) {
700 errorMessage = "'?>' expected";
702 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
703 errorEnd = SimpleCharStream.getPosition() + 1;
704 processParseExceptionDebug(e);
708 PHPEchoBlock phpEchoBlock() :
710 final Expression expr;
711 final PHPEchoBlock echoBlock;
712 final Token token, token2;
715 token = <PHPECHOSTART> expr = Expression() [ <SEMICOLON> ] token2 = <PHPEND>
717 echoBlock = new PHPEchoBlock(expr,token.sourceStart,token2.sourceEnd);
718 pushOnAstNodes(echoBlock);
728 ClassDeclaration ClassDeclaration() :
730 final ClassDeclaration classDeclaration;
731 Token className = null;
732 final Token superclassName, token;
733 String classNameImage = SYNTAX_ERROR_CHAR;
734 String superclassNameImage = null;
739 className = <IDENTIFIER>
740 {classNameImage = className.image;}
741 } catch (ParseException e) {
742 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', identifier expected";
744 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
745 errorEnd = SimpleCharStream.getPosition() + 1;
746 processParseExceptionDebug(e);
751 superclassName = <IDENTIFIER>
752 {superclassNameImage = superclassName.image;}
753 } catch (ParseException e) {
754 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', identifier expected";
756 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
757 errorEnd = SimpleCharStream.getPosition() + 1;
758 processParseExceptionDebug(e);
759 superclassNameImage = SYNTAX_ERROR_CHAR;
764 if (className == null) {
765 start = token.sourceStart;
766 end = token.sourceEnd;
768 start = className.sourceStart;
769 end = className.sourceEnd;
771 if (superclassNameImage == null) {
773 classDeclaration = new ClassDeclaration(currentSegment,
778 classDeclaration = new ClassDeclaration(currentSegment,
784 currentSegment.add(classDeclaration);
785 currentSegment = classDeclaration;
787 ClassBody(classDeclaration)
788 {currentSegment = (OutlineableWithChildren) currentSegment.getParent();
789 classDeclaration.sourceEnd = SimpleCharStream.getPosition();
790 pushOnAstNodes(classDeclaration);
791 return classDeclaration;}
794 void ClassBody(final ClassDeclaration classDeclaration) :
799 } catch (ParseException e) {
800 errorMessage = "unexpected token : '"+ e.currentToken.next.image + "'. '{' expected";
802 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
803 errorEnd = SimpleCharStream.getPosition() + 1;
804 processParseExceptionDebug(e);
806 ( ClassBodyDeclaration(classDeclaration) )*
809 } catch (ParseException e) {
810 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. 'var', 'function' or '}' expected";
812 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
813 errorEnd = SimpleCharStream.getPosition() + 1;
814 processParseExceptionDebug(e);
819 * A class can contain only methods and fields.
821 void ClassBodyDeclaration(final ClassDeclaration classDeclaration) :
823 final MethodDeclaration method;
824 final FieldDeclaration field;
827 method = MethodDeclaration() {method.analyzeCode();
828 classDeclaration.addMethod(method);}
829 | field = FieldDeclaration() {classDeclaration.addField(field);}
833 * A class field declaration : it's var VariableDeclarator() (, VariableDeclarator())*;.
834 * it is only used by ClassBodyDeclaration()
836 FieldDeclaration FieldDeclaration() :
838 VariableDeclaration variableDeclaration;
839 final VariableDeclaration[] list;
840 final ArrayList arrayList = new ArrayList();
845 token = <VAR> variableDeclaration = VariableDeclaratorNoSuffix()
846 {arrayList.add(variableDeclaration);
847 outlineInfo.addVariable(variableDeclaration.name());}
849 <COMMA> variableDeclaration = VariableDeclaratorNoSuffix()
850 {arrayList.add(variableDeclaration);
851 outlineInfo.addVariable(variableDeclaration.name());}
855 } catch (ParseException e) {
856 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected after variable declaration";
858 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
859 errorEnd = SimpleCharStream.getPosition() + 1;
860 processParseExceptionDebug(e);
863 {list = new VariableDeclaration[arrayList.size()];
864 arrayList.toArray(list);
866 if (token2 == null) {
867 end = list[list.length-1].sourceEnd;
869 end = token2.sourceEnd;
871 return new FieldDeclaration(list,
878 * a strict variable declarator : there cannot be a suffix here.
879 * It will be used by fields and formal parameters
881 VariableDeclaration VariableDeclaratorNoSuffix() :
884 Expression initializer = null;
888 varName = <DOLLAR_ID>
890 assignToken = <ASSIGN>
892 initializer = VariableInitializer()
893 } catch (ParseException e) {
894 errorMessage = "Literal expression expected in variable initializer";
896 errorStart = assignToken.sourceEnd +1;
897 errorEnd = assignToken.sourceEnd +1;
898 processParseExceptionDebug(e);
902 if (initializer == null) {
903 return new VariableDeclaration(currentSegment,
904 new Variable(varName.image.substring(1),
905 varName.sourceStart+1,
906 varName.sourceEnd+1),
907 varName.sourceStart+1,
908 varName.sourceEnd+1);
910 return new VariableDeclaration(currentSegment,
911 new Variable(varName.image.substring(1),
912 varName.sourceStart+1,
913 varName.sourceEnd+1),
915 VariableDeclaration.EQUAL,
916 varName.sourceStart+1);
921 * this will be used by static statement
923 VariableDeclaration VariableDeclarator() :
925 final AbstractVariable variable;
926 Expression initializer = null;
929 variable = VariableDeclaratorId()
933 initializer = VariableInitializer()
934 } catch (ParseException e) {
935 errorMessage = "Literal expression expected in variable initializer";
937 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
938 errorEnd = SimpleCharStream.getPosition() + 1;
939 processParseExceptionDebug(e);
943 if (initializer == null) {
944 return new VariableDeclaration(currentSegment,
946 variable.sourceStart,
949 return new VariableDeclaration(currentSegment,
952 VariableDeclaration.EQUAL,
953 variable.sourceStart);
959 * @return the variable name (with suffix)
961 AbstractVariable VariableDeclaratorId() :
964 AbstractVariable expression = null;
971 expression = VariableSuffix(var)
974 if (expression == null) {
979 } catch (ParseException e) {
980 errorMessage = "'$' expected for variable identifier";
982 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
983 errorEnd = SimpleCharStream.getPosition() + 1;
989 * Return a variablename without the $.
990 * @return a variable name
994 final StringBuffer buff;
995 Expression expression = null;
1002 [<LBRACE> expression = Expression() <RBRACE>]
1004 if (expression == null) {
1005 return new Variable(token.image.substring(1),
1006 token.sourceStart+1,
1009 String s = expression.toStringExpression();
1010 buff = new StringBuffer(token.image.length()+s.length()+2);
1011 buff.append(token.image);
1015 s = buff.toString();
1016 return new Variable(s,token.sourceStart+1,token.sourceEnd+1);
1020 expr = VariableName()
1021 {return new Variable(expr,token.sourceStart,expr.sourceEnd);}
1024 Variable Variable() :
1026 Variable variable = null;
1030 token = <DOLLAR_ID> [variable = Var(token)]
1032 if (variable == null) {
1033 return new Variable(token.image.substring(1),token.sourceStart+1,token.sourceEnd+1);
1035 final StringBuffer buff = new StringBuffer();
1036 buff.append(token.image.substring(1));
1037 buff.append(variable.toStringExpression());
1038 return new Variable(buff.toString(),token.sourceStart+1,variable.sourceEnd+1);
1041 token = <DOLLAR> variable = Var(token)
1043 return new Variable(variable,token.sourceStart,variable.sourceEnd);
1047 Variable Var(final Token dollar) :
1049 Variable variable = null;
1051 ConstantIdentifier constant;
1054 token = <DOLLAR_ID> [variable = Var(token)]
1055 {if (variable == null) {
1056 return new Variable(token.image.substring(1),token.sourceStart+1,token.sourceEnd+1);
1058 final StringBuffer buff = new StringBuffer();
1059 buff.append(token.image.substring(1));
1060 buff.append(variable.toStringExpression());
1061 return new Variable(buff.toString(),dollar.sourceStart,variable.sourceEnd);
1064 LOOKAHEAD(<DOLLAR> <DOLLAR>)
1065 token = <DOLLAR> variable = Var(token)
1066 {return new Variable(variable,dollar.sourceStart,variable.sourceEnd);}
1068 constant = VariableName()
1069 {return new Variable(constant.name,dollar.sourceStart,constant.sourceEnd);}
1073 * A Variable name (without the $)
1074 * @return a variable name String
1076 ConstantIdentifier VariableName():
1078 final StringBuffer buff;
1080 Expression expression = null;
1082 Token token2 = null;
1085 token = <LBRACE> expression = Expression() token2 = <RBRACE>
1086 {expr = expression.toStringExpression();
1087 buff = new StringBuffer(expr.length()+2);
1091 expr = buff.toString();
1092 return new ConstantIdentifier(expr,
1098 token = <IDENTIFIER>
1099 [<LBRACE> expression = Expression() token2 = <RBRACE>]
1101 if (expression == null) {
1102 return new ConstantIdentifier(token.image,
1106 expr = expression.toStringExpression();
1107 buff = new StringBuffer(token.image.length()+expr.length()+2);
1108 buff.append(token.image);
1112 expr = buff.toString();
1113 return new ConstantIdentifier(expr,
1119 var = VariableName()
1121 return new Variable(var,
1128 return new Variable(token.image,
1129 token.sourceStart+1,
1134 Expression VariableInitializer() :
1136 final Expression expr;
1137 final Token token, token2;
1143 token2 = <MINUS> (token = <INTEGER_LITERAL> | token = <FLOATING_POINT_LITERAL>)
1144 {return new PrefixedUnaryExpression(new NumberLiteral(token),
1146 token2.sourceStart);}
1148 token2 = <PLUS> (token = <INTEGER_LITERAL> | token = <FLOATING_POINT_LITERAL>)
1149 {return new PrefixedUnaryExpression(new NumberLiteral(token),
1151 token2.sourceStart);}
1153 expr = ArrayDeclarator()
1156 token = <IDENTIFIER>
1157 {return new ConstantIdentifier(token);}
1160 ArrayVariableDeclaration ArrayVariable() :
1162 final Expression expr,expr2;
1167 <ARRAYASSIGN> expr2 = Expression()
1168 {return new ArrayVariableDeclaration(expr,expr2);}
1170 {return new ArrayVariableDeclaration(expr,SimpleCharStream.getPosition());}
1173 ArrayVariableDeclaration[] ArrayInitializer() :
1175 ArrayVariableDeclaration expr;
1176 final ArrayList list = new ArrayList();
1181 expr = ArrayVariable()
1183 ( LOOKAHEAD(2) <COMMA> expr = ArrayVariable()
1188 <COMMA> {list.add(null);}
1192 final ArrayVariableDeclaration[] vars = new ArrayVariableDeclaration[list.size()];
1198 * A Method Declaration.
1199 * <b>function</b> MetodDeclarator() Block()
1201 MethodDeclaration MethodDeclaration() :
1203 final MethodDeclaration functionDeclaration;
1205 final OutlineableWithChildren seg = currentSegment;
1211 functionDeclaration = MethodDeclarator(token.sourceStart)
1212 {outlineInfo.addVariable(new String(functionDeclaration.name));}
1213 } catch (ParseException e) {
1214 if (errorMessage != null) throw e;
1215 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function identifier expected";
1217 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
1218 errorEnd = SimpleCharStream.getPosition() + 1;
1221 {currentSegment = functionDeclaration;}
1223 {functionDeclaration.statements = block.statements;
1224 currentSegment = seg;
1225 return functionDeclaration;}
1229 * A MethodDeclarator.
1230 * [&] IDENTIFIER(parameters ...).
1231 * @return a function description for the outline
1233 MethodDeclaration MethodDeclarator(final int start) :
1235 Token identifier = null;
1236 Token reference = null;
1237 final Hashtable formalParameters = new Hashtable();
1238 String identifierChar = SYNTAX_ERROR_CHAR;
1242 [reference = <BIT_AND>]
1244 identifier = <IDENTIFIER>
1245 {identifierChar = identifier.image;}
1246 } catch (ParseException e) {
1247 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function identifier expected";
1249 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
1250 errorEnd = SimpleCharStream.getPosition() + 1;
1251 processParseExceptionDebug(e);
1253 end = FormalParameters(formalParameters)
1255 int nameStart, nameEnd;
1256 if (identifier == null) {
1257 if (reference == null) {
1258 nameStart = start + 9;
1259 nameEnd = start + 10;
1261 nameStart = reference.sourceEnd + 1;
1262 nameEnd = reference.sourceEnd + 2;
1265 nameStart = identifier.sourceStart;
1266 nameEnd = identifier.sourceEnd;
1268 return new MethodDeclaration(currentSegment,
1280 * FormalParameters follows method identifier.
1281 * (FormalParameter())
1283 int FormalParameters(final Hashtable parameters) :
1285 VariableDeclaration var;
1292 } catch (ParseException e) {
1293 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', '(' expected after function identifier";
1295 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
1296 errorEnd = SimpleCharStream.getPosition() + 1;
1297 processParseExceptionDebug(e);
1300 var = FormalParameter()
1301 {parameters.put(new String(var.name()),var);}
1303 <COMMA> var = FormalParameter()
1304 {parameters.put(new String(var.name()),var);}
1309 {end = token.sourceEnd;}
1310 } catch (ParseException e) {
1311 errorMessage = "')' expected";
1313 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
1314 errorEnd = SimpleCharStream.getPosition() + 1;
1315 processParseExceptionDebug(e);
1316 end = e.currentToken.sourceStart;
1322 * A formal parameter.
1323 * $varname[=value] (,$varname[=value])
1325 VariableDeclaration FormalParameter() :
1327 final VariableDeclaration variableDeclaration;
1331 [token = <BIT_AND>] variableDeclaration = VariableDeclaratorNoSuffix()
1333 if (token != null) {
1334 variableDeclaration.setReference(true);
1336 return variableDeclaration;}
1339 ConstantIdentifier Type() :
1340 {final Token token;}
1342 token = <STRING> {return new ConstantIdentifier(token);}
1343 | token = <BOOL> {return new ConstantIdentifier(token);}
1344 | token = <BOOLEAN> {return new ConstantIdentifier(token);}
1345 | token = <REAL> {return new ConstantIdentifier(token);}
1346 | token = <DOUBLE> {return new ConstantIdentifier(token);}
1347 | token = <FLOAT> {return new ConstantIdentifier(token);}
1348 | token = <INT> {return new ConstantIdentifier(token);}
1349 | token = <INTEGER> {return new ConstantIdentifier(token);}
1350 | token = <OBJECT> {return new ConstantIdentifier(token);}
1353 Expression Expression() :
1355 final Expression expr;
1356 Expression initializer = null;
1357 int assignOperator = -1;
1361 expr = ConditionalExpression()
1363 assignOperator = AssignmentOperator()
1365 initializer = Expression()
1366 } catch (ParseException e) {
1367 if (errorMessage != null) {
1370 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', expression expected";
1372 errorEnd = SimpleCharStream.getPosition();
1377 if (assignOperator != -1) {// todo : change this, very very bad :(
1378 if (expr instanceof AbstractVariable) {
1379 return new VariableDeclaration(currentSegment,
1380 (AbstractVariable) expr,
1383 initializer.sourceEnd);
1385 String varName = expr.toStringExpression().substring(1);
1386 return new VariableDeclaration(currentSegment,
1387 new Variable(varName,
1391 initializer.sourceEnd);
1395 | expr = ExpressionWBang() {return expr;}
1398 Expression ExpressionWBang() :
1400 final Expression expr;
1404 token = <BANG> expr = ExpressionWBang()
1405 {return new PrefixedUnaryExpression(expr,OperatorIds.NOT,token.sourceStart);}
1406 | expr = ExpressionNoBang() {return expr;}
1409 Expression ExpressionNoBang() :
1414 expr = ListExpression() {return expr;}
1416 expr = PrintExpression() {return expr;}
1420 * Any assignement operator.
1421 * @return the assignement operator id
1423 int AssignmentOperator() :
1426 <ASSIGN> {return VariableDeclaration.EQUAL;}
1427 | <STARASSIGN> {return VariableDeclaration.STAR_EQUAL;}
1428 | <SLASHASSIGN> {return VariableDeclaration.SLASH_EQUAL;}
1429 | <REMASSIGN> {return VariableDeclaration.REM_EQUAL;}
1430 | <PLUSASSIGN> {return VariableDeclaration.PLUS_EQUAL;}
1431 | <MINUSASSIGN> {return VariableDeclaration.MINUS_EQUAL;}
1432 | <LSHIFTASSIGN> {return VariableDeclaration.LSHIFT_EQUAL;}
1433 | <RSIGNEDSHIFTASSIGN> {return VariableDeclaration.RSIGNEDSHIFT_EQUAL;}
1434 | <ANDASSIGN> {return VariableDeclaration.AND_EQUAL;}
1435 | <XORASSIGN> {return VariableDeclaration.XOR_EQUAL;}
1436 | <ORASSIGN> {return VariableDeclaration.OR_EQUAL;}
1437 | <DOTASSIGN> {return VariableDeclaration.DOT_EQUAL;}
1438 | <TILDEEQUAL> {return VariableDeclaration.TILDE_EQUAL;}
1441 Expression ConditionalExpression() :
1443 final Expression expr;
1444 Expression expr2 = null;
1445 Expression expr3 = null;
1448 expr = ConditionalOrExpression() [ <HOOK> expr2 = Expression() <COLON> expr3 = ConditionalExpression() ]
1450 if (expr3 == null) {
1453 return new ConditionalExpression(expr,expr2,expr3);
1457 Expression ConditionalOrExpression() :
1459 Expression expr,expr2;
1463 expr = ConditionalAndExpression()
1466 <OR_OR> {operator = OperatorIds.OR_OR;}
1467 | <_ORL> {operator = OperatorIds.ORL;}
1469 expr2 = ConditionalAndExpression()
1471 expr = new BinaryExpression(expr,expr2,operator);
1477 Expression ConditionalAndExpression() :
1479 Expression expr,expr2;
1483 expr = ConcatExpression()
1485 ( <AND_AND> {operator = OperatorIds.AND_AND;}
1486 | <_ANDL> {operator = OperatorIds.ANDL;})
1487 expr2 = ConcatExpression() {expr = new BinaryExpression(expr,expr2,operator);}
1492 Expression ConcatExpression() :
1494 Expression expr,expr2;
1497 expr = InclusiveOrExpression()
1499 <DOT> expr2 = InclusiveOrExpression()
1500 {expr = new BinaryExpression(expr,expr2,OperatorIds.DOT);}
1505 Expression InclusiveOrExpression() :
1507 Expression expr,expr2;
1510 expr = ExclusiveOrExpression()
1511 (<BIT_OR> expr2 = ExclusiveOrExpression()
1512 {expr = new BinaryExpression(expr,expr2,OperatorIds.OR);}
1517 Expression ExclusiveOrExpression() :
1519 Expression expr,expr2;
1522 expr = AndExpression()
1524 <XOR> expr2 = AndExpression()
1525 {expr = new BinaryExpression(expr,expr2,OperatorIds.XOR);}
1530 Expression AndExpression() :
1532 Expression expr,expr2;
1535 expr = EqualityExpression()
1538 <BIT_AND> expr2 = EqualityExpression()
1539 {expr = new BinaryExpression(expr,expr2,OperatorIds.AND);}
1544 Expression EqualityExpression() :
1546 Expression expr,expr2;
1550 expr = RelationalExpression()
1552 ( <EQUAL_EQUAL> {operator = OperatorIds.EQUAL_EQUAL;}
1553 | <DIF> {operator = OperatorIds.DIF;}
1554 | <NOT_EQUAL> {operator = OperatorIds.DIF;}
1555 | <BANGDOUBLEEQUAL> {operator = OperatorIds.BANG_EQUAL_EQUAL;}
1556 | <TRIPLEEQUAL> {operator = OperatorIds.EQUAL_EQUAL_EQUAL;}
1559 expr2 = RelationalExpression()
1560 } catch (ParseException e) {
1561 if (errorMessage != null) {
1564 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', expression expected";
1566 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
1567 errorEnd = SimpleCharStream.getPosition() + 1;
1571 expr = new BinaryExpression(expr,expr2,operator);
1577 Expression RelationalExpression() :
1579 Expression expr,expr2;
1583 expr = ShiftExpression()
1585 ( <LT> {operator = OperatorIds.LESS;}
1586 | <GT> {operator = OperatorIds.GREATER;}
1587 | <LE> {operator = OperatorIds.LESS_EQUAL;}
1588 | <GE> {operator = OperatorIds.GREATER_EQUAL;})
1589 expr2 = ShiftExpression()
1590 {expr = new BinaryExpression(expr,expr2,operator);}
1595 Expression ShiftExpression() :
1597 Expression expr,expr2;
1601 expr = AdditiveExpression()
1603 ( <LSHIFT> {operator = OperatorIds.LEFT_SHIFT;}
1604 | <RSIGNEDSHIFT> {operator = OperatorIds.RIGHT_SHIFT;}
1605 | <RUNSIGNEDSHIFT> {operator = OperatorIds.UNSIGNED_RIGHT_SHIFT;})
1606 expr2 = AdditiveExpression()
1607 {expr = new BinaryExpression(expr,expr2,operator);}
1612 Expression AdditiveExpression() :
1614 Expression expr,expr2;
1618 expr = MultiplicativeExpression()
1621 ( <PLUS> {operator = OperatorIds.PLUS;}
1622 | <MINUS> {operator = OperatorIds.MINUS;}
1624 expr2 = MultiplicativeExpression()
1625 {expr = new BinaryExpression(expr,expr2,operator);}
1630 Expression MultiplicativeExpression() :
1632 Expression expr,expr2;
1637 expr = UnaryExpression()
1638 } catch (ParseException e) {
1639 if (errorMessage != null) throw e;
1640 errorMessage = "unexpected token '"+e.currentToken.next.image+"'";
1642 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
1643 errorEnd = SimpleCharStream.getPosition() + 1;
1647 ( <STAR> {operator = OperatorIds.MULTIPLY;}
1648 | <SLASH> {operator = OperatorIds.DIVIDE;}
1649 | <REMAINDER> {operator = OperatorIds.REMAINDER;})
1650 expr2 = UnaryExpression()
1651 {expr = new BinaryExpression(expr,expr2,operator);}
1657 * An unary expression starting with @, & or nothing
1659 Expression UnaryExpression() :
1661 final Expression expr;
1664 /* <BIT_AND> expr = UnaryExpressionNoPrefix() //why did I had that ?
1665 {return new PrefixedUnaryExpression(expr,OperatorIds.AND,pos);}
1667 expr = AtNotUnaryExpression() {return expr;}
1671 * An expression prefixed (or not) by one or more @ and !.
1672 * @return the expression
1674 Expression AtNotUnaryExpression() :
1676 final Expression expr;
1681 expr = AtNotUnaryExpression()
1682 {return new PrefixedUnaryExpression(expr,OperatorIds.AT,token.sourceStart);}
1685 expr = AtNotUnaryExpression()
1686 {return new PrefixedUnaryExpression(expr,OperatorIds.NOT,token.sourceStart);}
1688 expr = UnaryExpressionNoPrefix()
1692 Expression UnaryExpressionNoPrefix() :
1694 final Expression expr;
1698 token = <PLUS> expr = AtNotUnaryExpression() {return new PrefixedUnaryExpression(expr,
1700 token.sourceStart);}
1702 token = <MINUS> expr = AtNotUnaryExpression() {return new PrefixedUnaryExpression(expr,
1704 token.sourceStart);}
1706 expr = PreIncDecExpression()
1709 expr = UnaryExpressionNotPlusMinus()
1714 Expression PreIncDecExpression() :
1716 final Expression expr;
1722 token = <PLUS_PLUS> {operator = OperatorIds.PLUS_PLUS;}
1724 token = <MINUS_MINUS> {operator = OperatorIds.MINUS_MINUS;}
1726 expr = PrimaryExpression()
1727 {return new PrefixedUnaryExpression(expr,operator,token.sourceStart);}
1730 Expression UnaryExpressionNotPlusMinus() :
1732 final Expression expr;
1735 LOOKAHEAD( <LPAREN> (Type() | <ARRAY>) <RPAREN> )
1736 expr = CastExpression() {return expr;}
1737 | expr = PostfixExpression() {return expr;}
1738 | expr = Literal() {return expr;}
1739 | <LPAREN> expr = Expression()
1742 } catch (ParseException e) {
1743 errorMessage = "')' expected";
1745 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
1746 errorEnd = SimpleCharStream.getPosition() + 1;
1752 CastExpression CastExpression() :
1754 final ConstantIdentifier type;
1755 final Expression expr;
1756 final Token token,token1;
1763 token = <ARRAY> {type = new ConstantIdentifier(token);}
1765 <RPAREN> expr = UnaryExpression()
1766 {return new CastExpression(type,expr,token1.sourceStart,expr.sourceEnd);}
1769 Expression PostfixExpression() :
1771 final Expression expr;
1776 expr = PrimaryExpression()
1778 token = <PLUS_PLUS> {operator = OperatorIds.PLUS_PLUS;}
1780 token = <MINUS_MINUS> {operator = OperatorIds.MINUS_MINUS;}
1783 if (operator == -1) {
1786 return new PostfixedUnaryExpression(expr,operator,token.sourceEnd);
1790 Expression PrimaryExpression() :
1796 [token = <BIT_AND>] expr = refPrimaryExpression(token)
1799 expr = ArrayDeclarator()
1803 Expression refPrimaryExpression(final Token reference) :
1806 Expression expr2 = null;
1807 final Token identifier;
1810 identifier = <IDENTIFIER>
1812 expr = new ConstantIdentifier(identifier);
1815 <STATICCLASSACCESS> expr2 = ClassIdentifier()
1816 {expr = new ClassAccess(expr,
1818 ClassAccess.STATIC);}
1820 [ expr2 = Arguments(expr) ]
1822 if (expr2 == null) {
1823 if (reference != null) {
1824 ParseException e = generateParseException();
1825 errorMessage = "you cannot use a constant by reference";
1827 errorStart = reference.sourceStart;
1828 errorEnd = reference.sourceEnd;
1829 processParseExceptionDebug(e);
1836 expr = VariableDeclaratorId() //todo use the reference parameter ...
1837 [ expr = Arguments(expr) ]
1841 expr = ClassIdentifier()
1844 if (reference == null) {
1845 start = token.sourceStart;
1847 start = reference.sourceStart;
1849 expr = new ClassInstantiation(expr,
1853 [ expr = Arguments(expr) ]
1858 * An array declarator.
1862 ArrayInitializer ArrayDeclarator() :
1864 final ArrayVariableDeclaration[] vars;
1868 token = <ARRAY> vars = ArrayInitializer()
1869 {return new ArrayInitializer(vars,token.sourceStart,SimpleCharStream.getPosition());}
1872 Expression ClassIdentifier():
1874 final Expression expr;
1878 token = <IDENTIFIER> {return new ConstantIdentifier(token);}
1879 | expr = Type() {return expr;}
1880 | expr = VariableDeclaratorId() {return expr;}
1884 * Used by Variabledeclaratorid and primarysuffix
1886 AbstractVariable VariableSuffix(final AbstractVariable prefix) :
1888 Expression expression = null;
1889 final Token classAccessToken;
1892 classAccessToken = <CLASSACCESS>
1894 ( expression = VariableName() | expression = Variable() )
1895 } catch (ParseException e) {
1896 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function call or field access expected";
1898 errorStart = classAccessToken.sourceEnd +1;
1899 errorEnd = classAccessToken.sourceEnd +1;
1900 processParseExceptionDebug(e);
1902 {return new ClassAccess(prefix,
1904 ClassAccess.NORMAL);}
1906 <LBRACKET> [ expression = Expression() | expression = Type() ] //Not good
1909 } catch (ParseException e) {
1910 errorMessage = "']' expected";
1912 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
1913 errorEnd = SimpleCharStream.getPosition() + 1;
1916 {return new ArrayDeclarator(prefix,expression,SimpleCharStream.getPosition());}
1924 token = <INTEGER_LITERAL> {return new NumberLiteral(token);}
1925 | token = <FLOATING_POINT_LITERAL> {return new NumberLiteral(token);}
1926 | token = <STRING_LITERAL> {return new StringLiteral(token);}
1927 | token = <TRUE> {return new TrueLiteral(token);}
1928 | token = <FALSE> {return new FalseLiteral(token);}
1929 | token = <NULL> {return new NullLiteral(token);}
1932 FunctionCall Arguments(final Expression func) :
1934 Expression[] args = null;
1938 <LPAREN> [ args = ArgumentList() ]
1941 } catch (ParseException e) {
1942 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected to close the argument list";
1944 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
1945 errorEnd = SimpleCharStream.getPosition() + 1;
1948 {return new FunctionCall(func,args,token.sourceEnd);}
1952 * An argument list is a list of arguments separated by comma :
1953 * argumentDeclaration() (, argumentDeclaration)*
1954 * @return an array of arguments
1956 Expression[] ArgumentList() :
1959 final ArrayList list = new ArrayList();
1968 } catch (ParseException e) {
1969 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. An expression expected after a comma in argument list";
1971 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
1972 errorEnd = SimpleCharStream.getPosition() + 1;
1977 final Expression[] arguments = new Expression[list.size()];
1978 list.toArray(arguments);
1983 * A Statement without break.
1984 * @return a statement
1986 Statement StatementNoBreak() :
1988 final Statement statement;
1993 statement = expressionStatement() {return statement;}
1995 statement = LabeledStatement() {return statement;}
1996 | statement = Block() {return statement;}
1997 | statement = EmptyStatement() {return statement;}
1998 | statement = SwitchStatement() {return statement;}
1999 | statement = IfStatement() {return statement;}
2000 | statement = WhileStatement() {return statement;}
2001 | statement = DoStatement() {return statement;}
2002 | statement = ForStatement() {return statement;}
2003 | statement = ForeachStatement() {return statement;}
2004 | statement = ContinueStatement() {return statement;}
2005 | statement = ReturnStatement() {return statement;}
2006 | statement = EchoStatement() {return statement;}
2007 | [token=<AT>] statement = IncludeStatement()
2008 {if (token != null) {
2009 ((InclusionStatement)statement).silent = true;
2010 statement.sourceStart = token.sourceStart;
2013 | statement = StaticStatement() {return statement;}
2014 | statement = GlobalStatement() {return statement;}
2015 | statement = defineStatement() {currentSegment.add((Outlineable)statement);return statement;}
2019 * A statement expression.
2021 * @return an expression
2023 Statement expressionStatement() :
2025 final Statement statement;
2029 statement = Expression()
2032 {statement.sourceEnd = token.sourceEnd;}
2033 } catch (ParseException e) {
2034 if (e.currentToken.next.kind != PHPParserConstants.PHPEND) {
2035 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected";
2037 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2038 errorEnd = SimpleCharStream.getPosition() + 1;
2045 Define defineStatement() :
2047 final int start = SimpleCharStream.getPosition();
2048 Expression defineName,defineValue;
2054 } catch (ParseException e) {
2055 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', '(' expected";
2057 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2058 errorEnd = SimpleCharStream.getPosition() + 1;
2059 processParseExceptionDebug(e);
2062 defineName = Expression()
2063 } catch (ParseException e) {
2064 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', expression expected";
2066 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2067 errorEnd = SimpleCharStream.getPosition() + 1;
2072 } catch (ParseException e) {
2073 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ',' expected";
2075 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2076 errorEnd = SimpleCharStream.getPosition() + 1;
2077 processParseExceptionDebug(e);
2080 defineValue = Expression()
2081 } catch (ParseException e) {
2082 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', expression expected";
2084 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2085 errorEnd = SimpleCharStream.getPosition() + 1;
2090 } catch (ParseException e) {
2091 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected";
2093 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2094 errorEnd = SimpleCharStream.getPosition() + 1;
2095 processParseExceptionDebug(e);
2097 {return new Define(currentSegment,
2101 SimpleCharStream.getPosition());}
2105 * A Normal statement.
2107 Statement Statement() :
2109 final Statement statement;
2112 statement = StatementNoBreak() {return statement;}
2113 | statement = BreakStatement() {return statement;}
2117 * An html block inside a php syntax.
2119 HTMLBlock htmlBlock() :
2121 final int startIndex = nodePtr;
2122 final AstNode[] blockNodes;
2126 <PHPEND> (phpEchoBlock())*
2128 (<PHPSTARTLONG> | <PHPSTARTSHORT>)
2129 } catch (ParseException e) {
2130 errorMessage = "unexpected end of file , '<?php' expected";
2132 errorStart = SimpleCharStream.getPosition();
2133 errorEnd = SimpleCharStream.getPosition();
2137 nbNodes = nodePtr - startIndex;
2138 blockNodes = new AstNode[nbNodes];
2139 System.arraycopy(nodes,startIndex,blockNodes,0,nbNodes);
2140 nodePtr = startIndex;
2141 return new HTMLBlock(blockNodes);}
2145 * An include statement. It's "include" an expression;
2147 InclusionStatement IncludeStatement() :
2149 final Expression expr;
2151 final InclusionStatement inclusionStatement;
2152 final Token token, token2;
2155 ( token = <REQUIRE> {keyword = InclusionStatement.REQUIRE;}
2156 | token = <REQUIRE_ONCE> {keyword = InclusionStatement.REQUIRE_ONCE;}
2157 | token = <INCLUDE> {keyword = InclusionStatement.INCLUDE;}
2158 | token = <INCLUDE_ONCE> {keyword = InclusionStatement.INCLUDE_ONCE;})
2161 } catch (ParseException e) {
2162 if (errorMessage != null) {
2165 errorMessage = "unexpected token '"+ e.currentToken.next.image+"', expression expected";
2167 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2168 errorEnd = SimpleCharStream.getPosition() + 1;
2171 {inclusionStatement = new InclusionStatement(currentSegment,
2175 currentSegment.add(inclusionStatement);
2178 token2 = <SEMICOLON>
2179 } catch (ParseException e) {
2180 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected";
2182 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2183 errorEnd = SimpleCharStream.getPosition() + 1;
2186 {inclusionStatement.sourceEnd = token2.sourceEnd;
2187 return inclusionStatement;}
2190 PrintExpression PrintExpression() :
2192 final Expression expr;
2193 final int pos = SimpleCharStream.getPosition();
2196 <PRINT> expr = Expression() {return new PrintExpression(expr,pos,SimpleCharStream.getPosition());}
2199 ListExpression ListExpression() :
2201 Expression expr = null;
2202 final Expression expression;
2203 final ArrayList list = new ArrayList();
2204 final int pos = SimpleCharStream.getPosition();
2205 final Token listToken;
2211 } catch (ParseException e) {
2212 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', '(' expected";
2214 errorStart = listToken.sourceEnd+1;
2215 errorEnd = listToken.sourceEnd+1;
2216 processParseExceptionDebug(e);
2219 expr = VariableDeclaratorId()
2222 {if (expr == null) list.add(null);}
2226 } catch (ParseException e) {
2227 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ',' expected";
2229 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2230 errorEnd = SimpleCharStream.getPosition() + 1;
2233 [expr = VariableDeclaratorId() {list.add(expr);}]
2237 } catch (ParseException e) {
2238 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected";
2240 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2241 errorEnd = SimpleCharStream.getPosition() + 1;
2244 [ <ASSIGN> expression = Expression()
2246 final AbstractVariable[] vars = new AbstractVariable[list.size()];
2248 return new ListExpression(vars,
2251 SimpleCharStream.getPosition());}
2254 final Variable[] vars = new Variable[list.size()];
2256 return new ListExpression(vars,pos,SimpleCharStream.getPosition());}
2260 * An echo statement.
2261 * echo anyexpression (, otherexpression)*
2263 EchoStatement EchoStatement() :
2265 final ArrayList expressions = new ArrayList();
2268 Token token2 = null;
2271 token = <ECHO> expr = Expression()
2272 {expressions.add(expr);}
2274 <COMMA> expr = Expression()
2275 {expressions.add(expr);}
2278 token2 = <SEMICOLON>
2279 } catch (ParseException e) {
2280 if (e.currentToken.next.kind != 4) {
2281 errorMessage = "';' expected after 'echo' statement";
2283 errorStart = e.currentToken.sourceEnd;
2284 errorEnd = e.currentToken.sourceEnd;
2285 processParseExceptionDebug(e);
2289 final Expression[] exprs = new Expression[expressions.size()];
2290 expressions.toArray(exprs);
2291 if (token2 == null) {
2292 return new EchoStatement(exprs,token.sourceStart, exprs[exprs.length-1].sourceEnd);
2294 return new EchoStatement(exprs,token.sourceStart, token2.sourceEnd);
2298 GlobalStatement GlobalStatement() :
2301 final ArrayList vars = new ArrayList();
2302 final GlobalStatement global;
2303 final Token token, token2;
2314 token2 = <SEMICOLON>
2316 final Variable[] variables = new Variable[vars.size()];
2317 vars.toArray(variables);
2318 global = new GlobalStatement(currentSegment,
2322 currentSegment.add(global);
2324 } catch (ParseException e) {
2325 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. a ';' was expected";
2327 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2328 errorEnd = SimpleCharStream.getPosition() + 1;
2333 StaticStatement StaticStatement() :
2335 final ArrayList vars = new ArrayList();
2336 VariableDeclaration expr;
2337 final Token token, token2;
2340 token = <STATIC> expr = VariableDeclarator() {vars.add(expr);}
2342 <COMMA> expr = VariableDeclarator() {vars.add(expr);}
2345 token2 = <SEMICOLON>
2347 final VariableDeclaration[] variables = new VariableDeclaration[vars.size()];
2348 vars.toArray(variables);
2349 return new StaticStatement(variables,
2352 } catch (ParseException e) {
2353 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. a ';' was expected";
2355 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2356 errorEnd = SimpleCharStream.getPosition() + 1;
2361 LabeledStatement LabeledStatement() :
2364 final Statement statement;
2367 label = <IDENTIFIER> <COLON> statement = Statement()
2368 {return new LabeledStatement(label.image,statement,label.sourceStart,statement.sourceEnd);}
2380 final ArrayList list = new ArrayList();
2381 Statement statement;
2382 final Token token, token2;
2387 } catch (ParseException e) {
2388 errorMessage = "'{' expected";
2390 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2391 errorEnd = SimpleCharStream.getPosition() + 1;
2394 ( statement = BlockStatement() {list.add(statement);}
2395 | statement = htmlBlock() {list.add(statement);})*
2398 } catch (ParseException e) {
2399 errorMessage = "unexpected token : '"+ e.currentToken.image +"', '}' expected";
2401 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2402 errorEnd = SimpleCharStream.getPosition() + 1;
2406 final Statement[] statements = new Statement[list.size()];
2407 list.toArray(statements);
2408 return new Block(statements,token.sourceStart,token2.sourceEnd);}
2411 Statement BlockStatement() :
2413 final Statement statement;
2417 statement = Statement() {if (phpDocument == currentSegment) pushOnAstNodes(statement);
2419 } catch (ParseException e) {
2420 errorMessage = "unexpected token : '"+ e.currentToken.image +"', a statement was expected";
2422 errorStart = e.currentToken.sourceStart;
2423 errorEnd = e.currentToken.sourceEnd;
2426 | statement = ClassDeclaration() {return statement;}
2427 | statement = MethodDeclaration() {if (phpDocument == currentSegment) pushOnAstNodes(statement);
2428 currentSegment.add((MethodDeclaration) statement);
2429 ((MethodDeclaration) statement).analyzeCode();
2434 * A Block statement that will not contain any 'break'
2436 Statement BlockStatementNoBreak() :
2438 final Statement statement;
2441 statement = StatementNoBreak() {return statement;}
2442 | statement = ClassDeclaration() {return statement;}
2443 | statement = MethodDeclaration() {currentSegment.add((MethodDeclaration) statement);
2444 ((MethodDeclaration) statement).analyzeCode();
2449 * used only by ForInit()
2451 Expression[] LocalVariableDeclaration() :
2453 final ArrayList list = new ArrayList();
2459 ( <COMMA> var = Expression() {list.add(var);})*
2461 final Expression[] vars = new Expression[list.size()];
2468 * used only by LocalVariableDeclaration().
2470 VariableDeclaration LocalVariableDeclarator() :
2472 final Variable varName;
2473 Expression initializer = null;
2476 varName = Variable() [ <ASSIGN> initializer = Expression() ]
2478 if (initializer == null) {
2479 return new VariableDeclaration(currentSegment,
2481 varName.sourceStart,
2484 return new VariableDeclaration(currentSegment,
2487 VariableDeclaration.EQUAL,
2488 varName.sourceStart);
2492 EmptyStatement EmptyStatement() :
2498 {return new EmptyStatement(token.sourceStart,token.sourceEnd);}
2502 * used only by StatementExpressionList() which is used only by ForInit() and ForStatement()
2504 Expression StatementExpression() :
2506 final Expression expr;
2509 expr = PreIncDecExpression() {return expr;}
2511 expr = PrimaryExpression()
2512 [ <PLUS_PLUS> {return new PostfixedUnaryExpression(expr,
2513 OperatorIds.PLUS_PLUS,
2514 SimpleCharStream.getPosition());}
2515 | <MINUS_MINUS> {return new PostfixedUnaryExpression(expr,
2516 OperatorIds.MINUS_MINUS,
2517 SimpleCharStream.getPosition());}
2522 SwitchStatement SwitchStatement() :
2524 final Expression variable;
2525 final AbstractCase[] cases;
2526 final int pos = SimpleCharStream.getPosition();
2527 final Token switchToken;
2530 switchToken = <SWITCH>
2533 } catch (ParseException e) {
2534 errorMessage = "'(' expected after 'switch'";
2536 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2537 errorEnd = SimpleCharStream.getPosition() + 1;
2541 variable = Expression()
2542 } catch (ParseException e) {
2543 if (errorMessage != null) {
2546 errorMessage = "expression expected";
2548 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2549 errorEnd = SimpleCharStream.getPosition() + 1;
2554 } catch (ParseException e) {
2555 errorMessage = "')' expected";
2557 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2558 errorEnd = SimpleCharStream.getPosition() + 1;
2561 (cases = switchStatementBrace() | cases = switchStatementColon(switchToken.sourceStart, switchToken.sourceEnd))
2562 {return new SwitchStatement(variable,cases,switchToken.sourceStart,SimpleCharStream.getPosition());}
2565 AbstractCase[] switchStatementBrace() :
2568 final ArrayList cases = new ArrayList();
2572 ( cas = switchLabel0() {cases.add(cas);})*
2576 final AbstractCase[] abcase = new AbstractCase[cases.size()];
2577 cases.toArray(abcase);
2579 } catch (ParseException e) {
2580 errorMessage = "'}' expected";
2582 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2583 errorEnd = SimpleCharStream.getPosition() + 1;
2588 * A Switch statement with : ... endswitch;
2589 * @param start the begin offset of the switch
2590 * @param end the end offset of the switch
2592 AbstractCase[] switchStatementColon(final int start, final int end) :
2595 final ArrayList cases = new ArrayList();
2600 setMarker(fileToParse,
2601 "Ugly syntax detected, you should switch () {...} instead of switch (): ... enswitch;",
2605 "Line " + token.beginLine);
2606 } catch (CoreException e) {
2607 PHPeclipsePlugin.log(e);
2609 ( cas = switchLabel0() {cases.add(cas);})*
2612 } catch (ParseException e) {
2613 errorMessage = "'endswitch' expected";
2615 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2616 errorEnd = SimpleCharStream.getPosition() + 1;
2622 final AbstractCase[] abcase = new AbstractCase[cases.size()];
2623 cases.toArray(abcase);
2625 } catch (ParseException e) {
2626 errorMessage = "';' expected after 'endswitch' keyword";
2628 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2629 errorEnd = SimpleCharStream.getPosition() + 1;
2634 AbstractCase switchLabel0() :
2636 final Expression expr;
2637 Statement statement;
2638 final ArrayList stmts = new ArrayList();
2639 final int pos = SimpleCharStream.getPosition();
2642 expr = SwitchLabel()
2643 ( statement = BlockStatementNoBreak() {stmts.add(statement);}
2644 | statement = htmlBlock() {stmts.add(statement);})*
2645 [ statement = BreakStatement() {stmts.add(statement);}]
2647 final Statement[] stmtsArray = new Statement[stmts.size()];
2648 stmts.toArray(stmtsArray);
2649 if (expr == null) {//it's a default
2650 return new DefaultCase(stmtsArray,pos,SimpleCharStream.getPosition());
2652 return new Case(expr,stmtsArray,pos,SimpleCharStream.getPosition());}
2657 * case Expression() :
2659 * @return the if it was a case and null if not
2661 Expression SwitchLabel() :
2663 final Expression expr;
2669 } catch (ParseException e) {
2670 if (errorMessage != null) throw e;
2671 errorMessage = "expression expected after 'case' keyword";
2673 errorStart = token.sourceEnd +1;
2674 errorEnd = token.sourceEnd +1;
2680 } catch (ParseException e) {
2681 errorMessage = "':' expected after case expression";
2683 errorStart = expr.sourceEnd+1;
2684 errorEnd = expr.sourceEnd+1;
2685 processParseExceptionDebug(e);
2692 } catch (ParseException e) {
2693 errorMessage = "':' expected after 'default' keyword";
2695 errorStart = token.sourceEnd+1;
2696 errorEnd = token.sourceEnd+1;
2697 processParseExceptionDebug(e);
2701 Break BreakStatement() :
2703 Expression expression = null;
2704 final Token token, token2;
2707 token = <BREAK> [ expression = Expression() ]
2709 token2 = <SEMICOLON>
2710 } catch (ParseException e) {
2711 errorMessage = "';' expected after 'break' keyword";
2713 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2714 errorEnd = SimpleCharStream.getPosition() + 1;
2717 {return new Break(expression, token.sourceStart, token2.sourceEnd);}
2720 IfStatement IfStatement() :
2722 final Expression condition;
2723 final IfStatement ifStatement;
2727 token = <IF> condition = Condition("if")
2728 ifStatement = IfStatement0(condition,token.sourceStart,token.sourceEnd)
2729 {return ifStatement;}
2733 Expression Condition(final String keyword) :
2735 final Expression condition;
2740 } catch (ParseException e) {
2741 errorMessage = "'(' expected after " + keyword + " keyword";
2743 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length();
2744 errorEnd = errorStart +1;
2745 processParseExceptionDebug(e);
2747 condition = Expression()
2750 } catch (ParseException e) {
2751 errorMessage = "')' expected after " + keyword + " keyword";
2753 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2754 errorEnd = SimpleCharStream.getPosition() + 1;
2755 processParseExceptionDebug(e);
2760 IfStatement IfStatement0(final Expression condition, final int start,final int end) :
2762 Statement statement;
2763 final Statement stmt;
2764 final Statement[] statementsArray;
2765 ElseIf elseifStatement;
2766 Else elseStatement = null;
2767 final ArrayList stmts;
2768 final ArrayList elseIfList = new ArrayList();
2769 final ElseIf[] elseIfs;
2770 int pos = SimpleCharStream.getPosition();
2771 final int endStatements;
2775 {stmts = new ArrayList();}
2776 ( statement = Statement() {stmts.add(statement);}
2777 | statement = htmlBlock() {stmts.add(statement);})*
2778 {endStatements = SimpleCharStream.getPosition();}
2779 (elseifStatement = ElseIfStatementColon() {elseIfList.add(elseifStatement);})*
2780 [elseStatement = ElseStatementColon()]
2783 setMarker(fileToParse,
2784 "Ugly syntax detected, you should if () {...} instead of if (): ... endif;",
2788 "Line " + token.beginLine);
2789 } catch (CoreException e) {
2790 PHPeclipsePlugin.log(e);
2794 } catch (ParseException e) {
2795 errorMessage = "'endif' expected";
2797 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2798 errorEnd = SimpleCharStream.getPosition() + 1;
2803 } catch (ParseException e) {
2804 errorMessage = "';' expected after 'endif' keyword";
2806 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2807 errorEnd = SimpleCharStream.getPosition() + 1;
2811 elseIfs = new ElseIf[elseIfList.size()];
2812 elseIfList.toArray(elseIfs);
2813 if (stmts.size() == 1) {
2814 return new IfStatement(condition,
2815 (Statement) stmts.get(0),
2819 SimpleCharStream.getPosition());
2821 statementsArray = new Statement[stmts.size()];
2822 stmts.toArray(statementsArray);
2823 return new IfStatement(condition,
2824 new Block(statementsArray,pos,endStatements),
2828 SimpleCharStream.getPosition());
2833 (stmt = Statement() | stmt = htmlBlock())
2834 ( LOOKAHEAD(1) elseifStatement = ElseIfStatement() {elseIfList.add(elseifStatement);})*
2838 {pos = SimpleCharStream.getPosition();}
2839 statement = Statement()
2840 {elseStatement = new Else(statement,pos,SimpleCharStream.getPosition());}
2841 } catch (ParseException e) {
2842 if (errorMessage != null) {
2845 errorMessage = "unexpected token '"+e.currentToken.next.image+"', a statement was expected";
2847 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2848 errorEnd = SimpleCharStream.getPosition() + 1;
2853 elseIfs = new ElseIf[elseIfList.size()];
2854 elseIfList.toArray(elseIfs);
2855 return new IfStatement(condition,
2860 SimpleCharStream.getPosition());}
2863 ElseIf ElseIfStatementColon() :
2865 final Expression condition;
2866 Statement statement;
2867 final ArrayList list = new ArrayList();
2868 final int pos = SimpleCharStream.getPosition();
2871 <ELSEIF> condition = Condition("elseif")
2872 <COLON> ( statement = Statement() {list.add(statement);}
2873 | statement = htmlBlock() {list.add(statement);})*
2875 final Statement[] stmtsArray = new Statement[list.size()];
2876 list.toArray(stmtsArray);
2877 return new ElseIf(condition,stmtsArray ,pos,SimpleCharStream.getPosition());}
2880 Else ElseStatementColon() :
2882 Statement statement;
2883 final ArrayList list = new ArrayList();
2884 final int pos = SimpleCharStream.getPosition();
2887 <ELSE> <COLON> ( statement = Statement() {list.add(statement);}
2888 | statement = htmlBlock() {list.add(statement);})*
2890 final Statement[] stmtsArray = new Statement[list.size()];
2891 list.toArray(stmtsArray);
2892 return new Else(stmtsArray,pos,SimpleCharStream.getPosition());}
2895 ElseIf ElseIfStatement() :
2897 final Expression condition;
2898 final Statement statement;
2899 final ArrayList list = new ArrayList();
2900 final int pos = SimpleCharStream.getPosition();
2903 <ELSEIF> condition = Condition("elseif") statement = Statement() {list.add(statement);/*todo:do better*/}
2905 final Statement[] stmtsArray = new Statement[list.size()];
2906 list.toArray(stmtsArray);
2907 return new ElseIf(condition,stmtsArray,pos,SimpleCharStream.getPosition());}
2910 WhileStatement WhileStatement() :
2912 final Expression condition;
2913 final Statement action;
2914 final int pos = SimpleCharStream.getPosition();
2918 condition = Condition("while")
2919 action = WhileStatement0(pos,pos + 5)
2920 {return new WhileStatement(condition,action,pos,SimpleCharStream.getPosition());}
2923 Statement WhileStatement0(final int start, final int end) :
2925 Statement statement;
2926 final ArrayList stmts = new ArrayList();
2927 final int pos = SimpleCharStream.getPosition();
2930 <COLON> (statement = Statement() {stmts.add(statement);})*
2932 setMarker(fileToParse,
2933 "Ugly syntax detected, you should while () {...} instead of while (): ... endwhile;",
2937 "Line " + token.beginLine);
2938 } catch (CoreException e) {
2939 PHPeclipsePlugin.log(e);
2943 } catch (ParseException e) {
2944 errorMessage = "'endwhile' expected";
2946 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2947 errorEnd = SimpleCharStream.getPosition() + 1;
2953 final Statement[] stmtsArray = new Statement[stmts.size()];
2954 stmts.toArray(stmtsArray);
2955 return new Block(stmtsArray,pos,SimpleCharStream.getPosition());}
2956 } catch (ParseException e) {
2957 errorMessage = "';' expected after 'endwhile' keyword";
2959 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2960 errorEnd = SimpleCharStream.getPosition() + 1;
2964 statement = Statement()
2968 DoStatement DoStatement() :
2970 final Statement action;
2971 final Expression condition;
2972 final Token token, token2;
2975 token = <DO> action = Statement() <WHILE> condition = Condition("while")
2977 token2 = <SEMICOLON>
2978 {return new DoStatement(condition,action,token.sourceStart,token2.sourceEnd);}
2979 } catch (ParseException e) {
2980 errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected";
2982 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
2983 errorEnd = SimpleCharStream.getPosition() + 1;
2988 ForeachStatement ForeachStatement() :
2990 Statement statement;
2991 Expression expression;
2992 ArrayVariableDeclaration variable;
2999 } catch (ParseException e) {
3000 errorMessage = "'(' expected after 'foreach' keyword";
3002 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
3003 errorEnd = SimpleCharStream.getPosition() + 1;
3007 expression = Expression()
3008 } catch (ParseException e) {
3009 errorMessage = "variable expected";
3011 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
3012 errorEnd = SimpleCharStream.getPosition() + 1;
3017 } catch (ParseException e) {
3018 errorMessage = "'as' expected";
3020 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
3021 errorEnd = SimpleCharStream.getPosition() + 1;
3025 variable = ArrayVariable()
3026 } catch (ParseException e) {
3027 errorMessage = "variable expected";
3029 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
3030 errorEnd = SimpleCharStream.getPosition() + 1;
3035 } catch (ParseException e) {
3036 errorMessage = "')' expected after 'foreach' keyword";
3038 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
3039 errorEnd = SimpleCharStream.getPosition() + 1;
3043 statement = Statement()
3044 } catch (ParseException e) {
3045 if (errorMessage != null) throw e;
3046 errorMessage = "statement expected";
3048 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
3049 errorEnd = SimpleCharStream.getPosition() + 1;
3052 {return new ForeachStatement(expression,
3056 statement.sourceEnd);}
3061 * a for declaration.
3062 * @return a node representing the for statement
3064 ForStatement ForStatement() :
3066 final Token token,token2;
3067 final int pos = SimpleCharStream.getPosition();
3068 Expression[] initializations = null;
3069 Expression condition = null;
3070 Expression[] increments = null;
3072 final ArrayList list = new ArrayList();
3078 } catch (ParseException e) {
3079 errorMessage = "'(' expected after 'for' keyword";
3081 errorStart = token.sourceEnd;
3082 errorEnd = token.sourceEnd +1;
3083 processParseExceptionDebug(e);
3085 [ initializations = ForInit() ] <SEMICOLON>
3086 [ condition = Expression() ] <SEMICOLON>
3087 [ increments = StatementExpressionList() ] <RPAREN>
3089 action = Statement()
3090 {return new ForStatement(initializations,
3098 (action = Statement() {list.add(action);})*
3101 setMarker(fileToParse,
3102 "Ugly syntax detected, you should for () {...} instead of for (): ... endfor;",
3106 "Line " + token.beginLine);
3107 } catch (CoreException e) {
3108 PHPeclipsePlugin.log(e);
3113 } catch (ParseException e) {
3114 errorMessage = "'endfor' expected";
3116 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
3117 errorEnd = SimpleCharStream.getPosition() + 1;
3121 token2 = <SEMICOLON>
3123 final Statement[] stmtsArray = new Statement[list.size()];
3124 list.toArray(stmtsArray);
3125 return new ForStatement(initializations,
3128 new Block(stmtsArray,
3129 stmtsArray[0].sourceStart,
3130 stmtsArray[stmtsArray.length-1].sourceEnd),
3133 } catch (ParseException e) {
3134 errorMessage = "';' expected after 'endfor' keyword";
3136 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
3137 errorEnd = SimpleCharStream.getPosition() + 1;
3143 Expression[] ForInit() :
3145 final Expression[] exprs;
3148 LOOKAHEAD(LocalVariableDeclaration())
3149 exprs = LocalVariableDeclaration()
3152 exprs = StatementExpressionList()
3156 Expression[] StatementExpressionList() :
3158 final ArrayList list = new ArrayList();
3159 final Expression expr;
3162 expr = Expression() {list.add(expr);}
3163 (<COMMA> Expression() {list.add(expr);})*
3165 final Expression[] exprsArray = new Expression[list.size()];
3166 list.toArray(exprsArray);
3171 Continue ContinueStatement() :
3173 Expression expr = null;
3174 final Token token,token2;
3177 token = <CONTINUE> [ expr = Expression() ]
3179 token2 = <SEMICOLON>
3180 {return new Continue(expr,token.sourceStart,token2.sourceEnd);}
3181 } catch (ParseException e) {
3182 errorMessage = "';' expected after 'continue' statement";
3184 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
3185 errorEnd = SimpleCharStream.getPosition() + 1;
3190 ReturnStatement ReturnStatement() :
3192 Expression expr = null;
3193 final Token token,token2;
3196 token = <RETURN> [ expr = Expression() ]
3198 token2 = <SEMICOLON>
3199 {return new ReturnStatement(expr,token.sourceStart,token2.sourceEnd);}
3200 } catch (ParseException e) {
3201 errorMessage = "';' expected after 'return' statement";
3203 errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1;
3204 errorEnd = SimpleCharStream.getPosition() + 1;