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 final 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 final void setFileToParse(IFile fileToParse) {
 
  68     this.fileToParse = fileToParse;
 
  71   public PHPParser(IFile fileToParse) {
 
  72     this(new StringReader(""));
 
  73     this.fileToParse = fileToParse;
 
  76   public static final 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 static final 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 final 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,
 
 132                 jj_input_stream.tokenBegin,
 
 133                 jj_input_stream.tokenBegin + e.currentToken.image.length(),
 
 135                 "Line " + e.currentToken.beginLine);
 
 136     } catch (CoreException e2) {
 
 137       PHPeclipsePlugin.log(e2);
 
 142    * Create markers according to the external parser output
 
 144   private static void createMarkers(String output, IFile file) throws CoreException {
 
 145     // delete all markers
 
 146     file.deleteMarkers(IMarker.PROBLEM, false, 0);
 
 151     while ((brIndx = output.indexOf("<br />", indx)) != -1) {
 
 152       // newer php error output (tested with 4.2.3)
 
 153       scanLine(output, file, indx, brIndx);
 
 158       while ((brIndx = output.indexOf("<br>", indx)) != -1) {
 
 159         // older php error output (tested with 4.2.3)
 
 160         scanLine(output, file, indx, brIndx);
 
 166   private static void scanLine(String output, IFile file, int indx, int brIndx) throws CoreException {
 
 168     StringBuffer lineNumberBuffer = new StringBuffer(10);
 
 170     current = output.substring(indx, brIndx);
 
 172     if (current.indexOf(PARSE_WARNING_STRING) != -1 || current.indexOf(PARSE_ERROR_STRING) != -1) {
 
 173       int onLine = current.indexOf("on line <b>");
 
 175         lineNumberBuffer.delete(0, lineNumberBuffer.length());
 
 176         for (int i = onLine; i < current.length(); i++) {
 
 177           ch = current.charAt(i);
 
 178           if ('0' <= ch && '9' >= ch) {
 
 179             lineNumberBuffer.append(ch);
 
 183         int lineNumber = Integer.parseInt(lineNumberBuffer.toString());
 
 185         Hashtable attributes = new Hashtable();
 
 187         current = current.replaceAll("\n", "");
 
 188         current = current.replaceAll("<b>", "");
 
 189         current = current.replaceAll("</b>", "");
 
 190         MarkerUtilities.setMessage(attributes, current);
 
 192         if (current.indexOf(PARSE_ERROR_STRING) != -1)
 
 193           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
 
 194         else if (current.indexOf(PARSE_WARNING_STRING) != -1)
 
 195           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
 
 197           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
 
 198         MarkerUtilities.setLineNumber(attributes, lineNumber);
 
 199         MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
 
 204   public final void parse(String s) throws CoreException {
 
 205     StringReader stream = new StringReader(s);
 
 206     if (jj_input_stream == null) {
 
 207       jj_input_stream = new SimpleCharStream(stream, 1, 1);
 
 212     } catch (ParseException e) {
 
 213       processParseException(e);
 
 218    * Call the php parse command ( php -l -f <filename> )
 
 219    * and create markers according to the external parser output
 
 221   public static void phpExternalParse(IFile file) {
 
 222     IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
 
 223     String filename = file.getLocation().toString();
 
 225     String[] arguments = { filename };
 
 226     MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF));
 
 227     String command = form.format(arguments);
 
 229     String parserResult = PHPStartApacheAction.getParserOutput(command, "External parser: ");
 
 232       // parse the buffer to find the errors and warnings
 
 233       createMarkers(parserResult, file);
 
 234     } catch (CoreException e) {
 
 235       PHPeclipsePlugin.log(e);
 
 239   public static final void parse() throws ParseException {
 
 244 PARSER_END(PHPParser)
 
 248   <PHPSTART : "<?php" | "<?"> : PHPPARSING
 
 253   <PHPEND :"?>"> : DEFAULT
 
 277   "//" : IN_SINGLE_LINE_COMMENT
 
 279   <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
 
 281   "/*" : IN_MULTI_LINE_COMMENT
 
 284 <IN_SINGLE_LINE_COMMENT> SPECIAL_TOKEN :
 
 286   <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : PHPPARSING
 
 289 <IN_SINGLE_LINE_COMMENT> TOKEN :
 
 291   <SINGLE_LINE_COMMENT_PHPEND : "?>" > : DEFAULT
 
 297   <FORMAL_COMMENT: "*/" > : PHPPARSING
 
 300 <IN_MULTI_LINE_COMMENT>
 
 303   <MULTI_LINE_COMMENT: "*/" > : PHPPARSING
 
 306 <IN_SINGLE_LINE_COMMENT,IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT>
 
 316 | <FUNCTION : "function">
 
 319 | <ELSEIF   : "elseif">
 
 324 /* LANGUAGE CONSTRUCT */
 
 329 | <INCLUDE : "include">
 
 330 | <REQUIRE : "require">
 
 331 | <INCLUDE_ONCE : "include_once">
 
 332 | <REQUIRE_ONCE : "require_once">
 
 333 | <GLOBAL : "global">
 
 334 | <STATIC : "static">
 
 335 | <CLASSACCESS: "->">
 
 336 | <STATICCLASSACCESS: "::">
 
 337 | <ARRAYASSIGN: "=>">
 
 340 /* RESERVED WORDS AND LITERALS */
 
 347 | < CONTINUE: "continue" >
 
 348 | < _DEFAULT: "default" >
 
 350 | < EXTENDS: "extends" >
 
 356 | < RETURN: "return" >
 
 358 | < SWITCH: "switch" >
 
 362 | < ENDWHILE : "endwhile" >
 
 364 | <ENDFOR : "endfor" >
 
 365 | <FOREACH : "foreach" >
 
 374 | <OBJECT : "object">
 
 376 | <BOOLEAN : "boolean">
 
 378 | <DOUBLE : "double">
 
 381 | <INTEGER : "integer">
 
 395         <DECIMAL_LITERAL> (["l","L"])?
 
 396       | <HEX_LITERAL> (["l","L"])?
 
 397       | <OCTAL_LITERAL> (["l","L"])?
 
 400   < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
 
 402   < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
 
 404   < #OCTAL_LITERAL: "0" (["0"-"7"])* >
 
 406   < FLOATING_POINT_LITERAL:
 
 407         (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?
 
 408       | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
 
 409       | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
 
 410       | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]
 
 413   < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
 
 415   < STRING_LITERAL: (<STRING_1> | <STRING_2> | <STRING_3>)>
 
 450   < IDENTIFIER: (<LETTER>|<SPECIAL>) (<LETTER>|<DIGIT>|<SPECIAL>)* >
 
 453       ["a"-"z"] | ["A"-"Z"]
 
 461     "_" | ["\u007f"-"\u00ff"]
 
 510 | <RSIGNEDSHIFT: ">>" >
 
 511 | <RUNSIGNEDSHIFT: ">>>" >
 
 512 | <PLUSASSIGN: "+=" >
 
 513 | <MINUSASSIGN: "-=" >
 
 514 | <STARASSIGN: "*=" >
 
 515 | <SLASHASSIGN: "/=" >
 
 521 | <LSHIFTASSIGN: "<<=" >
 
 522 | <RSIGNEDSHIFTASSIGN: ">>=" >
 
 523 | <BANGDOUBLEEQUAL: "!==" >
 
 524 | <TRIPLEEQUAL: "===" >
 
 525 | <TILDEEQUAL: "~=" >
 
 530   < DOLLAR_ID: <DOLLAR> <IDENTIFIER>  >
 
 533 /*****************************************
 
 534  * THE JAVA LANGUAGE GRAMMAR STARTS HERE *
 
 535  *****************************************/
 
 538  * Program structuring syntax follows.
 
 555   } catch (ParseException e) {
 
 556     errorMessage = "'?>' expected";
 
 562   } catch (TokenMgrError e) {
 
 563     errorMessage = e.getMessage();
 
 565     throw generateParseException();
 
 575 void ClassDeclaration() :
 
 577   PHPClassDeclaration classDeclaration;
 
 579   final int pos = jj_input_stream.bufpos;
 
 582   <CLASS> className = <IDENTIFIER> [ <EXTENDS> <IDENTIFIER> ]
 
 584     if (currentSegment != null) {
 
 585       classDeclaration = new PHPClassDeclaration(currentSegment,className.image,pos);
 
 586       currentSegment.add(classDeclaration);
 
 587       currentSegment = classDeclaration;
 
 592     if (currentSegment != null) {
 
 593       currentSegment = (PHPSegmentWithChildren) currentSegment.getParent();
 
 603   } catch (ParseException e) {
 
 604     errorMessage = "'{' expected";
 
 608   ( ClassBodyDeclaration() )*
 
 611   } catch (ParseException e) {
 
 612     errorMessage = "'var', 'function' or '}' expected";
 
 618 void ClassBodyDeclaration() :
 
 626 void FieldDeclaration() :
 
 628   PHPVarDeclaration variableDeclaration;
 
 631   <VAR> variableDeclaration = VariableDeclarator()
 
 633     if (currentSegment != null) {
 
 634       currentSegment.add(variableDeclaration);
 
 638       variableDeclaration = VariableDeclarator()
 
 640       if (currentSegment != null) {
 
 641         currentSegment.add(variableDeclaration);
 
 647   } catch (ParseException e) {
 
 648     errorMessage = "';' expected after variable declaration";
 
 654 PHPVarDeclaration VariableDeclarator() :
 
 657   String varValue = null;
 
 658   final int pos = jj_input_stream.bufpos;
 
 661   varName = VariableDeclaratorId()
 
 665       varValue = VariableInitializer()
 
 666     } catch (ParseException e) {
 
 667       errorMessage = "Literal expression expected in variable initializer";
 
 673     if (varValue == null) {
 
 674       return new PHPVarDeclaration(currentSegment,varName,pos);
 
 676     return new PHPVarDeclaration(currentSegment,varName,pos,varValue);
 
 680 String VariableDeclaratorId() :
 
 683   final StringBuffer buff = new StringBuffer();
 
 689     ( LOOKAHEAD(2) expr = VariableSuffix()
 
 692     {return buff.toString();}
 
 693   } catch (ParseException e) {
 
 694     errorMessage = "'$' expected for variable identifier";
 
 706   token = <DOLLAR_ID> [<LBRACE> expr = Expression() <RBRACE>]
 
 711     return token + "{" + expr + "}";
 
 714   <DOLLAR> expr = VariableName()
 
 718 String VariableName():
 
 724   <LBRACE> expr = Expression() <RBRACE>
 
 725   {return "{"+expr+"}";}
 
 727   token = <IDENTIFIER> [<LBRACE> expr = Expression() <RBRACE>]
 
 732     return token + "{" + expr + "}";
 
 735   <DOLLAR> expr = VariableName()
 
 738   token = <DOLLAR_ID> [expr = VariableName()]
 
 743   return token.image + expr;
 
 747 String VariableInitializer() :
 
 756   <MINUS> (token = <INTEGER_LITERAL> | token = <FLOATING_POINT_LITERAL>)
 
 757   {return "-" + token.image;}
 
 759   <PLUS> (token = <INTEGER_LITERAL> | token = <FLOATING_POINT_LITERAL>)
 
 760   {return "+" + token.image;}
 
 762   expr = ArrayDeclarator()
 
 766   {return token.image;}
 
 769 String ArrayVariable() :
 
 772 final StringBuffer buff = new StringBuffer();
 
 777    [<ARRAYASSIGN> expr = Expression()
 
 778    {buff.append("=>").append(expr);}]
 
 779   {return buff.toString();}
 
 782 String ArrayInitializer() :
 
 785 final StringBuffer buff = new StringBuffer("(");
 
 788   <LPAREN> [ expr = ArrayVariable()
 
 790             ( LOOKAHEAD(2) <COMMA> expr = ArrayVariable()
 
 791             {buff.append(",").append(expr);}
 
 796     return buff.toString();
 
 800 void MethodDeclaration() :
 
 802   PHPFunctionDeclaration functionDeclaration;
 
 805   <FUNCTION> functionDeclaration = MethodDeclarator()
 
 807     if (currentSegment != null) {
 
 808       currentSegment.add(functionDeclaration);
 
 809       currentSegment = functionDeclaration;
 
 814     if (currentSegment != null) {
 
 815       currentSegment = (PHPSegmentWithChildren) currentSegment.getParent();
 
 820 PHPFunctionDeclaration MethodDeclarator() :
 
 823   StringBuffer methodDeclaration = new StringBuffer();
 
 824   String formalParameters;
 
 825   final int pos = jj_input_stream.bufpos;
 
 828   [ <BIT_AND> {methodDeclaration.append("&");} ]
 
 829   identifier = <IDENTIFIER>
 
 830   {methodDeclaration.append(identifier);}
 
 831     formalParameters = FormalParameters()
 
 833     methodDeclaration.append(formalParameters);
 
 834     return new PHPFunctionDeclaration(currentSegment,methodDeclaration.toString(),pos);
 
 838 String FormalParameters() :
 
 841   final StringBuffer buff = new StringBuffer("(");
 
 846   } catch (ParseException e) {
 
 847     errorMessage = "Formal parameter expected after function identifier";
 
 849     jj_consume_token(token.kind);
 
 851             [ expr = FormalParameter()
 
 854                 <COMMA> expr = FormalParameter()
 
 855                 {buff.append(",").append(expr);}
 
 860   } catch (ParseException e) {
 
 861     errorMessage = "')' expected";
 
 867   return buff.toString();
 
 871 String FormalParameter() :
 
 873   PHPVarDeclaration variableDeclaration;
 
 874   final StringBuffer buff = new StringBuffer();
 
 877   [<BIT_AND> {buff.append("&");}] variableDeclaration = VariableDeclarator()
 
 879     buff.append(variableDeclaration.toString());
 
 880     return buff.toString();
 
 915 String Expression() :
 
 918   String assignOperator = null;
 
 922   expr = PrintExpression()
 
 925   expr = ConditionalExpression()
 
 927     assignOperator = AssignmentOperator()
 
 930     } catch (ParseException e) {
 
 931       errorMessage = "expression expected";
 
 940       return expr + assignOperator + expr2;
 
 945 String AssignmentOperator() :
 
 962 | <RSIGNEDSHIFTASSIGN>
 
 976 String ConditionalExpression() :
 
 983   expr = ConditionalOrExpression() [ <HOOK> expr2 = Expression() <COLON> expr3 = ConditionalExpression() ]
 
 988     return expr + "?" + expr2 + ":" + expr3;
 
 993 String ConditionalOrExpression() :
 
 998   final StringBuffer buff = new StringBuffer();
 
1001   expr = ConditionalAndExpression()
 
1006     (operator = <SC_OR> | operator = <_ORL>) expr2 = ConditionalAndExpression()
 
1008       buff.append(operator.image);
 
1013     return buff.toString();
 
1017 String ConditionalAndExpression() :
 
1021   String expr2 = null;
 
1022   final StringBuffer buff = new StringBuffer();
 
1025   expr = ConcatExpression()
 
1030   (operator = <SC_AND> | operator = <_ANDL>) expr2 = ConcatExpression()
 
1032       buff.append(operator.image);
 
1037     return buff.toString();
 
1041 String ConcatExpression() :
 
1044   String expr2 = null;
 
1045   final StringBuffer buff = new StringBuffer();
 
1048   expr = InclusiveOrExpression()
 
1053   <DOT> expr2 = InclusiveOrExpression()
 
1060     return buff.toString();
 
1064 String InclusiveOrExpression() :
 
1067   String expr2 = null;
 
1068   final StringBuffer buff = new StringBuffer();
 
1071   expr = ExclusiveOrExpression()
 
1076   <BIT_OR> expr2 = ExclusiveOrExpression()
 
1083     return buff.toString();
 
1087 String ExclusiveOrExpression() :
 
1090   String expr2 = null;
 
1091   final StringBuffer buff = new StringBuffer();
 
1094   expr = AndExpression()
 
1099     <XOR> expr2 = AndExpression()
 
1106     return buff.toString();
 
1110 String AndExpression() :
 
1113   String expr2 = null;
 
1114   final StringBuffer buff = new StringBuffer();
 
1117   expr = EqualityExpression()
 
1122     <BIT_AND> expr2 = EqualityExpression()
 
1129     return buff.toString();
 
1133 String EqualityExpression() :
 
1138   final StringBuffer buff = new StringBuffer();
 
1141   expr = RelationalExpression()
 
1142   {buff.append(expr);}
 
1147     | operator = <BANGDOUBLEEQUAL>
 
1148     | operator = <TRIPLEEQUAL>
 
1150   expr2 = RelationalExpression()
 
1152     buff.append(operator.image);
 
1156   {return buff.toString();}
 
1159 String RelationalExpression() :
 
1164   final StringBuffer buff = new StringBuffer();
 
1167   expr = ShiftExpression()
 
1168   {buff.append(expr);}
 
1170   ( operator = <LT> | operator = <GT> | operator = <LE> | operator = <GE> ) expr2 = ShiftExpression()
 
1172     buff.append(operator.image);
 
1176   {return buff.toString();}
 
1179 String ShiftExpression() :
 
1183   final StringBuffer buff = new StringBuffer();
 
1186   expr = AdditiveExpression()
 
1187   {buff.append(expr);}
 
1189   (operator = <LSHIFT> | operator = <RSIGNEDSHIFT> | operator = <RUNSIGNEDSHIFT> ) expr = AdditiveExpression()
 
1191     buff.append(operator.image);
 
1195   {return buff.toString();}
 
1198 String AdditiveExpression() :
 
1202   final StringBuffer buff = new StringBuffer();
 
1205   expr = MultiplicativeExpression()
 
1206   {buff.append(expr);}
 
1208    ( operator = <PLUS> | operator = <MINUS> ) expr = MultiplicativeExpression()
 
1210     buff.append(operator.image);
 
1214   {return buff.toString();}
 
1217 String MultiplicativeExpression() :
 
1221   final StringBuffer buff = new StringBuffer();}
 
1223   expr = UnaryExpression()
 
1224   {buff.append(expr);}
 
1226   ( operator = <STAR> | operator = <SLASH> | operator = <REM> ) expr = UnaryExpression()
 
1228     buff.append(operator.image);
 
1232   {return buff.toString();}
 
1236  * An unary expression starting with @, & or nothing
 
1238 String UnaryExpression() :
 
1242   final StringBuffer buff = new StringBuffer();
 
1245   token = <BIT_AND> expr = UnaryExpressionNoPrefix()
 
1247     if (token == null) {
 
1250     return token.image + expr;
 
1253   (<AT> {buff.append("@");})* expr = UnaryExpressionNoPrefix()
 
1254   {return buff.append(expr).toString();}
 
1257 String UnaryExpressionNoPrefix() :
 
1263   ( token = <PLUS> | token = <MINUS> ) expr = UnaryExpression()
 
1265     return token.image + expr;
 
1268   expr = PreIncrementExpression()
 
1271   expr = PreDecrementExpression()
 
1274   expr = UnaryExpressionNotPlusMinus()
 
1279 String PreIncrementExpression() :
 
1284   <INCR> expr = PrimaryExpression()
 
1288 String PreDecrementExpression() :
 
1293   <DECR> expr = PrimaryExpression()
 
1297 String UnaryExpressionNotPlusMinus() :
 
1302   <BANG> expr = UnaryExpression()
 
1303   {return "!" + expr;}
 
1305   LOOKAHEAD( <LPAREN> Type() <RPAREN> )
 
1306   expr = CastExpression()
 
1309   expr = PostfixExpression()
 
1315   <LPAREN> expr = Expression()<RPAREN>
 
1316   {return "("+expr+")";}
 
1319 String CastExpression() :
 
1321 final String type, expr;
 
1324   <LPAREN> type = Type() <RPAREN> expr = UnaryExpression()
 
1325   {return "(" + type + ")" + expr;}
 
1328 String PostfixExpression() :
 
1331   Token operator = null;
 
1334   expr = PrimaryExpression() [ operator = <INCR> | operator = <DECR> ]
 
1336     if (operator == null) {
 
1339     return expr + operator.image;
 
1343 String PrimaryExpression() :
 
1347   final StringBuffer buff = new StringBuffer();
 
1351   identifier = <IDENTIFIER> <STATICCLASSACCESS> expr = ClassIdentifier()
 
1352   {buff.append(identifier.image).append("::").append(expr);}
 
1354   expr = PrimarySuffix()
 
1355   {buff.append(expr);}
 
1357   {return buff.toString();}
 
1359   expr = PrimaryPrefix()  {buff.append(expr);}
 
1360   ( expr = PrimarySuffix()  {buff.append(expr);} )*
 
1361   {return buff.toString();}
 
1363   expr = ArrayDeclarator()
 
1364   {return "array" + expr;}
 
1367 String ArrayDeclarator() :
 
1372   <ARRAY> expr = ArrayInitializer()
 
1373   {return "array" + expr;}
 
1376 String PrimaryPrefix() :
 
1382   token = <IDENTIFIER>
 
1383   {return token.image;}
 
1385   <NEW> expr = ClassIdentifier()
 
1387     return "new " + expr;
 
1390   expr = VariableDeclaratorId()
 
1394 String ClassIdentifier():
 
1400   token = <IDENTIFIER>
 
1401   {return token.image;}
 
1403   expr = VariableDeclaratorId()
 
1407 String PrimarySuffix() :
 
1415   expr = VariableSuffix()
 
1419 String VariableSuffix() :
 
1424   <CLASSACCESS> expr = VariableName()
 
1425   {return "->" + expr;}
 
1427   <LBRACKET> [ expr = Expression() ]
 
1430   } catch (ParseException e) {
 
1431     errorMessage = "']' expected";
 
1439     return "[" + expr + "]";
 
1449   token = <INTEGER_LITERAL>
 
1450   {return token.image;}
 
1452   token = <FLOATING_POINT_LITERAL>
 
1453   {return token.image;}
 
1455   token = <STRING_LITERAL>
 
1456   {return token.image;}
 
1458   expr = BooleanLiteral()
 
1461   expr = NullLiteral()
 
1465 String BooleanLiteral() :
 
1475 String NullLiteral() :
 
1482 String Arguments() :
 
1487   <LPAREN> [ expr = ArgumentList() ]
 
1490   } catch (ParseException e) {
 
1491     errorMessage = "')' expected to close the argument list";
 
1499   return "(" + expr + ")";
 
1503 String ArgumentList() :
 
1506 final StringBuffer buff = new StringBuffer();
 
1510   {buff.append(expr);}
 
1514       } catch (ParseException e) {
 
1515         errorMessage = "expression expected after a comma in argument list";
 
1520       buff.append(",").append("expr");
 
1523    {return buff.toString();}
 
1527  * Statement syntax follows.
 
1536     (<SEMICOLON> | "?>")
 
1537   } catch (ParseException e) {
 
1538     errorMessage = "';' expected";
 
1550   StatementExpression()
 
1553   } catch (ParseException e) {
 
1554     errorMessage = "';' expected after expression";
 
1579   [<AT>] IncludeStatement()
 
1586 void IncludeStatement() :
 
1589   final int pos = jj_input_stream.bufpos;
 
1595     if (currentSegment != null) {
 
1596       currentSegment.add(new PHPReqIncDeclaration(currentSegment, "require",pos,expr));
 
1600     (<SEMICOLON> | "?>")
 
1601   } catch (ParseException e) {
 
1602     errorMessage = "';' expected";
 
1610     if (currentSegment != null) {
 
1611       currentSegment.add(new PHPReqIncDeclaration(currentSegment, "require_once",pos,expr));
 
1615     (<SEMICOLON> | "?>")
 
1616   } catch (ParseException e) {
 
1617     errorMessage = "';' expected";
 
1625     if (currentSegment != null) {
 
1626       currentSegment.add(new PHPReqIncDeclaration(currentSegment, "include",pos,expr));
 
1630     (<SEMICOLON> | "?>")
 
1631   } catch (ParseException e) {
 
1632     errorMessage = "';' expected";
 
1640     if (currentSegment != null) {
 
1641       currentSegment.add(new PHPReqIncDeclaration(currentSegment, "include_once",pos,expr));
 
1645     (<SEMICOLON> | "?>")
 
1646   } catch (ParseException e) {
 
1647     errorMessage = "';' expected";
 
1653 String PrintExpression() :
 
1655   final StringBuffer buff = new StringBuffer("print ");
 
1659   <PRINT> expr = Expression()
 
1662     return buff.toString();
 
1666 void EchoStatement() :
 
1669   <ECHO> Expression() (<COMMA> Expression())*
 
1671     (<SEMICOLON> | "?>")
 
1672   } catch (ParseException e) {
 
1673     errorMessage = "';' expected after 'echo' statement";
 
1679 void GlobalStatement() :
 
1682   <GLOBAL> VariableDeclaratorId() (<COMMA> VariableDeclaratorId())*
 
1684     (<SEMICOLON> | "?>")
 
1685   } catch (ParseException e) {
 
1686     errorMessage = "';' expected";
 
1692 void StaticStatement() :
 
1695   <STATIC> VariableDeclarator() (<COMMA> VariableDeclarator())*
 
1697     (<SEMICOLON> | "?>")
 
1698   } catch (ParseException e) {
 
1699     errorMessage = "';' expected";
 
1705 void LabeledStatement() :
 
1708   <IDENTIFIER> <COLON> Statement()
 
1716   } catch (ParseException e) {
 
1717     errorMessage = "'{' expected";
 
1721   ( BlockStatement() )*
 
1725 void BlockStatement() :
 
1735 void LocalVariableDeclaration() :
 
1738   VariableDeclarator() ( <COMMA> VariableDeclarator() )*
 
1741 void EmptyStatement() :
 
1747 void StatementExpression() :
 
1750   PreIncrementExpression()
 
1752   PreDecrementExpression()
 
1760     AssignmentOperator() Expression()
 
1764 void SwitchStatement() :
 
1767   <SWITCH> <LPAREN> Expression() <RPAREN> <LBRACE>
 
1768     ( SwitchLabel() ( BlockStatement() )* )*
 
1772 void SwitchLabel() :
 
1775   <CASE> Expression() <COLON>
 
1780 void IfStatement() :
 
1782  * The disambiguating algorithm of JavaCC automatically binds dangling
 
1783  * else's to the innermost if statement.  The LOOKAHEAD specification
 
1784  * is to tell JavaCC that we know what we are doing.
 
1788   final int pos = jj_input_stream.bufpos;
 
1791   token = <IF> Condition("if") IfStatement0(pos,pos+token.image.length())
 
1794 void Condition(String keyword) :
 
1799   } catch (ParseException e) {
 
1800     errorMessage = "'(' expected after " + keyword + " keyword";
 
1807   } catch (ParseException e) {
 
1808     errorMessage = "')' expected after " + keyword + " keyword";
 
1814 void IfStatement0(int start,int end) :
 
1818   <COLON> (Statement())* (ElseIfStatementColon())* [ElseStatementColon()]
 
1821   setMarker(fileToParse,
 
1822             "Ugly syntax detected, you should if () {...} instead of if (): ... endif;",
 
1826             "Line " + token.beginLine);
 
1827   } catch (CoreException e) {
 
1828     PHPeclipsePlugin.log(e);
 
1832   } catch (ParseException e) {
 
1833     errorMessage = "'endif' expected";
 
1839   } catch (ParseException e) {
 
1840     errorMessage = "';' expected 'endif' keyword";
 
1845   Statement() ( LOOKAHEAD(1) ElseIfStatement() )* [ LOOKAHEAD(1) <ELSE> Statement() ]
 
1848 void ElseIfStatementColon() :
 
1851   <ELSEIF> Condition("elseif") <COLON> (Statement())*
 
1854 void ElseStatementColon() :
 
1857   <ELSE> <COLON> (Statement())*
 
1860 void ElseIfStatement() :
 
1863   <ELSEIF> Condition("elseif") Statement()
 
1866 void WhileStatement() :
 
1869   final int pos = jj_input_stream.bufpos;
 
1872   token = <WHILE> Condition("while") WhileStatement0(pos,pos + token.image.length())
 
1875 void WhileStatement0(final int start, final int end) :
 
1878   <COLON> (Statement())*
 
1880   setMarker(fileToParse,
 
1881             "Ugly syntax detected, you should while () {...} instead of while (): ... endwhile;",
 
1885             "Line " + token.beginLine);
 
1886   } catch (CoreException e) {
 
1887     PHPeclipsePlugin.log(e);
 
1891   } catch (ParseException e) {
 
1892     errorMessage = "'endwhile' expected";
 
1897     (<SEMICOLON> | "?>")
 
1898   } catch (ParseException e) {
 
1899     errorMessage = "';' expected after 'endwhile' keyword";
 
1907 void DoStatement() :
 
1910   <DO> Statement() <WHILE> Condition("while")
 
1912     (<SEMICOLON> | "?>")
 
1913   } catch (ParseException e) {
 
1914     errorMessage = "';' expected";
 
1920 void ForeachStatement() :
 
1926   } catch (ParseException e) {
 
1927     errorMessage = "'(' expected after 'foreach' keyword";
 
1933   } catch (ParseException e) {
 
1934     errorMessage = "variable expected";
 
1940   } catch (ParseException e) {
 
1941     errorMessage = "'as' expected";
 
1947   } catch (ParseException e) {
 
1948     errorMessage = "variable expected";
 
1952   [ <ARRAYASSIGN> Expression() ]
 
1955   } catch (ParseException e) {
 
1956     errorMessage = "')' expected after 'foreach' keyword";
 
1962   } catch (ParseException e) {
 
1963     if (errorMessage != null) throw e;
 
1964     errorMessage = "statement expected";
 
1970 void ForStatement() :
 
1973 final int pos = jj_input_stream.bufpos;
 
1979   } catch (ParseException e) {
 
1980     errorMessage = "'(' expected after 'for' keyword";
 
1984      [ ForInit() ] <SEMICOLON> [ Expression() ] <SEMICOLON> [ ForUpdate() ] <RPAREN>
 
1988       <COLON> (Statement())*
 
1991         setMarker(fileToParse,
 
1992                   "Ugly syntax detected, you should for () {...} instead of for (): ... endfor;",
 
1994                   pos+token.image.length(),
 
1996                   "Line " + token.beginLine);
 
1997         } catch (CoreException e) {
 
1998           PHPeclipsePlugin.log(e);
 
2003       } catch (ParseException e) {
 
2004         errorMessage = "'endfor' expected";
 
2010       } catch (ParseException e) {
 
2011         errorMessage = "';' expected 'endfor' keyword";
 
2021   LOOKAHEAD(LocalVariableDeclaration())
 
2022   LocalVariableDeclaration()
 
2024   StatementExpressionList()
 
2027 void StatementExpressionList() :
 
2030   StatementExpression() ( <COMMA> StatementExpression() )*
 
2036   StatementExpressionList()
 
2039 void BreakStatement() :
 
2042   <BREAK> [ <IDENTIFIER> ] <SEMICOLON>
 
2045 void ContinueStatement() :
 
2048   <CONTINUE> [ <IDENTIFIER> ] <SEMICOLON>
 
2051 void ReturnStatement() :
 
2054   <RETURN> [ Expression() ] <SEMICOLON>