3 CHOICE_AMBIGUITY_CHECK = 2;
4 OTHER_AMBIGUITY_CHECK = 1;
7 DEBUG_LOOKAHEAD = false;
8 DEBUG_TOKEN_MANAGER = false;
9 OPTIMIZE_TOKEN_MANAGER = false;
10 ERROR_REPORTING = true;
11 JAVA_UNICODE_ESCAPE = false;
12 UNICODE_INPUT = false;
14 USER_TOKEN_MANAGER = false;
15 USER_CHAR_STREAM = false;
17 BUILD_TOKEN_MANAGER = true;
19 FORCE_LA_CHECK = false;
22 PARSER_BEGIN(PHPParser)
25 import org.eclipse.core.resources.IFile;
26 import org.eclipse.core.resources.IMarker;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.ui.texteditor.MarkerUtilities;
29 import org.eclipse.jface.preference.IPreferenceStore;
31 import java.util.Hashtable;
32 import java.io.StringReader;
33 import java.text.MessageFormat;
35 import net.sourceforge.phpeclipse.actions.PHPStartApacheAction;
36 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
37 import net.sourceforge.phpdt.internal.compiler.parser.PHPOutlineInfo;
38 import net.sourceforge.phpdt.internal.compiler.parser.PHPSegmentWithChildren;
39 import net.sourceforge.phpdt.internal.compiler.parser.PHPFunctionDeclaration;
40 import net.sourceforge.phpdt.internal.compiler.parser.PHPClassDeclaration;
41 import net.sourceforge.phpdt.internal.compiler.parser.PHPVarDeclaration;
42 import net.sourceforge.phpdt.internal.compiler.parser.PHPReqIncDeclaration;
46 * This php parser is inspired by the Java 1.2 grammar example
47 * given with JavaCC. You can get JavaCC at http://www.webgain.com
48 * You can test the parser with the PHPParserTestCase2.java
49 * @author Matthieu Casanova
51 public class PHPParser extends PHPParserSuperclass {
53 private static IFile fileToParse;
55 /** The current segment */
56 private static PHPSegmentWithChildren currentSegment;
58 private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$
59 private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$
60 PHPOutlineInfo outlineInfo;
61 private static int errorLevel = ERROR;
62 private static String errorMessage;
67 public void setFileToParse(IFile fileToParse) {
68 this.fileToParse = fileToParse;
71 public PHPParser(IFile fileToParse) {
72 this(new StringReader(""));
73 this.fileToParse = fileToParse;
76 public void phpParserTester(String strEval) throws CoreException, ParseException {
77 PHPParserTokenManager.SwitchTo(PHPParserTokenManager.PHPPARSING);
78 StringReader stream = new StringReader(strEval);
79 if (jj_input_stream == null) {
80 jj_input_stream = new SimpleCharStream(stream, 1, 1);
82 ReInit(new StringReader(strEval));
86 public void htmlParserTester(String strEval) throws CoreException, ParseException {
87 StringReader stream = new StringReader(strEval);
88 if (jj_input_stream == null) {
89 jj_input_stream = new SimpleCharStream(stream, 1, 1);
95 public PHPOutlineInfo parseInfo(Object parent, String s) {
96 outlineInfo = new PHPOutlineInfo(parent);
97 currentSegment = outlineInfo.getDeclarations();
98 StringReader stream = new StringReader(s);
99 if (jj_input_stream == null) {
100 jj_input_stream = new SimpleCharStream(stream, 1, 1);
105 } catch (ParseException e) {
106 processParseException(e);
112 * This method will process the parse exception.
113 * If the error message is null, the parse exception wasn't catched and a trace is written in the log
114 * @param e the ParseException
116 private static void processParseException(final ParseException e) {
117 if (errorMessage == null) {
118 PHPeclipsePlugin.log(e);
119 errorMessage = "this exception wasn't handled by the parser please tell us how to reproduce it";
126 * Create marker for the parse error
128 private static void setMarker(ParseException e) {
130 setMarker(fileToParse, errorMessage, jj_input_stream.tokenBegin,jj_input_stream.tokenBegin+e.currentToken.image.length(), errorLevel);
131 } catch (CoreException e2) {
132 PHPeclipsePlugin.log(e2);
137 * Create markers according to the external parser output
139 private static void createMarkers(String output, IFile file) throws CoreException {
140 // delete all markers
141 file.deleteMarkers(IMarker.PROBLEM, false, 0);
146 while ((brIndx = output.indexOf("<br />", indx)) != -1) {
147 // newer php error output (tested with 4.2.3)
148 scanLine(output, file, indx, brIndx);
153 while ((brIndx = output.indexOf("<br>", indx)) != -1) {
154 // older php error output (tested with 4.2.3)
155 scanLine(output, file, indx, brIndx);
161 private static void scanLine(String output, IFile file, int indx, int brIndx) throws CoreException {
163 StringBuffer lineNumberBuffer = new StringBuffer(10);
165 current = output.substring(indx, brIndx);
167 if (current.indexOf(PARSE_WARNING_STRING) != -1 || current.indexOf(PARSE_ERROR_STRING) != -1) {
168 int onLine = current.indexOf("on line <b>");
170 lineNumberBuffer.delete(0, lineNumberBuffer.length());
171 for (int i = onLine; i < current.length(); i++) {
172 ch = current.charAt(i);
173 if ('0' <= ch && '9' >= ch) {
174 lineNumberBuffer.append(ch);
178 int lineNumber = Integer.parseInt(lineNumberBuffer.toString());
180 Hashtable attributes = new Hashtable();
182 current = current.replaceAll("\n", "");
183 current = current.replaceAll("<b>", "");
184 current = current.replaceAll("</b>", "");
185 MarkerUtilities.setMessage(attributes, current);
187 if (current.indexOf(PARSE_ERROR_STRING) != -1)
188 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
189 else if (current.indexOf(PARSE_WARNING_STRING) != -1)
190 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
192 attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
193 MarkerUtilities.setLineNumber(attributes, lineNumber);
194 MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
199 public void parse(String s) throws CoreException {
200 ReInit(new StringReader(s));
203 } catch (ParseException e) {
204 processParseException(e);
209 * Call the php parse command ( php -l -f <filename> )
210 * and create markers according to the external parser output
212 public static void phpExternalParse(IFile file) {
213 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
214 String filename = file.getLocation().toString();
216 String[] arguments = { filename };
217 MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF));
218 String command = form.format(arguments);
220 String parserResult = PHPStartApacheAction.getParserOutput(command, "External parser: ");
223 // parse the buffer to find the errors and warnings
224 createMarkers(parserResult, file);
225 } catch (CoreException e) {
226 PHPeclipsePlugin.log(e);
230 public void parse() throws ParseException {
235 PARSER_END(PHPParser)
239 <PHPSTART : "<?php" | "<?"> : PHPPARSING
244 <PHPEND :"?>"> : DEFAULT
268 "//" : IN_SINGLE_LINE_COMMENT
270 <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
272 "/*" : IN_MULTI_LINE_COMMENT
275 <IN_SINGLE_LINE_COMMENT>
278 <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" | "?>" > : PHPPARSING
284 <FORMAL_COMMENT: "*/" > : PHPPARSING
287 <IN_MULTI_LINE_COMMENT>
290 <MULTI_LINE_COMMENT: "*/" > : PHPPARSING
293 <IN_SINGLE_LINE_COMMENT,IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT>
303 | <FUNCTION : "function">
306 | <ELSEIF : "elseif">
311 /* LANGUAGE CONSTRUCT */
316 | <INCLUDE : "include">
317 | <REQUIRE : "require">
318 | <INCLUDE_ONCE : "include_once">
319 | <REQUIRE_ONCE : "require_once">
320 | <GLOBAL : "global">
321 | <STATIC : "static">
322 | <CLASSACCESS: "->">
323 | <STATICCLASSACCESS: "::">
324 | <ARRAYASSIGN: "=>">
327 /* RESERVED WORDS AND LITERALS */
334 | < CONTINUE: "continue" >
335 | < _DEFAULT: "default" >
337 | < EXTENDS: "extends" >
343 | < RETURN: "return" >
345 | < SWITCH: "switch" >
349 | < ENDWHILE : "endwhile" >
357 | <OBJECT : "object">
359 | <BOOLEAN : "boolean">
361 | <DOUBLE : "double">
364 | <INTEGER : "integer">
378 <DECIMAL_LITERAL> (["l","L"])?
379 | <HEX_LITERAL> (["l","L"])?
380 | <OCTAL_LITERAL> (["l","L"])?
383 < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
385 < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
387 < #OCTAL_LITERAL: "0" (["0"-"7"])* >
389 < FLOATING_POINT_LITERAL:
390 (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?
391 | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
392 | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
393 | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]
396 < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
398 < STRING_LITERAL: (<STRING_1> | <STRING_2> | <STRING_3>)>
423 < IDENTIFIER: (<LETTER>|<SPECIAL>) (<LETTER>|<DIGIT>|<SPECIAL>)* >
426 ["a"-"z"] | ["A"-"Z"]
482 | < RSIGNEDSHIFT: ">>" >
483 | < RUNSIGNEDSHIFT: ">>>" >
484 | < PLUSASSIGN: "+=" >
485 | < MINUSASSIGN: "-=" >
486 | < STARASSIGN: "*=" >
487 | < SLASHASSIGN: "/=" >
488 | < ANDASSIGN: "&=" >
490 | < XORASSIGN: "^=" >
491 | < DOTASSIGN: ".=" >
492 | < REMASSIGN: "%=" >
493 | < LSHIFTASSIGN: "<<=" >
494 | < RSIGNEDSHIFTASSIGN: ">>=" >
495 | < RUNSIGNEDSHIFTASSIGN: ">>>=" >
500 < DOLLAR_ID: <DOLLAR> <IDENTIFIER> >
503 /*****************************************
504 * THE JAVA LANGUAGE GRAMMAR STARTS HERE *
505 *****************************************/
508 * Program structuring syntax follows.
521 (<PHPSTART> Php() <PHPEND>)*
531 void ClassDeclaration() :
533 PHPClassDeclaration classDeclaration;
535 int pos = jj_input_stream.bufpos;
538 <CLASS> className = <IDENTIFIER> [ <EXTENDS> <IDENTIFIER> ]
540 classDeclaration = new PHPClassDeclaration(currentSegment,className.image,pos);
541 currentSegment.add(classDeclaration);
542 currentSegment = classDeclaration;
546 currentSegment = (PHPSegmentWithChildren) currentSegment.getParent();
555 } catch (ParseException e) {
556 errorMessage = "'{' expected";
560 ( ClassBodyDeclaration() )*
563 } catch (ParseException e) {
564 errorMessage = "'var', 'function' or '}' expected";
570 void ClassBodyDeclaration() :
578 void FieldDeclaration() :
580 PHPVarDeclaration variableDeclaration;
583 <VAR> variableDeclaration = VariableDeclarator()
584 {currentSegment.add(variableDeclaration);}
586 variableDeclaration = VariableDeclarator()
587 {currentSegment.add(variableDeclaration);}
591 } catch (ParseException e) {
592 errorMessage = "';' expected after variable declaration";
598 PHPVarDeclaration VariableDeclarator() :
601 String varValue = null;
605 varName = VariableDeclaratorId()
606 {pos = jj_input_stream.tokenBegin;}
610 varValue = VariableInitializer()
611 } catch (ParseException e) {
612 errorMessage = "Literal expression expected in variable initializer";
618 if (varValue == null) {
619 return new PHPVarDeclaration(currentSegment,varName,pos);
621 return new PHPVarDeclaration(currentSegment,varName,pos,varValue);
625 String VariableDeclaratorId() :
628 StringBuffer buff = new StringBuffer();
634 ( LOOKAHEAD(2) expr = VariableSuffix()
637 {return buff.toString();}
638 } catch (ParseException e) {
639 errorMessage = "'$' expected for variable identifier";
651 token = <DOLLAR_ID> [<LBRACE> expr = Expression() <RBRACE>]
656 return token + "{" + expr + "}";
659 <DOLLAR> expr = VariableName()
663 String VariableName():
669 <LBRACE> expr = Expression() <RBRACE>
670 {return "{"+expr+"}";}
672 token = <IDENTIFIER> [<LBRACE> expr = Expression() <RBRACE>]
677 return token + "{" + expr + "}";
680 <DOLLAR> expr = VariableName()
683 token = <DOLLAR_ID> [expr = VariableName()]
688 return token.image + expr;
692 String VariableInitializer() :
701 String ArrayVariable() :
704 StringBuffer buff = new StringBuffer();
709 [<ARRAYASSIGN> expr = Expression()
710 {buff.append("=>").append(expr);}]
711 {return buff.toString();}
714 String ArrayInitializer() :
717 StringBuffer buff = new StringBuffer("(");
720 <LPAREN> [ expr = ArrayVariable()
722 ( LOOKAHEAD(2) <COMMA> expr = ArrayVariable()
723 {buff.append(",").append(expr);}
728 return buff.toString();
732 void MethodDeclaration() :
734 PHPFunctionDeclaration functionDeclaration;
737 <FUNCTION> functionDeclaration = MethodDeclarator()
739 currentSegment.add(functionDeclaration);
740 currentSegment = functionDeclaration;
744 currentSegment = (PHPSegmentWithChildren) currentSegment.getParent();
748 PHPFunctionDeclaration MethodDeclarator() :
751 StringBuffer methodDeclaration = new StringBuffer();
752 String formalParameters;
753 int pos = jj_input_stream.bufpos;
756 [ <BIT_AND> {methodDeclaration.append("&");} ]
757 identifier = <IDENTIFIER>
758 {methodDeclaration.append(identifier);}
759 formalParameters = FormalParameters()
761 methodDeclaration.append(formalParameters);
762 return new PHPFunctionDeclaration(currentSegment,methodDeclaration.toString(),pos);
766 String FormalParameters() :
769 final StringBuffer buff = new StringBuffer("(");
774 } catch (ParseException e) {
775 errorMessage = "Formal parameter expected after function identifier";
777 jj_consume_token(token.kind);
779 [ expr = FormalParameter()
782 <COMMA> expr = FormalParameter()
783 {buff.append(",").append(expr);}
788 } catch (ParseException e) {
789 errorMessage = "')' expected";
795 return buff.toString();
799 String FormalParameter() :
801 PHPVarDeclaration variableDeclaration;
802 StringBuffer buff = new StringBuffer();
805 [<BIT_AND> {buff.append("&");}] variableDeclaration = VariableDeclarator()
807 buff.append(variableDeclaration.toString());
808 return buff.toString();
840 String Expression() :
843 String assignOperator = null;
847 expr = PrintExpression()
850 expr = ConditionalExpression()
852 assignOperator = AssignmentOperator()
859 return expr + assignOperator + expr2;
864 String AssignmentOperator() :
866 Token assignOperator;
883 | <RSIGNEDSHIFTASSIGN>
885 | <RUNSIGNEDSHIFTASSIGN>
897 String ConditionalExpression() :
904 expr = ConditionalOrExpression() [ <HOOK> expr2 = Expression() <COLON> expr3 = ConditionalExpression() ]
909 return expr + "?" + expr2 + ":" + expr3;
914 String ConditionalOrExpression() :
919 StringBuffer buff = new StringBuffer();
922 expr = ConditionalAndExpression()
927 (operator = <SC_OR> | operator = <_ORL>) expr2 = ConditionalAndExpression()
929 buff.append(operator.image);
934 return buff.toString();
938 String ConditionalAndExpression() :
943 StringBuffer buff = new StringBuffer();
946 expr = ConcatExpression()
951 (operator = <SC_AND> | operator = <_ANDL>) expr2 = ConcatExpression()
953 buff.append(operator.image);
958 return buff.toString();
962 String ConcatExpression() :
966 StringBuffer buff = new StringBuffer();
969 expr = InclusiveOrExpression()
974 <DOT> expr2 = InclusiveOrExpression()
981 return buff.toString();
985 String InclusiveOrExpression() :
989 StringBuffer buff = new StringBuffer();
992 expr = ExclusiveOrExpression()
997 <BIT_OR> expr2 = ExclusiveOrExpression()
1004 return buff.toString();
1008 String ExclusiveOrExpression() :
1011 String expr2 = null;
1012 StringBuffer buff = new StringBuffer();
1015 expr = AndExpression()
1020 <XOR> expr2 = AndExpression()
1027 return buff.toString();
1031 String AndExpression() :
1034 String expr2 = null;
1035 StringBuffer buff = new StringBuffer();
1038 expr = EqualityExpression()
1043 <BIT_AND> expr2 = EqualityExpression()
1050 return buff.toString();
1054 String EqualityExpression() :
1059 StringBuffer buff = new StringBuffer();
1062 expr = RelationalExpression()
1063 {buff.append(expr);}
1065 ( operator = <EQ> | operator = <NE> ) expr2 = RelationalExpression()
1067 buff.append(operator.image);
1071 {return buff.toString();}
1074 String RelationalExpression() :
1079 StringBuffer buff = new StringBuffer();
1082 expr = ShiftExpression()
1083 {buff.append(expr);}
1085 ( operator = <LT> | operator = <GT> | operator = <LE> | operator = <GE> ) expr2 = ShiftExpression()
1087 buff.append(operator.image);
1091 {return buff.toString();}
1094 String ShiftExpression() :
1099 StringBuffer buff = new StringBuffer();
1102 expr = AdditiveExpression()
1103 {buff.append(expr);}
1105 (operator = <LSHIFT> | operator = <RSIGNEDSHIFT> | operator = <RUNSIGNEDSHIFT> ) expr2 = AdditiveExpression()
1107 buff.append(operator.image);
1111 {return buff.toString();}
1114 String AdditiveExpression() :
1119 StringBuffer buff = new StringBuffer();
1122 expr = MultiplicativeExpression()
1123 {buff.append(expr);}
1125 ( operator = <PLUS> | operator = <MINUS> ) expr2 = MultiplicativeExpression()
1127 buff.append(operator.image);
1131 {return buff.toString();}
1134 String MultiplicativeExpression() :
1138 final StringBuffer buff = new StringBuffer();}
1140 expr = UnaryExpression()
1141 {buff.append(expr);}
1143 ( operator = <STAR> | operator = <SLASH> | operator = <REM> ) expr2 = UnaryExpression()
1145 buff.append(operator.image);
1149 {return buff.toString();}
1152 String UnaryExpression() :
1155 final StringBuffer buff = new StringBuffer();
1158 <AT> expr = UnaryExpression()
1159 {return "@" + expr;}
1161 ( <PLUS> {buff.append("+");}| <MINUS> {buff.append("-");}) expr = UnaryExpression()
1164 return buff.toString();
1167 expr = PreIncrementExpression()
1170 expr = PreDecrementExpression()
1173 expr = UnaryExpressionNotPlusMinus()
1177 String PreIncrementExpression() :
1182 <INCR> expr = PrimaryExpression()
1186 String PreDecrementExpression() :
1191 <DECR> expr = PrimaryExpression()
1195 String UnaryExpressionNotPlusMinus() :
1200 <BANG> expr = UnaryExpression()
1201 {return "!" + expr;}
1203 LOOKAHEAD( <LPAREN> Type() <RPAREN> )
1204 expr = CastExpression()
1207 expr = PostfixExpression()
1213 <LPAREN> expr = Expression()<RPAREN>
1214 {return "("+expr+")";}
1217 String CastExpression() :
1223 <LPAREN> type = Type() <RPAREN> expr = UnaryExpression()
1224 {return "(" + type + ")" + expr;}
1227 String PostfixExpression() :
1230 Token operator = null;
1233 expr = PrimaryExpression() [ operator = <INCR> | operator = <DECR> ]
1235 if (operator == null) {
1238 return expr + operator.image;
1242 String PrimaryExpression() :
1246 final StringBuffer buff = new StringBuffer();
1250 identifier = <IDENTIFIER> <STATICCLASSACCESS> expr = ClassIdentifier()
1251 {buff.append(identifier.image).append("::").append(expr);}
1253 expr = PrimarySuffix()
1254 {buff.append(expr);}
1256 {return buff.toString();}
1258 expr = PrimaryPrefix() {buff.append(expr);}
1259 ( expr = PrimarySuffix() {buff.append(expr);} )*
1260 {return buff.toString();}
1262 <ARRAY> expr = ArrayInitializer()
1263 {return "array" + expr;}
1266 String PrimaryPrefix() :
1272 token = <IDENTIFIER>
1273 {return token.image;}
1275 [token = <BIT_AND>] <NEW> expr = ClassIdentifier()
1277 if (token == null) {
1278 return "new " + expr;
1280 return "new &" + expr;
1283 expr = VariableDeclaratorId()
1287 String ClassIdentifier():
1293 token = <IDENTIFIER>
1294 {return token.image;}
1296 expr = VariableDeclaratorId()
1300 String PrimarySuffix() :
1308 expr = VariableSuffix()
1312 String VariableSuffix() :
1317 <CLASSACCESS> expr = VariableName()
1318 {return "->" + expr;}
1320 <LBRACKET> [ expr = Expression() ] <RBRACKET>
1325 return "[" + expr + "]";
1335 token = <INTEGER_LITERAL>
1336 {return token.image;}
1338 token = <FLOATING_POINT_LITERAL>
1339 {return token.image;}
1342 token = <STRING_LITERAL>
1343 {return token.image;}
1344 } catch (TokenMgrError e) {
1345 errorMessage = "unterminated string";
1347 throw generateParseException();
1350 expr = BooleanLiteral()
1353 expr = NullLiteral()
1357 String BooleanLiteral() :
1367 String NullLiteral() :
1374 String Arguments() :
1379 <LPAREN> [ expr = ArgumentList() ]
1382 } catch (ParseException e) {
1383 errorMessage = "')' expected to close the argument list";
1391 return "(" + expr + ")";
1395 String ArgumentList() :
1398 StringBuffer buff = new StringBuffer();
1402 {buff.append(expr);}
1406 } catch (ParseException e) {
1407 errorMessage = "expression expected after a comma in argument list";
1412 buff.append(",").append("expr");
1415 {return buff.toString();}
1419 * Statement syntax follows.
1426 Expression() (<SEMICOLON> | "?>")
1435 StatementExpression()
1438 } catch (ParseException e) {
1439 errorMessage = "';' expected after expression";
1462 [<AT>] IncludeStatement()
1469 void IncludeStatement() :
1477 {pos = token.beginLine;}
1479 {currentSegment.add(new PHPReqIncDeclaration(currentSegment, "require",pos,expr));}
1480 (<SEMICOLON> | "?>")
1482 token = <REQUIRE_ONCE>
1483 {pos = token.beginLine;}
1485 {currentSegment.add(new PHPReqIncDeclaration(currentSegment, "require_once",pos,expr));}
1486 (<SEMICOLON> | "?>")
1489 {pos = token.beginLine;}
1491 {currentSegment.add(new PHPReqIncDeclaration(currentSegment, "include",pos,expr));}
1492 (<SEMICOLON> | "?>")
1494 token = <INCLUDE_ONCE>
1495 {pos = token.beginLine;}
1497 {currentSegment.add(new PHPReqIncDeclaration(currentSegment, "include_once",pos,expr));}
1498 (<SEMICOLON> | "?>")
1501 String PrintExpression() :
1503 StringBuffer buff = new StringBuffer("print ");
1507 <PRINT> expr = Expression()
1510 return buff.toString();
1514 void EchoStatement() :
1517 <ECHO> Expression() (<COMMA> Expression())*
1519 (<SEMICOLON> | "?>")
1520 } catch (ParseException e) {
1521 errorMessage = "';' expected after 'echo' statement";
1527 void GlobalStatement() :
1530 <GLOBAL> VariableDeclaratorId() (<COMMA> VariableDeclaratorId())* (<SEMICOLON> | "?>")
1533 void StaticStatement() :
1536 <STATIC> VariableDeclarator() (<COMMA> VariableDeclarator())* (<SEMICOLON> | "?>")
1539 void LabeledStatement() :
1542 <IDENTIFIER> <COLON> Statement()
1550 } catch (ParseException e) {
1551 errorMessage = "'{' expected";
1555 ( BlockStatement() )*
1559 void BlockStatement() :
1569 void LocalVariableDeclaration() :
1572 VariableDeclarator() ( <COMMA> VariableDeclarator() )*
1575 void EmptyStatement() :
1581 void StatementExpression() :
1583 * The last expansion of this production accepts more than the legal
1584 * Java expansions for StatementExpression. This expansion does not
1585 * use PostfixExpression for performance reasons.
1589 PreIncrementExpression()
1591 PreDecrementExpression()
1599 AssignmentOperator() Expression()
1603 void SwitchStatement() :
1606 <SWITCH> <LPAREN> Expression() <RPAREN> <LBRACE>
1607 ( SwitchLabel() ( BlockStatement() )* )*
1611 void SwitchLabel() :
1614 <CASE> Expression() <COLON>
1619 void IfStatement() :
1621 * The disambiguating algorithm of JavaCC automatically binds dangling
1622 * else's to the innermost if statement. The LOOKAHEAD specification
1623 * is to tell JavaCC that we know what we are doing.
1627 <IF> Condition("if") Statement() ( LOOKAHEAD(1) ElseIfStatement() )* [ LOOKAHEAD(1) <ELSE> Statement() ]
1630 void Condition(String keyword) :
1635 } catch (ParseException e) {
1636 errorMessage = "'(' expected after " + keyword + " keyword";
1643 } catch (ParseException e) {
1644 errorMessage = "')' expected after " + keyword + " keyword";
1650 void ElseIfStatement() :
1653 <ELSEIF> Condition("elseif") Statement()
1656 void WhileStatement() :
1659 <WHILE> Condition("while") WhileStatement0()
1662 void WhileStatement0() :
1665 <COLON> (Statement())* <ENDWHILE> (<SEMICOLON> | "?>")
1670 void DoStatement() :
1673 <DO> Statement() <WHILE> Condition("while") (<SEMICOLON> | "?>")
1676 void ForStatement() :
1679 <FOR> <LPAREN> [ ForInit() ] <SEMICOLON> [ Expression() ] <SEMICOLON> [ ForUpdate() ] <RPAREN> Statement()
1685 LOOKAHEAD(LocalVariableDeclaration())
1686 LocalVariableDeclaration()
1688 StatementExpressionList()
1691 void StatementExpressionList() :
1694 StatementExpression() ( <COMMA> StatementExpression() )*
1700 StatementExpressionList()
1703 void BreakStatement() :
1706 <BREAK> [ <IDENTIFIER> ] <SEMICOLON>
1709 void ContinueStatement() :
1712 <CONTINUE> [ <IDENTIFIER> ] <SEMICOLON>
1715 void ReturnStatement() :
1718 <RETURN> [ Expression() ] <SEMICOLON>