X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/test/PHPParser.jj b/net.sourceforge.phpeclipse/src/test/PHPParser.jj index 57e9eb8..e3b05cf 100644 --- a/net.sourceforge.phpeclipse/src/test/PHPParser.jj +++ b/net.sourceforge.phpeclipse/src/test/PHPParser.jj @@ -28,7 +28,6 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.ui.texteditor.MarkerUtilities; import org.eclipse.jface.preference.IPreferenceStore; -import java.io.CharArrayReader; import java.util.Hashtable; import java.io.StringReader; import java.text.MessageFormat; @@ -36,6 +35,11 @@ import java.text.MessageFormat; import net.sourceforge.phpeclipse.actions.PHPStartApacheAction; import net.sourceforge.phpeclipse.PHPeclipsePlugin; import net.sourceforge.phpdt.internal.compiler.parser.PHPOutlineInfo; +import net.sourceforge.phpdt.internal.compiler.parser.PHPSegmentWithChildren; +import net.sourceforge.phpdt.internal.compiler.parser.PHPFunctionDeclaration; +import net.sourceforge.phpdt.internal.compiler.parser.PHPClassDeclaration; +import net.sourceforge.phpdt.internal.compiler.parser.PHPVarDeclaration; +import net.sourceforge.phpdt.internal.compiler.parser.PHPReqIncDeclaration; /** * A new php parser. @@ -44,17 +48,15 @@ import net.sourceforge.phpdt.internal.compiler.parser.PHPOutlineInfo; * You can test the parser with the PHPParserTestCase2.java * @author Matthieu Casanova */ -public class PHPParser extends PHPParserSuperclass { - - private static PHPParser me; +public final class PHPParser extends PHPParserSuperclass { private static IFile fileToParse; + /** The current segment */ + private static PHPSegmentWithChildren currentSegment; + private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$ private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$ - public static final int ERROR = 2; - public static final int WARNING = 1; - public static final int INFO = 0; PHPOutlineInfo outlineInfo; private static int errorLevel = ERROR; private static String errorMessage; @@ -62,34 +64,16 @@ public class PHPParser extends PHPParserSuperclass { public PHPParser() { } - public static PHPParser getInstance(IFile fileToParse) { - if (me == null) { - me = new PHPParser(fileToParse); - } else { - me.setFileToParse(fileToParse); - } - return me; - } - - public void setFileToParse(IFile fileToParse) { + public final void setFileToParse(IFile fileToParse) { this.fileToParse = fileToParse; } - public static PHPParser getInstance(java.io.Reader stream) { - if (me == null) { - me = new PHPParser(stream); - } else { - me.ReInit(stream); - } - return me; - } - public PHPParser(IFile fileToParse) { this(new StringReader("")); this.fileToParse = fileToParse; } - public void phpParserTester(String strEval) throws CoreException, ParseException { + public static final void phpParserTester(String strEval) throws CoreException, ParseException { PHPParserTokenManager.SwitchTo(PHPParserTokenManager.PHPPARSING); StringReader stream = new StringReader(strEval); if (jj_input_stream == null) { @@ -99,17 +83,18 @@ public class PHPParser extends PHPParserSuperclass { phpTest(); } - public void htmlParserTester(String strEval) throws CoreException, ParseException { + public static final void htmlParserTester(String strEval) throws CoreException, ParseException { StringReader stream = new StringReader(strEval); if (jj_input_stream == null) { jj_input_stream = new SimpleCharStream(stream, 1, 1); } ReInit(stream); - phpTest(); + phpFile(); } - public PHPOutlineInfo parseInfo(Object parent, String s) { + public final PHPOutlineInfo parseInfo(Object parent, String s) { outlineInfo = new PHPOutlineInfo(parent); + currentSegment = outlineInfo.getDeclarations(); StringReader stream = new StringReader(s); if (jj_input_stream == null) { jj_input_stream = new SimpleCharStream(stream, 1, 1); @@ -118,45 +103,38 @@ public class PHPParser extends PHPParserSuperclass { try { parse(); } catch (ParseException e) { - if (errorMessage == null) { - PHPeclipsePlugin.log(e); - } else { - setMarker(errorMessage, e.currentToken.beginLine, errorLevel); - errorMessage = null; - } + processParseException(e); } return outlineInfo; } - /** - * Create marker for the parse error + * This method will process the parse exception. + * If the error message is null, the parse exception wasn't catched and a trace is written in the log + * @param e the ParseException */ - private static void setMarker(String message, int lineNumber, int errorLevel) { - try { - setMarker(fileToParse, message, lineNumber, errorLevel); - } catch (CoreException e) { + private static void processParseException(final ParseException e) { + if (errorMessage == null) { PHPeclipsePlugin.log(e); + errorMessage = "this exception wasn't handled by the parser please tell us how to reproduce it"; } + setMarker(e); + errorMessage = null; } - public static void setMarker(IFile file, String message, int lineNumber, int errorLevel) throws CoreException { - if (file != null) { - Hashtable attributes = new Hashtable(); - MarkerUtilities.setMessage(attributes, message); - switch (errorLevel) { - case ERROR : - attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR)); - break; - case WARNING : - attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING)); - break; - case INFO : - attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO)); - break; - } - MarkerUtilities.setLineNumber(attributes, lineNumber); - MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM); + /** + * Create marker for the parse error + */ + private static void setMarker(ParseException e) { + try { + setMarker(fileToParse, + errorMessage, + jj_input_stream.tokenBegin, + jj_input_stream.tokenBegin + e.currentToken.image.length(), + errorLevel, + "Line " + e.currentToken.beginLine); + } catch (CoreException e2) { + PHPeclipsePlugin.log(e2); } } @@ -223,12 +201,16 @@ public class PHPParser extends PHPParserSuperclass { } } - public void parse(String s) throws CoreException { - ReInit(new StringReader(s)); + public final void parse(String s) throws CoreException { + StringReader stream = new StringReader(s); + if (jj_input_stream == null) { + jj_input_stream = new SimpleCharStream(stream, 1, 1); + } + ReInit(stream); try { parse(); } catch (ParseException e) { - PHPeclipsePlugin.log(e); + processParseException(e); } } @@ -254,7 +236,7 @@ public class PHPParser extends PHPParserSuperclass { } } - public void parse() throws ParseException { + public static final void parse() throws ParseException { phpFile(); } } @@ -263,20 +245,20 @@ PARSER_END(PHPParser) <DEFAULT> TOKEN : { - "<?php" : PHPPARSING -| "<?" : PHPPARSING + <PHPSTART : "<?php" | "<?"> : PHPPARSING } -<DEFAULT> SKIP : +<PHPPARSING> TOKEN : { - < ~[] > + <PHPEND :"?>"> : DEFAULT } -<PHPPARSING> TOKEN : +<DEFAULT> SKIP : { - "?>" : DEFAULT + < ~[] > } + /* WHITE SPACE */ <PHPPARSING> SKIP : @@ -299,10 +281,14 @@ PARSER_END(PHPParser) "/*" : IN_MULTI_LINE_COMMENT } -<IN_SINGLE_LINE_COMMENT> -SPECIAL_TOKEN : +<IN_SINGLE_LINE_COMMENT> SPECIAL_TOKEN : { - <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" | "?>" > : PHPPARSING + <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : PHPPARSING +} + +<IN_SINGLE_LINE_COMMENT> TOKEN : +{ + <SINGLE_LINE_COMMENT_PHPEND : "?>" > : DEFAULT } <IN_FORMAL_COMMENT> @@ -374,6 +360,10 @@ MORE : | < TRUE: "true" > | < WHILE: "while" > | < ENDWHILE : "endwhile" > +| <ENDIF : "endif" > +| <ENDFOR : "endfor" > +| <FOREACH : "foreach" > +| <AS : "as" > } /* TYPES */ @@ -425,20 +415,30 @@ MORE : < STRING_LITERAL: (<STRING_1> | <STRING_2> | <STRING_3>)> | < STRING_1: "\"" - ( (~["\""]) - | "\\\"" + ( + ~["\""] + | + "\\\"" )* "\"" > | < STRING_2: "'" - ( (~["'"]))* + ( + ~["'"] + | + "\\'" + )* "'" > | < STRING_3: "`" - ( (~["`"]))* + ( + ~["`"] + | + "\\`" + )* "`" > } @@ -458,7 +458,7 @@ MORE : > | < #SPECIAL: - "_" + "_" | ["\u007f"-"\u00ff"] > } @@ -483,43 +483,46 @@ MORE : { <AT : "@"> | <DOLLAR : "$"> -| < ASSIGN: "=" > -| < GT: ">" > -| < LT: "<" > -| < BANG: "!" > -| < HOOK: "?" > -| < COLON: ":" > -| < EQ: "==" > -| < LE: "<=" > -| < GE: ">=" > -| < NE: "!=" > -| < SC_OR: "||" > -| < SC_AND: "&&" > -| < INCR: "++" > -| < DECR: "--" > -| < PLUS: "+" > -| < MINUS: "-" > -| < STAR: "*" > -| < SLASH: "/" > -| < BIT_AND: "&" > -| < BIT_OR: "|" > -| < XOR: "^" > -| < REM: "%" > -| < LSHIFT: "<<" > -| < RSIGNEDSHIFT: ">>" > -| < RUNSIGNEDSHIFT: ">>>" > -| < PLUSASSIGN: "+=" > -| < MINUSASSIGN: "-=" > -| < STARASSIGN: "*=" > -| < SLASHASSIGN: "/=" > -| < ANDASSIGN: "&=" > -| < ORASSIGN: "|=" > -| < XORASSIGN: "^=" > -| < DOTASSIGN: ".=" > -| < REMASSIGN: "%=" > -| < LSHIFTASSIGN: "<<=" > -| < RSIGNEDSHIFTASSIGN: ">>=" > -| < RUNSIGNEDSHIFTASSIGN: ">>>=" > +| <ASSIGN: "=" > +| <GT: ">" > +| <LT: "<" > +| <BANG: "!" > +| <HOOK: "?" > +| <COLON: ":" > +| <EQ: "==" > +| <LE: "<=" > +| <GE: ">=" > +| <NE: "!=" > +| <DIF: "<>" > +| <SC_OR: "||" > +| <SC_AND: "&&" > +| <INCR: "++" > +| <DECR: "--" > +| <PLUS: "+" > +| <MINUS: "-" > +| <STAR: "*" > +| <SLASH: "/" > +| <BIT_AND: "&" > +| <BIT_OR: "|" > +| <XOR: "^" > +| <REM: "%" > +| <LSHIFT: "<<" > +| <RSIGNEDSHIFT: ">>" > +| <RUNSIGNEDSHIFT: ">>>" > +| <PLUSASSIGN: "+=" > +| <MINUSASSIGN: "-=" > +| <STARASSIGN: "*=" > +| <SLASHASSIGN: "/=" > +| <ANDASSIGN: "&=" > +| <ORASSIGN: "|=" > +| <XORASSIGN: "^=" > +| <DOTASSIGN: ".=" > +| <REMASSIGN: "%=" > +| <LSHIFTASSIGN: "<<=" > +| <RSIGNEDSHIFTASSIGN: ">>=" > +| <BANGDOUBLEEQUAL: "!==" > +| <TRIPLEEQUAL: "===" > +| <TILDEEQUAL: "~=" > } <PHPPARSING> TOKEN : @@ -545,8 +548,22 @@ void phpTest() : void phpFile() : {} { - ("<?php" Php() "?>")* + try { + (<PHPSTART> Php() + try { + <PHPEND> + } catch (ParseException e) { + errorMessage = "'?>' expected"; + errorLevel = ERROR; + throw e; + } + )* <EOF> + } catch (TokenMgrError e) { + errorMessage = e.getMessage(); + errorLevel = ERROR; + throw generateParseException(); + } } void Php() : @@ -556,16 +573,46 @@ void Php() : } void ClassDeclaration() : -{} { - <CLASS> <IDENTIFIER> [ <EXTENDS> <IDENTIFIER> ] + PHPClassDeclaration classDeclaration; + Token className; + final int pos = jj_input_stream.bufpos; +} +{ + <CLASS> className = <IDENTIFIER> [ <EXTENDS> <IDENTIFIER> ] + { + if (currentSegment != null) { + classDeclaration = new PHPClassDeclaration(currentSegment,className.image,pos); + currentSegment.add(classDeclaration); + currentSegment = classDeclaration; + } + } ClassBody() + { + if (currentSegment != null) { + currentSegment = (PHPSegmentWithChildren) currentSegment.getParent(); + } + } } void ClassBody() : {} { - <LBRACE> ( ClassBodyDeclaration() )* <RBRACE> + try { + <LBRACE> + } catch (ParseException e) { + errorMessage = "'{' expected"; + errorLevel = ERROR; + throw e; + } + ( ClassBodyDeclaration() )* + try { + <RBRACE> + } catch (ParseException e) { + errorMessage = "'var', 'function' or '}' expected"; + errorLevel = ERROR; + throw e; + } } void ClassBodyDeclaration() : @@ -577,342 +624,903 @@ void ClassBodyDeclaration() : } void FieldDeclaration() : -{} { - <VAR> VariableDeclarator() ( <COMMA> VariableDeclarator() )* <SEMICOLON> + PHPVarDeclaration variableDeclaration; +} +{ + <VAR> variableDeclaration = VariableDeclarator() + { + if (currentSegment != null) { + currentSegment.add(variableDeclaration); + } + } + ( <COMMA> + variableDeclaration = VariableDeclarator() + { + if (currentSegment != null) { + currentSegment.add(variableDeclaration); + } + } + )* + try { + <SEMICOLON> + } catch (ParseException e) { + errorMessage = "';' expected after variable declaration"; + errorLevel = ERROR; + throw e; + } } -void VariableDeclarator() : -{} +PHPVarDeclaration VariableDeclarator() : { - VariableDeclaratorId() [ <ASSIGN> VariableInitializer() ] + String varName; + String varValue = null; + final int pos = jj_input_stream.bufpos; +} +{ + varName = VariableDeclaratorId() + [ + <ASSIGN> + try { + varValue = VariableInitializer() + } catch (ParseException e) { + errorMessage = "Literal expression expected in variable initializer"; + errorLevel = ERROR; + throw e; + } + ] + { + if (varValue == null) { + return new PHPVarDeclaration(currentSegment,varName,pos); + } + return new PHPVarDeclaration(currentSegment,varName,pos,varValue); + } } -void VariableDeclaratorId() : -{} +String VariableDeclaratorId() : { - Variable() ( LOOKAHEAD(2) VariableSuffix() )* + String expr; + final StringBuffer buff = new StringBuffer(); +} +{ + try { + expr = Variable() + {buff.append(expr);} + ( LOOKAHEAD(2) expr = VariableSuffix() + {buff.append(expr);} + )* + {return buff.toString();} + } catch (ParseException e) { + errorMessage = "'$' expected for variable identifier"; + errorLevel = ERROR; + throw e; + } } -void Variable(): -{} +String Variable(): +{ + String expr = null; + Token token; +} { - <DOLLAR_ID> (<LBRACE> Expression() <RBRACE>) * + token = <DOLLAR_ID> [<LBRACE> expr = Expression() <RBRACE>] + { + if (expr == null) { + return token.image; + } + return token + "{" + expr + "}"; + } | - <DOLLAR> VariableName() + <DOLLAR> expr = VariableName() + {return "$" + expr;} } -void VariableName(): -{} +String VariableName(): { - <LBRACE> Expression() <RBRACE> +String expr = null; +Token token; +} +{ + <LBRACE> expr = Expression() <RBRACE> + {return "{"+expr+"}";} | - <IDENTIFIER> (<LBRACE> Expression() <RBRACE>) * + token = <IDENTIFIER> [<LBRACE> expr = Expression() <RBRACE>] + { + if (expr == null) { + return token.image; + } + return token + "{" + expr + "}"; + } | - <DOLLAR> VariableName() + <DOLLAR> expr = VariableName() + {return "$" + expr;} +| + token = <DOLLAR_ID> [expr = VariableName()] + { + if (expr == null) { + return token.image; + } + return token.image + expr; + } } -void VariableInitializer() : -{} +String VariableInitializer() : { - Expression() + String expr; + Token token; +} +{ + expr = Literal() + {return expr;} +| + <MINUS> (token = <INTEGER_LITERAL> | token = <FLOATING_POINT_LITERAL>) + {return "-" + token.image;} +| + <PLUS> (token = <INTEGER_LITERAL> | token = <FLOATING_POINT_LITERAL>) + {return "+" + token.image;} +| + expr = ArrayDeclarator() + {return expr;} +| + token = <IDENTIFIER> + {return token.image;} } -void ArrayVariable() : -{} +String ArrayVariable() : +{ +String expr; +final StringBuffer buff = new StringBuffer(); +} { - Expression() (<ARRAYASSIGN> Expression())* + expr = Expression() + {buff.append(expr);} + [<ARRAYASSIGN> expr = Expression() + {buff.append("=>").append(expr);}] + {return buff.toString();} } -void ArrayInitializer() : -{} +String ArrayInitializer() : +{ +String expr = null; +final StringBuffer buff = new StringBuffer("("); +} { - <LPAREN> [ ArrayVariable() ( LOOKAHEAD(2) <COMMA> ArrayVariable() )* ]<RPAREN> + <LPAREN> [ expr = ArrayVariable() + {buff.append(expr);} + ( LOOKAHEAD(2) <COMMA> expr = ArrayVariable() + {buff.append(",").append(expr);} + )* ] + <RPAREN> + { + buff.append(")"); + return buff.toString(); + } } void MethodDeclaration() : -{} { - <FUNCTION> MethodDeclarator() - ( Block() | <SEMICOLON> ) + PHPFunctionDeclaration functionDeclaration; +} +{ + <FUNCTION> functionDeclaration = MethodDeclarator() + { + if (currentSegment != null) { + currentSegment.add(functionDeclaration); + currentSegment = functionDeclaration; + } + } + Block() + { + if (currentSegment != null) { + currentSegment = (PHPSegmentWithChildren) currentSegment.getParent(); + } + } } -void MethodDeclarator() : -{} +PHPFunctionDeclaration MethodDeclarator() : +{ + Token identifier; + StringBuffer methodDeclaration = new StringBuffer(); + String formalParameters; + final int pos = jj_input_stream.bufpos; +} { - [<BIT_AND>] <IDENTIFIER> FormalParameters() + [ <BIT_AND> {methodDeclaration.append("&");} ] + identifier = <IDENTIFIER> + {methodDeclaration.append(identifier);} + formalParameters = FormalParameters() + { + methodDeclaration.append(formalParameters); + return new PHPFunctionDeclaration(currentSegment,methodDeclaration.toString(),pos); + } } -void FormalParameters() : -{} +String FormalParameters() : { - <LPAREN> [ FormalParameter() ( <COMMA> FormalParameter() )* ] <RPAREN> + String expr; + final StringBuffer buff = new StringBuffer("("); +} +{ + try { + <LPAREN> + } catch (ParseException e) { + errorMessage = "Formal parameter expected after function identifier"; + errorLevel = ERROR; + jj_consume_token(token.kind); + } + [ expr = FormalParameter() + {buff.append(expr);} + ( + <COMMA> expr = FormalParameter() + {buff.append(",").append(expr);} + )* + ] + try { + <RPAREN> + } catch (ParseException e) { + errorMessage = "')' expected"; + errorLevel = ERROR; + throw e; + } + { + buff.append(")"); + return buff.toString(); + } } -void FormalParameter() : -{} +String FormalParameter() : +{ + PHPVarDeclaration variableDeclaration; + final StringBuffer buff = new StringBuffer(); +} { - [<BIT_AND>] VariableDeclarator() + [<BIT_AND> {buff.append("&");}] variableDeclaration = VariableDeclarator() + { + buff.append(variableDeclaration.toString()); + return buff.toString(); + } } -void Type() : +String Type() : {} { <STRING> + {return "string";} | <BOOL> + {return "bool";} | <BOOLEAN> + {return "boolean";} | <REAL> + {return "real";} | <DOUBLE> + {return "double";} | <FLOAT> + {return "float";} | <INT> + {return "int";} | <INTEGER> + {return "integer";} +| + <OBJECT> + {return "object";} } -/* - * Expression syntax follows. - */ - -void Expression() : -/* - * This expansion has been written this way instead of: - * Assignment() | ConditionalExpression() - * for performance reasons. - * However, it is a weakening of the grammar for it allows the LHS of - * assignments to be any conditional expression whereas it can only be - * a primary expression. Consider adding a semantic predicate to work - * around this. - */ -{} +String Expression() : +{ + String expr; + String assignOperator = null; + String expr2 = null; +} { - PrintExpression() + expr = PrintExpression() + {return expr;} | - ConditionalExpression() + expr = ConditionalExpression() [ - AssignmentOperator() Expression() + assignOperator = AssignmentOperator() + try { + expr2 = Expression() + } catch (ParseException e) { + errorMessage = "expression expected"; + errorLevel = ERROR; + throw e; + } ] + { + if (expr2 == null) { + return expr; + } else { + return expr + assignOperator + expr2; + } + } } -void AssignmentOperator() : -{} -{ - <ASSIGN> | <STARASSIGN> | <SLASHASSIGN> | <REMASSIGN> | <PLUSASSIGN> | <MINUSASSIGN> | <LSHIFTASSIGN> | <RSIGNEDSHIFTASSIGN> | <RUNSIGNEDSHIFTASSIGN> | <ANDASSIGN> | <XORASSIGN> | <ORASSIGN> | <DOTASSIGN> +String AssignmentOperator() : +{} +{ + <ASSIGN> +{return "=";} +| <STARASSIGN> +{return "*=";} +| <SLASHASSIGN> +{return "/=";} +| <REMASSIGN> +{return "%=";} +| <PLUSASSIGN> +{return "+=";} +| <MINUSASSIGN> +{return "-=";} +| <LSHIFTASSIGN> +{return "<<=";} +| <RSIGNEDSHIFTASSIGN> +{return ">>=";} +| <ANDASSIGN> +{return "&=";} +| <XORASSIGN> +{return "|=";} +| <ORASSIGN> +{return "|=";} +| <DOTASSIGN> +{return ".=";} +| <TILDEEQUAL> +{return "~=";} +} + +String ConditionalExpression() : +{ + String expr; + String expr2 = null; + String expr3 = null; +} +{ + expr = ConditionalOrExpression() [ <HOOK> expr2 = Expression() <COLON> expr3 = ConditionalExpression() ] +{ + if (expr3 == null) { + return expr; + } else { + return expr + "?" + expr2 + ":" + expr3; + } +} } -void ConditionalExpression() : -{} +String ConditionalOrExpression() : { - ConditionalOrExpression() [ <HOOK> Expression() <COLON> ConditionalExpression() ] + String expr; + Token operator; + String expr2 = null; + final StringBuffer buff = new StringBuffer(); } - -void ConditionalOrExpression() : -{} { - ConditionalAndExpression() ( (<SC_OR> | <_ORL>) ConditionalAndExpression() )* + expr = ConditionalAndExpression() + { + buff.append(expr); + } + ( + (operator = <SC_OR> | operator = <_ORL>) expr2 = ConditionalAndExpression() + { + buff.append(operator.image); + buff.append(expr2); + } + )* + { + return buff.toString(); + } } -void ConditionalAndExpression() : -{} +String ConditionalAndExpression() : { - ConcatExpression() ( (<SC_AND> | <_ANDL>) ConcatExpression() )* + String expr; + Token operator; + String expr2 = null; + final StringBuffer buff = new StringBuffer(); +} +{ + expr = ConcatExpression() + { + buff.append(expr); + } + ( + (operator = <SC_AND> | operator = <_ANDL>) expr2 = ConcatExpression() + { + buff.append(operator.image); + buff.append(expr2); + } + )* + { + return buff.toString(); + } } -void ConcatExpression() : -{} +String ConcatExpression() : +{ + String expr; + String expr2 = null; + final StringBuffer buff = new StringBuffer(); +} { - InclusiveOrExpression() ( <DOT> InclusiveOrExpression() )* + expr = InclusiveOrExpression() + { + buff.append(expr); + } + ( + <DOT> expr2 = InclusiveOrExpression() + { + buff.append("."); + buff.append(expr2); + } + )* + { + return buff.toString(); + } } -void InclusiveOrExpression() : -{} +String InclusiveOrExpression() : +{ + String expr; + String expr2 = null; + final StringBuffer buff = new StringBuffer(); +} { - ExclusiveOrExpression() ( <BIT_OR> ExclusiveOrExpression() )* + expr = ExclusiveOrExpression() + { + buff.append(expr); + } + ( + <BIT_OR> expr2 = ExclusiveOrExpression() + { + buff.append("|"); + buff.append(expr2); + } + )* + { + return buff.toString(); + } } -void ExclusiveOrExpression() : -{} +String ExclusiveOrExpression() : { - AndExpression() ( <XOR> AndExpression() )* + String expr; + String expr2 = null; + final StringBuffer buff = new StringBuffer(); +} +{ + expr = AndExpression() + { + buff.append(expr); + } + ( + <XOR> expr2 = AndExpression() + { + buff.append("^"); + buff.append(expr2); + } + )* + { + return buff.toString(); + } } -void AndExpression() : -{} +String AndExpression() : { - EqualityExpression() ( <BIT_AND> EqualityExpression() )* + final String expr; + String expr2 = null; + final StringBuffer buff = new StringBuffer(); +} +{ + expr = EqualityExpression() + { + buff.append(expr); + } + ( + <BIT_AND> expr2 = EqualityExpression() + { + buff.append("&"); + buff.append(expr2); + } + )* + { + return buff.toString(); + } } -void EqualityExpression() : -{} +String EqualityExpression() : { - RelationalExpression() ( ( <EQ> | <NE> ) RelationalExpression() )* + String expr; + Token operator; + String expr2; + final StringBuffer buff = new StringBuffer(); +} +{ + expr = RelationalExpression() + {buff.append(expr);} + ( + ( operator = <EQ> + | operator = <DIF> + | operator = <NE> + | operator = <BANGDOUBLEEQUAL> + | operator = <TRIPLEEQUAL> + ) + expr2 = RelationalExpression() + { + buff.append(operator.image); + buff.append(expr2); + } + )* + {return buff.toString();} } -void RelationalExpression() : -{} +String RelationalExpression() : { - ShiftExpression() ( ( <LT> | <GT> | <LE> | <GE> ) ShiftExpression() )* + String expr; + Token operator; + String expr2; + final StringBuffer buff = new StringBuffer(); +} +{ + expr = ShiftExpression() + {buff.append(expr);} + ( + ( operator = <LT> | operator = <GT> | operator = <LE> | operator = <GE> ) expr2 = ShiftExpression() + { + buff.append(operator.image); + buff.append(expr2); + } + )* + {return buff.toString();} } -void ShiftExpression() : -{} +String ShiftExpression() : { - AdditiveExpression() ( ( <LSHIFT> | <RSIGNEDSHIFT> | <RUNSIGNEDSHIFT> ) AdditiveExpression() )* + String expr; + Token operator; + final StringBuffer buff = new StringBuffer(); +} +{ + expr = AdditiveExpression() + {buff.append(expr);} + ( + (operator = <LSHIFT> | operator = <RSIGNEDSHIFT> | operator = <RUNSIGNEDSHIFT> ) expr = AdditiveExpression() + { + buff.append(operator.image); + buff.append(expr); + } + )* + {return buff.toString();} } -void AdditiveExpression() : -{} +String AdditiveExpression() : +{ + String expr; + Token operator; + final StringBuffer buff = new StringBuffer(); +} { - MultiplicativeExpression() ( ( <PLUS> | <MINUS> ) MultiplicativeExpression() )* + expr = MultiplicativeExpression() + {buff.append(expr);} + ( + ( operator = <PLUS> | operator = <MINUS> ) expr = MultiplicativeExpression() + { + buff.append(operator.image); + buff.append(expr); + } + )* + {return buff.toString();} } -void MultiplicativeExpression() : -{} +String MultiplicativeExpression() : +{ + String expr; + Token operator; + final StringBuffer buff = new StringBuffer();} { - UnaryExpression() ( ( <STAR> | <SLASH> | <REM> ) UnaryExpression() )* + expr = UnaryExpression() + {buff.append(expr);} + ( + ( operator = <STAR> | operator = <SLASH> | operator = <REM> ) expr = UnaryExpression() + { + buff.append(operator.image); + buff.append(expr); + } + )* + {return buff.toString();} } -void UnaryExpression() : -{} +/** + * An unary expression starting with @, & or nothing + */ +String UnaryExpression() : { - <AT> UnaryExpression() + String expr; + Token token; + final StringBuffer buff = new StringBuffer(); +} +{ + token = <BIT_AND> expr = UnaryExpressionNoPrefix() + { + if (token == null) { + return expr; + } + return token.image + expr; + } | - ( <PLUS> | <MINUS> ) UnaryExpression() + (<AT> {buff.append("@");})* expr = UnaryExpressionNoPrefix() + {return buff.append(expr).toString();} +} + +String UnaryExpressionNoPrefix() : +{ + String expr; + Token token; +} +{ + ( token = <PLUS> | token = <MINUS> ) expr = UnaryExpression() + { + return token.image + expr; + } | - PreIncrementExpression() + expr = PreIncrementExpression() + {return expr;} | - PreDecrementExpression() + expr = PreDecrementExpression() + {return expr;} | - UnaryExpressionNotPlusMinus() + expr = UnaryExpressionNotPlusMinus() + {return expr;} } -void PreIncrementExpression() : -{} + +String PreIncrementExpression() : +{ +String expr; +} { - <INCR> PrimaryExpression() + <INCR> expr = PrimaryExpression() + {return "++"+expr;} } -void PreDecrementExpression() : -{} +String PreDecrementExpression() : +{ +String expr; +} { - <DECR> PrimaryExpression() + <DECR> expr = PrimaryExpression() + {return "--"+expr;} } -void UnaryExpressionNotPlusMinus() : -{} +String UnaryExpressionNotPlusMinus() : +{ + String expr; +} { - <BANG> UnaryExpression() + <BANG> expr = UnaryExpression() + {return "!" + expr;} | LOOKAHEAD( <LPAREN> Type() <RPAREN> ) - CastExpression() + expr = CastExpression() + {return expr;} | - PostfixExpression() + expr = PostfixExpression() + {return expr;} | - Literal() + expr = Literal() + {return expr;} | - <LPAREN>Expression()<RPAREN> + <LPAREN> expr = Expression()<RPAREN> + {return "("+expr+")";} } -void CastExpression() : -{} +String CastExpression() : { - <LPAREN> Type() <RPAREN> UnaryExpression() +final String type, expr; +} +{ + <LPAREN> type = Type() <RPAREN> expr = UnaryExpression() + {return "(" + type + ")" + expr;} } -void PostfixExpression() : -{} +String PostfixExpression() : { - PrimaryExpression() [ <INCR> | <DECR> ] + String expr; + Token operator = null; +} +{ + expr = PrimaryExpression() [ operator = <INCR> | operator = <DECR> ] + { + if (operator == null) { + return expr; + } + return expr + operator.image; + } } -void PrimaryExpression() : -{} +String PrimaryExpression() : +{ + Token identifier; + String expr; + final StringBuffer buff = new StringBuffer(); +} { LOOKAHEAD(2) - <IDENTIFIER> <STATICCLASSACCESS> ClassIdentifier() (PrimarySuffix())* + identifier = <IDENTIFIER> <STATICCLASSACCESS> expr = ClassIdentifier() + {buff.append(identifier.image).append("::").append(expr);} + ( + expr = PrimarySuffix() + {buff.append(expr);} + )* + {return buff.toString();} | - PrimaryPrefix() ( PrimarySuffix() )* + expr = PrimaryPrefix() {buff.append(expr);} + ( expr = PrimarySuffix() {buff.append(expr);} )* + {return buff.toString();} | - <ARRAY> ArrayInitializer() + expr = ArrayDeclarator() + {return "array" + expr;} } -void PrimaryPrefix() : -{} +String ArrayDeclarator() : { - <IDENTIFIER> + final String expr; +} +{ + <ARRAY> expr = ArrayInitializer() + {return "array" + expr;} +} + +String PrimaryPrefix() : +{ + String expr; + Token token = null; +} +{ + token = <IDENTIFIER> + {return token.image;} | - <NEW> ClassIdentifier() + <NEW> expr = ClassIdentifier() + { + return "new " + expr; + } | - VariableDeclaratorId() + expr = VariableDeclaratorId() + {return expr;} } -void ClassIdentifier(): -{} +String ClassIdentifier(): +{ + String expr; + Token token; +} { - <IDENTIFIER> + token = <IDENTIFIER> + {return token.image;} | - VariableDeclaratorId() + expr = VariableDeclaratorId() + {return expr;} } -void PrimarySuffix() : -{} +String PrimarySuffix() : { - Arguments() + String expr; +} +{ + expr = Arguments() + {return expr;} | - VariableSuffix() + expr = VariableSuffix() + {return expr;} } -void VariableSuffix() : -{} +String VariableSuffix() : { - <CLASSACCESS> VariableName() + String expr = null; +} +{ + <CLASSACCESS> expr = VariableName() + {return "->" + expr;} | - <LBRACKET> [ Expression() ] <RBRACKET> + <LBRACKET> [ expr = Expression() ] + try { + <RBRACKET> + } catch (ParseException e) { + errorMessage = "']' expected"; + errorLevel = ERROR; + throw e; + } + { + if(expr == null) { + return "[]"; + } + return "[" + expr + "]"; + } } -void Literal() : -{} +String Literal() : +{ + String expr; + Token token; +} { - <INTEGER_LITERAL> + token = <INTEGER_LITERAL> + {return token.image;} | - <FLOATING_POINT_LITERAL> + token = <FLOATING_POINT_LITERAL> + {return token.image;} | - <STRING_LITERAL> + token = <STRING_LITERAL> + {return token.image;} | - BooleanLiteral() + expr = BooleanLiteral() + {return expr;} | - NullLiteral() + expr = NullLiteral() + {return expr;} } -void BooleanLiteral() : +String BooleanLiteral() : {} { <TRUE> + {return "true";} | <FALSE> + {return "false";} } -void NullLiteral() : +String NullLiteral() : {} { <NULL> + {return "null";} } -void Arguments() : -{} +String Arguments() : { - <LPAREN> [ ArgumentList() ] <RPAREN> +String expr = null; +} +{ + <LPAREN> [ expr = ArgumentList() ] + try { + <RPAREN> + } catch (ParseException e) { + errorMessage = "')' expected to close the argument list"; + errorLevel = ERROR; + throw e; + } + { + if (expr == null) { + return "()"; + } + return "(" + expr + ")"; + } } -void ArgumentList() : -{} +String ArgumentList() : { - Expression() ( <COMMA> Expression() )* +String expr; +final StringBuffer buff = new StringBuffer(); +} +{ + expr = Expression() + {buff.append(expr);} + ( <COMMA> + try { + expr = Expression() + } catch (ParseException e) { + errorMessage = "expression expected after a comma in argument list"; + errorLevel = ERROR; + throw e; + } + { + buff.append(",").append("expr"); + } + )* + {return buff.toString();} } /* @@ -923,7 +1531,14 @@ void Statement() : {} { LOOKAHEAD(2) - Expression() (<SEMICOLON> | "?>") + Expression() + try { + (<SEMICOLON> | "?>") + } catch (ParseException e) { + errorMessage = "';' expected"; + errorLevel = ERROR; + throw e; + } | LOOKAHEAD(2) LabeledStatement() @@ -951,6 +1566,8 @@ void Statement() : | ForStatement() | + ForeachStatement() +| BreakStatement() | ContinueStatement() @@ -959,7 +1576,7 @@ void Statement() : | EchoStatement() | - IncludeStatement() + [<AT>] IncludeStatement() | StaticStatement() | @@ -967,21 +1584,83 @@ void Statement() : } void IncludeStatement() : -{} { - <REQUIRE> Expression() (<SEMICOLON> | "?>") + String expr; + final int pos = jj_input_stream.bufpos; +} +{ + <REQUIRE> + expr = Expression() + { + if (currentSegment != null) { + currentSegment.add(new PHPReqIncDeclaration(currentSegment, "require",pos,expr)); + } + } + try { + (<SEMICOLON> | "?>") + } catch (ParseException e) { + errorMessage = "';' expected"; + errorLevel = ERROR; + throw e; + } | - <REQUIRE_ONCE> Expression() (<SEMICOLON> | "?>") + <REQUIRE_ONCE> + expr = Expression() + { + if (currentSegment != null) { + currentSegment.add(new PHPReqIncDeclaration(currentSegment, "require_once",pos,expr)); + } + } + try { + (<SEMICOLON> | "?>") + } catch (ParseException e) { + errorMessage = "';' expected"; + errorLevel = ERROR; + throw e; + } | - <INCLUDE> Expression() (<SEMICOLON> | "?>") + <INCLUDE> + expr = Expression() + { + if (currentSegment != null) { + currentSegment.add(new PHPReqIncDeclaration(currentSegment, "include",pos,expr)); + } + } + try { + (<SEMICOLON> | "?>") + } catch (ParseException e) { + errorMessage = "';' expected"; + errorLevel = ERROR; + throw e; + } | - <INCLUDE_ONCE> Expression() (<SEMICOLON> | "?>") + <INCLUDE_ONCE> + expr = Expression() + { + if (currentSegment != null) { + currentSegment.add(new PHPReqIncDeclaration(currentSegment, "include_once",pos,expr)); + } + } + try { + (<SEMICOLON> | "?>") + } catch (ParseException e) { + errorMessage = "';' expected"; + errorLevel = ERROR; + throw e; + } } -void PrintExpression() : -{} +String PrintExpression() : { - <PRINT> Expression() + final StringBuffer buff = new StringBuffer("print "); + String expr; +} +{ + <PRINT> expr = Expression() + { + buff.append(expr); + return buff.toString(); + } } void EchoStatement() : @@ -1000,13 +1679,27 @@ void EchoStatement() : void GlobalStatement() : {} { - <GLOBAL> VariableDeclaratorId() (<COMMA> VariableDeclaratorId())* (<SEMICOLON> | "?>") + <GLOBAL> VariableDeclaratorId() (<COMMA> VariableDeclaratorId())* + try { + (<SEMICOLON> | "?>") + } catch (ParseException e) { + errorMessage = "';' expected"; + errorLevel = ERROR; + throw e; + } } void StaticStatement() : {} { - <STATIC> VariableDeclarator() (<COMMA> VariableDeclarator())* (<SEMICOLON> | "?>") + <STATIC> VariableDeclarator() (<COMMA> VariableDeclarator())* + try { + (<SEMICOLON> | "?>") + } catch (ParseException e) { + errorMessage = "';' expected"; + errorLevel = ERROR; + throw e; + } } void LabeledStatement() : @@ -1018,7 +1711,15 @@ void LabeledStatement() : void Block() : {} { - <LBRACE> ( BlockStatement() )* <RBRACE> + try { + <LBRACE> + } catch (ParseException e) { + errorMessage = "'{' expected"; + errorLevel = ERROR; + throw e; + } + ( BlockStatement() )* + <RBRACE> } void BlockStatement() : @@ -1044,11 +1745,6 @@ void EmptyStatement() : } void StatementExpression() : -/* - * The last expansion of this production accepts more than the legal - * Java expansions for StatementExpression. This expansion does not - * use PostfixExpression for performance reasons. - */ {} { PreIncrementExpression() @@ -1087,9 +1783,12 @@ void IfStatement() : * else's to the innermost if statement. The LOOKAHEAD specification * is to tell JavaCC that we know what we are doing. */ -{} { - <IF> Condition("if") Statement() [ LOOKAHEAD(1) ElseIfStatement() ] [ LOOKAHEAD(1) <ELSE> Statement() ] + Token token; + final int pos = jj_input_stream.bufpos; +} +{ + token = <IF> Condition("if") IfStatement0(pos,pos+token.image.length()) } void Condition(String keyword) : @@ -1112,6 +1811,52 @@ void Condition(String keyword) : } } +void IfStatement0(int start,int end) : +{ +} +{ + <COLON> (Statement())* (ElseIfStatementColon())* [ElseStatementColon()] + + {try { + setMarker(fileToParse, + "Ugly syntax detected, you should if () {...} instead of if (): ... endif;", + start, + end, + INFO, + "Line " + token.beginLine); + } catch (CoreException e) { + PHPeclipsePlugin.log(e); + }} + try { + <ENDIF> + } catch (ParseException e) { + errorMessage = "'endif' expected"; + errorLevel = ERROR; + throw e; + } + try { + <SEMICOLON> + } catch (ParseException e) { + errorMessage = "';' expected 'endif' keyword"; + errorLevel = ERROR; + throw e; + } +| + Statement() ( LOOKAHEAD(1) ElseIfStatement() )* [ LOOKAHEAD(1) <ELSE> Statement() ] +} + +void ElseIfStatementColon() : +{} +{ + <ELSEIF> Condition("elseif") <COLON> (Statement())* +} + +void ElseStatementColon() : +{} +{ + <ELSE> <COLON> (Statement())* +} + void ElseIfStatement() : {} { @@ -1119,15 +1864,42 @@ void ElseIfStatement() : } void WhileStatement() : -{} { - <WHILE> Condition("while") WhileStatement0() + Token token; + final int pos = jj_input_stream.bufpos; +} +{ + token = <WHILE> Condition("while") WhileStatement0(pos,pos + token.image.length()) } -void WhileStatement0() : +void WhileStatement0(final int start, final int end) : {} { - <COLON> (Statement())* <ENDWHILE> (<SEMICOLON> | "?>") + <COLON> (Statement())* + {try { + setMarker(fileToParse, + "Ugly syntax detected, you should while () {...} instead of while (): ... endwhile;", + start, + end, + INFO, + "Line " + token.beginLine); + } catch (CoreException e) { + PHPeclipsePlugin.log(e); + }} + try { + <ENDWHILE> + } catch (ParseException e) { + errorMessage = "'endwhile' expected"; + errorLevel = ERROR; + throw e; + } + try { + (<SEMICOLON> | "?>") + } catch (ParseException e) { + errorMessage = "';' expected after 'endwhile' keyword"; + errorLevel = ERROR; + throw e; + } | Statement() } @@ -1135,13 +1907,112 @@ void WhileStatement0() : void DoStatement() : {} { - <DO> Statement() <WHILE> Condition("while") (<SEMICOLON> | "?>") + <DO> Statement() <WHILE> Condition("while") + try { + (<SEMICOLON> | "?>") + } catch (ParseException e) { + errorMessage = "';' expected"; + errorLevel = ERROR; + throw e; + } } -void ForStatement() : +void ForeachStatement() : {} { - <FOR> <LPAREN> [ ForInit() ] <SEMICOLON> [ Expression() ] <SEMICOLON> [ ForUpdate() ] <RPAREN> Statement() + <FOREACH> + try { + <LPAREN> + } catch (ParseException e) { + errorMessage = "'(' expected after 'foreach' keyword"; + errorLevel = ERROR; + throw e; + } + try { + Variable() + } catch (ParseException e) { + errorMessage = "variable expected"; + errorLevel = ERROR; + throw e; + } + try { + <AS> + } catch (ParseException e) { + errorMessage = "'as' expected"; + errorLevel = ERROR; + throw e; + } + try { + Variable() + } catch (ParseException e) { + errorMessage = "variable expected"; + errorLevel = ERROR; + throw e; + } + [ <ARRAYASSIGN> Expression() ] + try { + <RPAREN> + } catch (ParseException e) { + errorMessage = "')' expected after 'foreach' keyword"; + errorLevel = ERROR; + throw e; + } + try { + Statement() + } catch (ParseException e) { + if (errorMessage != null) throw e; + errorMessage = "statement expected"; + errorLevel = ERROR; + throw e; + } +} + +void ForStatement() : +{ +Token token; +final int pos = jj_input_stream.bufpos; +} +{ + token = <FOR> + try { + <LPAREN> + } catch (ParseException e) { + errorMessage = "'(' expected after 'for' keyword"; + errorLevel = ERROR; + throw e; + } + [ ForInit() ] <SEMICOLON> [ Expression() ] <SEMICOLON> [ ForUpdate() ] <RPAREN> + ( + Statement() + | + <COLON> (Statement())* + { + try { + setMarker(fileToParse, + "Ugly syntax detected, you should for () {...} instead of for (): ... endfor;", + pos, + pos+token.image.length(), + INFO, + "Line " + token.beginLine); + } catch (CoreException e) { + PHPeclipsePlugin.log(e); + } + } + try { + <ENDFOR> + } catch (ParseException e) { + errorMessage = "'endfor' expected"; + errorLevel = ERROR; + throw e; + } + try { + <SEMICOLON> + } catch (ParseException e) { + errorMessage = "';' expected 'endfor' keyword"; + errorLevel = ERROR; + throw e; + } + ) } void ForInit() :