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 306f21d..35b3173 100644 --- a/net.sourceforge.phpeclipse/src/test/PHPParser.jj +++ b/net.sourceforge.phpeclipse/src/test/PHPParser.jj @@ -29,132 +29,170 @@ import org.eclipse.ui.texteditor.MarkerUtilities; import org.eclipse.jface.preference.IPreferenceStore; import java.util.Hashtable; +import java.util.Enumeration; import java.io.StringReader; +import java.io.*; 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.*; +import net.sourceforge.phpdt.internal.compiler.ast.*; /** * A new php parser. - * This php parser is inspired by the Java 1.2 grammar example + * This php parser is inspired by the Java 1.2 grammar example * given with JavaCC. You can get JavaCC at http://www.webgain.com * You can test the parser with the PHPParserTestCase2.java * @author Matthieu Casanova */ -public class PHPParser extends PHPParserSuperclass { +public final class PHPParser extends PHPParserSuperclass { + /** The file that is parsed. */ private static IFile fileToParse; - /** The current segment */ + /** 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; + static PHPOutlineInfo outlineInfo; + + private static PHPFunctionDeclaration currentFunction; + private static boolean assigning; + + /** The error level of the current ParseException. */ private static int errorLevel = ERROR; + /** The message of the current ParseException. If it's null it's because the parse exception wasn't handled */ private static String errorMessage; - public PHPParser() { - } + private static int errorStart = -1; + private static int errorEnd = -1; - public void setFileToParse(IFile fileToParse) { + //ast stack + private final static int AstStackIncrement = 100; + /** The stack of node. */ + private static AstNode[] astStack; + /** The cursor in expression stack. */ + private static int expressionPtr; + + public final void setFileToParse(final IFile fileToParse) { this.fileToParse = fileToParse; } - public PHPParser(IFile fileToParse) { + public PHPParser() { + } + + public PHPParser(final IFile fileToParse) { this(new StringReader("")); this.fileToParse = fileToParse; } - public void phpParserTester(String strEval) throws CoreException, ParseException { + public static final void phpParserTester(final String strEval) throws CoreException, ParseException { PHPParserTokenManager.SwitchTo(PHPParserTokenManager.PHPPARSING); - StringReader stream = new StringReader(strEval); + final StringReader stream = new StringReader(strEval); if (jj_input_stream == null) { jj_input_stream = new SimpleCharStream(stream, 1, 1); } ReInit(new StringReader(strEval)); + astStack = new AstNode[AstStackIncrement]; phpTest(); } - public void htmlParserTester(String strEval) throws CoreException, ParseException { - StringReader stream = new StringReader(strEval); + public static final void htmlParserTester(final File fileName) throws CoreException, ParseException { + try { + final Reader stream = new FileReader(fileName); + if (jj_input_stream == null) { + jj_input_stream = new SimpleCharStream(stream, 1, 1); + } + ReInit(stream); + astStack = new AstNode[AstStackIncrement]; + phpFile(); + } catch (FileNotFoundException e) { + e.printStackTrace(); //To change body of catch statement use Options | File Templates. + } + } + + public static final void htmlParserTester(final String strEval) throws CoreException, ParseException { + final StringReader stream = new StringReader(strEval); if (jj_input_stream == null) { jj_input_stream = new SimpleCharStream(stream, 1, 1); } ReInit(stream); + astStack = new AstNode[AstStackIncrement]; phpFile(); } - public PHPOutlineInfo parseInfo(Object parent, String s) { + public final PHPOutlineInfo parseInfo(final Object parent, final String s) { outlineInfo = new PHPOutlineInfo(parent); currentSegment = outlineInfo.getDeclarations(); - StringReader stream = new StringReader(s); + final StringReader stream = new StringReader(s); if (jj_input_stream == null) { jj_input_stream = new SimpleCharStream(stream, 1, 1); } ReInit(stream); + astStack = new AstNode[AstStackIncrement]; 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"; + errorStart = jj_input_stream.getPosition(); + errorEnd = errorStart + 1; } + 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; + /** + * Create marker for the parse error + * @param e the ParseException + */ + private static void setMarker(final ParseException e) { + try { + if (errorStart == -1) { + setMarker(fileToParse, + errorMessage, + jj_input_stream.tokenBegin, + jj_input_stream.tokenBegin + e.currentToken.image.length(), + errorLevel, + "Line " + e.currentToken.beginLine); + } else { + setMarker(fileToParse, + errorMessage, + errorStart, + errorEnd, + errorLevel, + "Line " + e.currentToken.beginLine); + errorStart = -1; + errorEnd = -1; } - MarkerUtilities.setLineNumber(attributes, lineNumber); - MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM); + } catch (CoreException e2) { + PHPeclipsePlugin.log(e2); } } /** * Create markers according to the external parser output */ - private static void createMarkers(String output, IFile file) throws CoreException { + private static void createMarkers(final String output, final IFile file) throws CoreException { // delete all markers file.deleteMarkers(IMarker.PROBLEM, false, 0); int indx = 0; - int brIndx = 0; + int brIndx; boolean flag = true; while ((brIndx = output.indexOf("
", indx)) != -1) { // newer php error output (tested with 4.2.3) @@ -171,7 +209,10 @@ public class PHPParser extends PHPParserSuperclass { } } - private static void scanLine(String output, IFile file, int indx, int brIndx) throws CoreException { + private static void scanLine(final String output, + final IFile file, + final int indx, + final int brIndx) throws CoreException { String current; StringBuffer lineNumberBuffer = new StringBuffer(10); char ch; @@ -209,17 +250,17 @@ public class PHPParser extends PHPParserSuperclass { } } - public void parse(String s) throws CoreException { - ReInit(new StringReader(s)); + public final void parse(final String s) throws CoreException { + final StringReader stream = new StringReader(s); + if (jj_input_stream == null) { + jj_input_stream = new SimpleCharStream(stream, 1, 1); + } + ReInit(stream); + astStack = new AstNode[AstStackIncrement]; try { parse(); } catch (ParseException e) { - if (errorMessage == null) { - PHPeclipsePlugin.log(e); - } else { - setMarker(errorMessage, e.currentToken.beginLine, errorLevel); - errorMessage = null; - } + processParseException(e); } } @@ -227,15 +268,15 @@ public class PHPParser extends PHPParserSuperclass { * Call the php parse command ( php -l -f <filename> ) * and create markers according to the external parser output */ - public static void phpExternalParse(IFile file) { - IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore(); - String filename = file.getLocation().toString(); + public static void phpExternalParse(final IFile file) { + final IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore(); + final String filename = file.getLocation().toString(); - String[] arguments = { filename }; - MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF)); - String command = form.format(arguments); + final String[] arguments = { filename }; + final MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF)); + final String command = form.format(arguments); - String parserResult = PHPStartApacheAction.getParserOutput(command, "External parser: "); + final String parserResult = PHPStartApacheAction.getParserOutput(command, "External parser: "); try { // parse the buffer to find the errors and warnings @@ -245,7 +286,7 @@ public class PHPParser extends PHPParserSuperclass { } } - public void parse() throws ParseException { + private static final void parse() throws ParseException { phpFile(); } } @@ -254,7 +295,9 @@ PARSER_END(PHPParser) TOKEN : { - : PHPPARSING + : PHPPARSING +| : PHPPARSING +| "> : DEFAULT } +/* Skip any character if we are not in php mode */ SKIP : { < ~[] > @@ -269,7 +313,6 @@ PARSER_END(PHPParser) /* WHITE SPACE */ - SKIP : { " " @@ -280,20 +323,25 @@ PARSER_END(PHPParser) } /* COMMENTS */ - - MORE : + SPECIAL_TOKEN : { "//" : IN_SINGLE_LINE_COMMENT | + "#" : IN_SINGLE_LINE_COMMENT +| <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT | "/*" : IN_MULTI_LINE_COMMENT } - -SPECIAL_TOKEN : + SPECIAL_TOKEN : { - " > : PHPPARSING + : PHPPARSING +} + + SPECIAL_TOKEN : +{ + " > : DEFAULT } @@ -324,72 +372,76 @@ MORE : | | | +| +| } /* LANGUAGE CONSTRUCT */ TOKEN : { - -| -| -| -| -| -| -| -| "> -| -| "> + +| +| +| +| +| +| +| +| "> +| +| "> } /* RESERVED WORDS AND LITERALS */ TOKEN : { - < BREAK: "break" > -| < CASE: "case" > -| < CONST: "const" > -| < CONTINUE: "continue" > -| < _DEFAULT: "default" > -| < DO: "do" > -| < EXTENDS: "extends" > -| < FALSE: "false" > -| < FOR: "for" > -| < GOTO: "goto" > -| < NEW: "new" > -| < NULL: "null" > -| < RETURN: "return" > -| < SUPER: "super" > -| < SWITCH: "switch" > -| < THIS: "this" > -| < TRUE: "true" > -| < WHILE: "while" > -| < ENDWHILE : "endwhile" > + +| +| +| <_DEFAULT : "default"> +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| } /* TYPES */ - TOKEN : { - -| -| + +| +| | -| -| -| -| +| +| +| +| | } TOKEN : { - < _ORL : "OR" > -| < _ANDL: "AND"> + <_ORL : "OR"> +| <_ANDL : "AND"> } /* LITERALS */ - TOKEN : { < INTEGER_LITERAL: @@ -416,20 +468,29 @@ MORE : < STRING_LITERAL: ( | | )> | < STRING_1: "\"" - ( (~["\""]) + ( + ~["\"","{","}"] | "\\\"" + | "\\" + | "{" ~["\""] "}" )* "\"" > | < STRING_2: "'" - ( (~["'"]))* + ( + ~["'"] + | "\\'" + )* "'" > | < STRING_3: "`" - ( (~["`"]))* + ( + ~["`"] + | "\\`" + )* "`" > } @@ -449,7 +510,7 @@ MORE : > | < #SPECIAL: - "_" + "_" | ["\u007f"-"\u00ff"] > } @@ -457,74 +518,80 @@ MORE : TOKEN : { - < LPAREN: "(" > -| < RPAREN: ")" > -| < LBRACE: "{" > -| < RBRACE: "}" > -| < LBRACKET: "[" > -| < RBRACKET: "]" > -| < SEMICOLON: ";" > -| < COMMA: "," > -| < DOT: "." > + +| +| +| +| +| +| +| +| } -/* OPERATORS */ +/* COMPARATOR */ TOKEN : { - -| -| < 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: ">>>=" > + "> +| +| +| ="> +| "> +| +| } +/* ASSIGNATION */ TOKEN : { - < DOLLAR_ID: > + +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| >"> +| >>"> +| >="> +} -/* - * Program structuring syntax follows. - */ + TOKEN : +{ + < DOLLAR_ID: > +} void phpTest() : {} @@ -536,8 +603,60 @@ void phpTest() : void phpFile() : {} { - ( Php() )* - + try { + (PhpBlock())* + + } catch (TokenMgrError e) { + PHPeclipsePlugin.log(e); + errorStart = SimpleCharStream.getPosition(); + errorEnd = errorStart + 1; + errorMessage = e.getMessage(); + errorLevel = ERROR; + throw generateParseException(); + } +} + +/** + * A php block is a + * or + * or + */ +void PhpBlock() : +{ + final int start = jj_input_stream.getPosition(); +} +{ + phpEchoBlock() +| + [ + | + {try { + setMarker(fileToParse, + "You should use ' + } catch (ParseException e) { + errorMessage = "'?>' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } +} + +void phpEchoBlock() : +{} +{ + Expression() [ ] } void Php() : @@ -548,507 +667,1257 @@ void Php() : void ClassDeclaration() : { - PHPClassDeclaration classDeclaration; - Token className; - int pos = jj_input_stream.bufpos; + final PHPClassDeclaration classDeclaration; + final Token className; + final int pos; } { - className = [ ] + + try { + {pos = jj_input_stream.getPosition();} + className = + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', identifier expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + [ + + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', identifier expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + ] { - classDeclaration = new PHPClassDeclaration(currentSegment,className.image,pos); - currentSegment.add(classDeclaration); - currentSegment = classDeclaration; + if (currentSegment != null) { + classDeclaration = new PHPClassDeclaration(currentSegment,className.image,pos); + currentSegment.add(classDeclaration); + currentSegment = classDeclaration; + } } ClassBody() { - currentSegment = (PHPSegmentWithChildren) currentSegment.getParent(); + if (currentSegment != null) { + currentSegment = (PHPSegmentWithChildren) currentSegment.getParent(); + } } } void ClassBody() : {} { - ( ClassBodyDeclaration() )* + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image + "', '{' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + ( ClassBodyDeclaration() )* + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', 'var', 'function' or '}' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } } +/** + * A class can contain only methods and fields. + */ void ClassBodyDeclaration() : {} { MethodDeclaration() -| - FieldDeclaration() +| FieldDeclaration() } +/** + * A class field declaration : it's var VariableDeclarator() (, VariableDeclarator())*;. + */ void FieldDeclaration() : -{} { - VariableDeclarator() ( VariableDeclarator() )* + PHPVarDeclaration variableDeclaration; +} +{ + variableDeclaration = VariableDeclarator() + { + outlineInfo.addVariable(variableDeclaration.getVariable().getName()); + if (currentSegment != null) { + currentSegment.add(variableDeclaration); + } + } + ( + variableDeclaration = VariableDeclarator() + { + if (currentSegment != null) { + currentSegment.add(variableDeclaration); + } + } + )* + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected after variable declaration"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } } -void VariableDeclarator() : -{} +PHPVarDeclaration VariableDeclarator() : +{ + final String varName, varValue; + final int pos = jj_input_stream.getPosition(); +} { - VariableDeclaratorId() [ VariableInitializer() ] + varName = VariableDeclaratorId() + [ + + try { + varValue = VariableInitializer() + {return new PHPVarDeclaration(currentSegment,varName,pos,varValue);} + } catch (ParseException e) { + errorMessage = "Literal expression expected in variable initializer"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + ] + {return new PHPVarDeclaration(currentSegment,varName,pos);} } -void VariableDeclaratorId() : -{} +String VariableDeclaratorId() : +{ + String expr; + final StringBuffer buff = new StringBuffer(); +} { - Variable() ( LOOKAHEAD(2) VariableSuffix() )* + 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; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } } -void Variable(): -{} +String Variable(): { - ( Expression() ) * + String expr = null; + final Token token; +} +{ + token = [ expr = Expression() ] + { + if (expr == null && !assigning) { + if (currentFunction != null) { + PHPVarDeclaration var = currentFunction.getParameter(token.image.substring(1)); + if (var != null) { + var.getVariable().setUsed(true); + } + } + return token.image.substring(1); + } + return token + "{" + expr + "}"; + } | - VariableName() + expr = VariableName() + {return expr;} } -void VariableName(): -{} +String VariableName(): +{ +String expr = null; +final Token token; +} { - Expression() + expr = Expression() + {return "{"+expr+"}";} +| + token = [ expr = Expression() ] + { + if (expr == null) { + if (currentFunction != null) { + PHPVarDeclaration var = currentFunction.getParameter(token.image); + if (var != null) { + var.getVariable().setUsed(true); + } + } + return token.image; + } + return token + "{" + expr + "}"; + } | - ( Expression() ) * + expr = VariableName() + { + if (currentFunction != null) { + PHPVarDeclaration var = currentFunction.getParameter(expr); + if (var != null) { + var.getVariable().setUsed(true); + } + } + return "$" + expr; + } | - VariableName() + token = + { + if (currentFunction != null) { + PHPVarDeclaration var = currentFunction.getParameter(token.image.substring(1)); + if (var != null) { + var.getVariable().setUsed(true); + } + } + return token.image + expr; + } +/*| pas besoin ? + token = [expr = VariableName()] + { + if (expr == null) { + return token.image; + } + return token.image + expr; + }*/ } -void VariableInitializer() : -{} +String VariableInitializer() : { - Expression() + final String expr; + final Token token; +} +{ + expr = Literal() + {return expr;} +| + (token = | token = ) + {return "-" + token.image;} +| + (token = | token = ) + {return "+" + token.image;} +| + expr = ArrayDeclarator() + {return expr;} +| + token = + {return token.image;} } -void ArrayVariable() : -{} +String ArrayVariable() : +{ +String expr; +final StringBuffer buff = new StringBuffer(); +} { - Expression() ( Expression())* + expr = Expression() + {buff.append(expr);} + [ expr = Expression() + {buff.append("=>").append(expr);}] + {return buff.toString();} } -void ArrayInitializer() : -{} +String ArrayInitializer() : +{ +String expr; +final StringBuffer buff = new StringBuffer("("); +} { - [ ArrayVariable() ( LOOKAHEAD(2) ArrayVariable() )* ] + [ expr = ArrayVariable() + {buff.append(expr);} + ( LOOKAHEAD(2) expr = ArrayVariable() + {buff.append(",").append(expr);} + )* + ] + [ {buff.append(",");}] + + { + buff.append(")"); + return buff.toString(); + } } +/** + * A Method Declaration. + * function MetodDeclarator() Block() + */ void MethodDeclaration() : { - PHPFunctionDeclaration functionDeclaration; + final PHPFunctionDeclaration functionDeclaration; + Token functionToken; } { - functionDeclaration = MethodDeclarator() + functionToken = + try { + functionDeclaration = MethodDeclarator() + {outlineInfo.addVariable(functionDeclaration.getName());} + } catch (ParseException e) { + if (errorMessage != null) { + throw e; + } + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function identifier expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } { - currentSegment.add(functionDeclaration); - currentSegment = functionDeclaration; + if (currentSegment != null) { + currentSegment.add(functionDeclaration); + currentSegment = functionDeclaration; + } + currentFunction = functionDeclaration; } - ( Block() | ) + Block() { - currentSegment = (PHPSegmentWithChildren) currentSegment.getParent(); + Hashtable parameters = currentFunction.getParameters(); + Enumeration vars = parameters.elements(); + while (vars.hasMoreElements()) { + PHPVarDeclaration o = (PHPVarDeclaration) vars.nextElement(); + if (!o.getVariable().isUsed()) { + try { + setMarker(fileToParse, + "Parameter "+o.getVariable().getName()+" is never used in function", + functionToken.beginLine, + WARNING, + "Line " + token.beginLine); + } catch (CoreException e) { + PHPeclipsePlugin.log(e); + } + } + } + currentFunction = null; + if (currentSegment != null) { + currentSegment = (PHPSegmentWithChildren) currentSegment.getParent(); + } } } +/** + * A MethodDeclarator. + * [&] IDENTIFIER(parameters ...). + * @return a function description for the outline + */ PHPFunctionDeclaration MethodDeclarator() : { - Token bit_and = null; - Token identifier; - StringBuffer methodDeclaration = new StringBuffer(); - String formalParameters; - int pos = jj_input_stream.bufpos; + final Token identifier; + final StringBuffer methodDeclaration = new StringBuffer(); + final Hashtable formalParameters; + final int pos = jj_input_stream.getPosition(); } { - [ bit_and = ] - identifier = FormalParameters() + [ {methodDeclaration.append("&");} ] + identifier = + formalParameters = FormalParameters() { - if (bit_and != null) { - methodDeclaration.append("&"); - } methodDeclaration.append(identifier); - return new PHPFunctionDeclaration(currentSegment,methodDeclaration.toString(),pos); + return new PHPFunctionDeclaration(currentSegment,methodDeclaration.toString(),pos,formalParameters); } } -void FormalParameters() : -{} +/** + * FormalParameters follows method identifier. + * (FormalParameter()) + */ +Hashtable FormalParameters() : +{ + String expr; + final StringBuffer buff = new StringBuffer("("); + PHPVarDeclaration var; + final Hashtable parameters = new Hashtable(); +} { - [ FormalParameter() ( FormalParameter() )* ] + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', '(' expected after function identifier"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + [ var = FormalParameter() + {parameters.put(var.getVariable().getName(),var);} + ( + var = FormalParameter() + {parameters.put(var.getVariable().getName(),var);} + )* + ] + try { + + } catch (ParseException e) { + errorMessage = "')' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + {return parameters;} } -void FormalParameter() : -{} +/** + * A formal parameter. + * $varname[=value] (,$varname[=value]) + */ +PHPVarDeclaration FormalParameter() : { - [] VariableDeclarator() + final PHPVarDeclaration variableDeclaration; + Token token = null; +} +{ + [token = ] variableDeclaration = VariableDeclarator() + { + if (token != null) { + variableDeclaration.getVariable().setReference(true); + } + return variableDeclaration; + } } -void Type() : +String Type() : {} { - -| - -| - -| - -| - -| - -| - -| - + {return "string";} +| {return "bool";} +| {return "boolean";} +| {return "real";} +| {return "double";} +| {return "float";} +| {return "int";} +| {return "integer";} +| {return "object";} } -/* - * Expression syntax follows. - */ +String Expression() : +{ + final String expr; + final String assignOperator; + final String expr2; +} +{ + expr = PrintExpression() {return expr;} +| expr = ListExpression() {return expr;} +| LOOKAHEAD(varAssignation()) + expr = varAssignation() {return expr;} +| expr = ConditionalExpression() {return expr;} +} -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. +/** + * A Variable assignation. + * varName (an assign operator) any expression */ -{} +String varAssignation() : { - PrintExpression() -| - ConditionalExpression() - [ - AssignmentOperator() Expression() - ] + String varName,assignOperator,expr2; + PHPVarDeclaration variable; + final int pos = SimpleCharStream.getPosition(); +} +{ + varName = VariableDeclaratorId() + assignOperator = AssignmentOperator() + try { + expr2 = Expression() + } catch (ParseException e) { + if (errorMessage != null) { + throw e; + } + errorMessage = "expression expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + {return varName + assignOperator + expr2;} } -void AssignmentOperator() : +String AssignmentOperator() : {} { - | | | | | | | | | | | | + {return "=";} +| {return "*=";} +| {return "/=";} +| {return "%=";} +| {return "+=";} +| {return "-=";} +| {return "<<=";} +| {return ">>=";} +| {return "&=";} +| {return "|=";} +| {return "|=";} +| {return ".=";} +| {return "~=";} } -void ConditionalExpression() : -{} +String ConditionalExpression() : { - ConditionalOrExpression() [ Expression() ConditionalExpression() ] + final String expr; + String expr2 = null; + String expr3 = null; +} +{ + expr = ConditionalOrExpression() [ expr2 = Expression() expr3 = ConditionalExpression() ] +{ + if (expr3 == null) { + return expr; + } else { + return expr + "?" + expr2 + ":" + expr3; + } +} } -void ConditionalOrExpression() : -{} +String ConditionalOrExpression() : { - ConditionalAndExpression() ( ( | <_ORL>) ConditionalAndExpression() )* + String expr; + Token operator; + final StringBuffer buff = new StringBuffer(); +} +{ + expr = ConditionalAndExpression() + {buff.append(expr);} + ( + (operator = | operator = <_ORL>) expr = ConditionalAndExpression() + { + buff.append(operator.image); + buff.append(expr); + } + )* + { + return buff.toString(); + } } -void ConditionalAndExpression() : -{} +String ConditionalAndExpression() : { - ConcatExpression() ( ( | <_ANDL>) ConcatExpression() )* + String expr; + Token operator; + final StringBuffer buff = new StringBuffer(); +} +{ + expr = ConcatExpression() + {buff.append(expr);} + ( + (operator = | operator = <_ANDL>) expr = ConcatExpression() + { + buff.append(operator.image); + buff.append(expr); + } + )* + {return buff.toString();} } -void ConcatExpression() : -{} +String ConcatExpression() : +{ + String expr; + final StringBuffer buff = new StringBuffer(); +} { - InclusiveOrExpression() ( InclusiveOrExpression() )* + expr = InclusiveOrExpression() + {buff.append(expr);} + ( + expr = InclusiveOrExpression() + {buff.append(".").append(expr);} + )* + {return buff.toString();} } -void InclusiveOrExpression() : -{} +String InclusiveOrExpression() : +{ + String expr; + final StringBuffer buff = new StringBuffer(); +} { - ExclusiveOrExpression() ( ExclusiveOrExpression() )* + expr = ExclusiveOrExpression() + {buff.append(expr);} + ( + expr = ExclusiveOrExpression() + {buff.append("|").append(expr);} + )* + {return buff.toString();} } -void ExclusiveOrExpression() : -{} +String ExclusiveOrExpression() : +{ + String expr; + final StringBuffer buff = new StringBuffer(); +} { - AndExpression() ( AndExpression() )* + expr = AndExpression() + { + buff.append(expr); + } + ( + expr = AndExpression() + { + buff.append("^"); + buff.append(expr); + } + )* + { + return buff.toString(); + } } -void AndExpression() : -{} +String AndExpression() : +{ + String expr; + final StringBuffer buff = new StringBuffer(); +} { - EqualityExpression() ( EqualityExpression() )* + expr = EqualityExpression() + { + buff.append(expr); + } + ( + expr = EqualityExpression() + { + buff.append("&").append(expr); + } + )* + {return buff.toString();} } -void EqualityExpression() : -{} +String EqualityExpression() : +{ + String expr; + Token operator; + final StringBuffer buff = new StringBuffer(); +} +{ + expr = RelationalExpression() + {buff.append(expr);} + ( + ( operator = + | operator = + | operator = + | operator = + | operator = + ) + try { + expr = RelationalExpression() + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', expression expected after '"+operator.image+"'"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + { + buff.append(operator.image); + buff.append(expr); + } + )* + {return buff.toString();} +} + +String RelationalExpression() : +{ + String expr; + Token operator; + final StringBuffer buff = new StringBuffer(); +} { - RelationalExpression() ( ( | ) RelationalExpression() )* + expr = ShiftExpression() + {buff.append(expr);} + ( + ( operator = | operator = | operator = | operator = ) expr = ShiftExpression() + {buff.append(operator.image).append(expr);} + )* + {return buff.toString();} } -void RelationalExpression() : -{} +String ShiftExpression() : +{ + String expr; + Token operator; + final StringBuffer buff = new StringBuffer(); +} { - ShiftExpression() ( ( | | | ) ShiftExpression() )* + expr = AdditiveExpression() + {buff.append(expr);} + ( + (operator = | operator = | operator = ) expr = AdditiveExpression() + { + buff.append(operator.image); + buff.append(expr); + } + )* + {return buff.toString();} } -void ShiftExpression() : -{} +String AdditiveExpression() : +{ + String expr; + Token operator; + final StringBuffer buff = new StringBuffer(); +} { - AdditiveExpression() ( ( | | ) AdditiveExpression() )* + expr = MultiplicativeExpression() + {buff.append(expr);} + ( + ( operator = | operator = ) expr = MultiplicativeExpression() + { + buff.append(operator.image); + buff.append(expr); + } + )* + {return buff.toString();} } -void AdditiveExpression() : -{} +String MultiplicativeExpression() : +{ + String expr; + Token operator; + final StringBuffer buff = new StringBuffer();} { - MultiplicativeExpression() ( ( | ) MultiplicativeExpression() )* + try { + expr = UnaryExpression() + } catch (ParseException e) { + errorMessage = "unexpected token '"+e.currentToken.next.image+"'"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + {buff.append(expr);} + ( + ( operator = | operator = | operator = ) expr = UnaryExpression() + { + buff.append(operator.image); + buff.append(expr); + } + )* + {return buff.toString();} } -void MultiplicativeExpression() : -{} +/** + * An unary expression starting with @, & or nothing + */ +String UnaryExpression() : +{ + final String expr; + final Token token; + final StringBuffer buff = new StringBuffer(); +} { - UnaryExpression() ( ( | | ) UnaryExpression() )* + token = expr = UnaryExpressionNoPrefix() + { + if (token == null) { + return expr; + } + return token.image + expr; + } +| ( {buff.append("@");})* + expr = UnaryExpressionNoPrefix() + {return buff.append(expr).toString();} } -void UnaryExpression() : -{} +String UnaryExpressionNoPrefix() : { - UnaryExpression() -| - ( | ) UnaryExpression() -| - PreIncrementExpression() + final String expr; + final Token token; +} +{ + ( token = | token = ) expr = UnaryExpression() + { + return token.image + expr; + } | - PreDecrementExpression() + expr = PreIncDecExpression() + {return expr;} | - UnaryExpressionNotPlusMinus() + expr = UnaryExpressionNotPlusMinus() + {return expr;} } -void PreIncrementExpression() : -{} + +String PreIncDecExpression() : { - PrimaryExpression() +final String expr; +final Token token; } - -void PreDecrementExpression() : -{} { - PrimaryExpression() + (token = | token = ) expr = PrimaryExpression() + {return token.image + expr;} } -void UnaryExpressionNotPlusMinus() : -{} +String UnaryExpressionNotPlusMinus() : { - UnaryExpression() -| - LOOKAHEAD( Type() ) - CastExpression() -| - PostfixExpression() -| - Literal() -| - Expression() + final String expr; +} +{ + expr = UnaryExpression() {return "!" + expr;} +| LOOKAHEAD( (Type() | ) ) + expr = CastExpression() {return expr;} +| expr = PostfixExpression() {return expr;} +| expr = Literal() {return expr;} +| expr = Expression() + try { + + } catch (ParseException e) { + errorMessage = "')' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + {return "("+expr+")";} } -void CastExpression() : -{} +String CastExpression() : +{ +final String type, expr; +} { - Type() UnaryExpression() + (type = Type() | {type = "array";}) expr = UnaryExpression() + {return "(" + type + ")" + expr;} } -void PostfixExpression() : -{} +String PostfixExpression() : +{ + final String expr; + Token operator = null; +} { - PrimaryExpression() [ | ] + expr = PrimaryExpression() [ operator = | operator = ] + { + if (operator == null) { + return expr; + } + return expr + operator.image; + } } -void PrimaryExpression() : -{} +String PrimaryExpression() : +{ + final Token identifier; + String expr; + final StringBuffer buff = new StringBuffer(); +} { LOOKAHEAD(2) - ClassIdentifier() (PrimarySuffix())* + identifier = 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();} | - ArrayInitializer() + expr = ArrayDeclarator() + {return "array" + expr;} } -void PrimaryPrefix() : -{} +String ArrayDeclarator() : { - -| - ClassIdentifier() -| - VariableDeclaratorId() + final String expr; +} +{ + expr = ArrayInitializer() + {return "array" + expr;} } -void ClassIdentifier(): -{} +String PrimaryPrefix() : { - -| - VariableDeclaratorId() + final String expr; + final Token token; +} +{ + token = {return token.image;} +| expr = ClassIdentifier() {return "new " + expr;} +| expr = VariableDeclaratorId() {return expr;} } -void PrimarySuffix() : -{} +String classInstantiation() : { - Arguments() -| - VariableSuffix() + String expr; + final StringBuffer buff = new StringBuffer("new "); +} +{ + expr = ClassIdentifier() + {buff.append(expr);} + [ + expr = PrimaryExpression() + {buff.append(expr);} + ] + {return buff.toString();} } -void VariableSuffix() : -{} +String ClassIdentifier(): +{ + final String expr; + final Token token; +} { - VariableName() -| - [ Expression() ] + token = {return token.image;} +| expr = VariableDeclaratorId() {return expr;} } -void Literal() : -{} +String PrimarySuffix() : { - -| - -| - -| - BooleanLiteral() -| - NullLiteral() + final String expr; +} +{ + expr = Arguments() {return expr;} +| expr = VariableSuffix() {return expr;} } -void BooleanLiteral() : -{} +String VariableSuffix() : +{ + String expr = null; +} { - + + try { + expr = VariableName() + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function call or field access expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + {return "->" + expr;} | - + [ expr = Expression() | expr = Type() ] //Not good + try { + + } catch (ParseException e) { + errorMessage = "']' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + { + if(expr == null) { + return "[]"; + } + return "[" + expr + "]"; + } } -void NullLiteral() : -{} +String Literal() : +{ + final String expr; + final Token token; +} { - + token = {return token.image;} +| token = {return token.image;} +| token = {return token.image;} +| expr = BooleanLiteral() {return expr;} +| {return "null";} } -void Arguments() : +String BooleanLiteral() : {} { - [ ArgumentList() ] + {return "true";} +| {return "false";} +} + +String Arguments() : +{ +String expr = null; +} +{ + [ expr = ArgumentList() ] try { } catch (ParseException e) { - errorMessage = "')' expected to close the argument list"; + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected to close the argument list"; errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; throw e; } + { + if (expr == null) { + return "()"; + } + return "(" + expr + ")"; + } } -void ArgumentList() : -{} +String ArgumentList() : { - Expression() +String expr; +final StringBuffer buff = new StringBuffer(); +} +{ + expr = Expression() + {buff.append(expr);} ( try { - Expression() + expr = Expression() } catch (ParseException e) { - errorMessage = "expression expected after a comma in argument list"; + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. An expression expected after a comma in argument list"; errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; throw e; } + {buff.append(",").append(expr);} )* + {return buff.toString();} } -/* - * Statement syntax follows. +/** + * A Statement without break. */ - -void Statement() : +void StatementNoBreak() : {} { LOOKAHEAD(2) - Expression() ( | "?>") -| - LOOKAHEAD(2) + Expression() + try { + + } catch (ParseException e) { + if (e.currentToken.next.kind != 4) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + } +| LOOKAHEAD(2) LabeledStatement() -| - Block() -| - EmptyStatement() -| - StatementExpression() +| Block() +| EmptyStatement() +| StatementExpression() try { } catch (ParseException e) { - errorMessage = "';' expected after expression"; + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected"; errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; throw e; } -| - SwitchStatement() -| - IfStatement() -| - WhileStatement() -| - DoStatement() -| - ForStatement() -| - BreakStatement() -| - ContinueStatement() -| - ReturnStatement() -| - EchoStatement() -| - IncludeStatement() -| - StaticStatement() -| - GlobalStatement() +| SwitchStatement() +| IfStatement() +| WhileStatement() +| DoStatement() +| ForStatement() +| ForeachStatement() +| ContinueStatement() +| ReturnStatement() +| EchoStatement() +| [] IncludeStatement() +| StaticStatement() +| GlobalStatement() } -void IncludeStatement() : +/** + * A Normal statement. + */ +void Statement() : {} { - Expression() ( | "?>") -| - Expression() ( | "?>") -| - Expression() ( | "?>") -| - Expression() ( | "?>") + StatementNoBreak() +| BreakStatement() } -void PrintExpression() : +/** + * An html block inside a php syntax. + */ +void htmlBlock() : {} { - Expression() + (phpEchoBlock())* + try { + ( | ) + } catch (ParseException e) { + errorMessage = "End of file unexpected, ' + | token = + | token = + | token = ) + try { + expr = Expression() + } catch (ParseException e) { + if (errorMessage != null) { + throw e; + } + errorMessage = "unexpected token '"+ e.currentToken.next.image+"', expression expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + { + if (currentSegment != null) { + currentSegment.add(new PHPReqIncDeclaration(currentSegment, token.image,pos,expr)); + } + } + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } } +String PrintExpression() : +{ + final String expr; +} +{ + expr = Expression() {return "print " + expr;} +} + +String ListExpression() : +{ + final StringBuffer buff = new StringBuffer("list("); + String expr; +} +{ + + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', '(' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + [ + expr = VariableDeclaratorId() + {buff.append(expr);} + ] + ( + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ',' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + expr = VariableDeclaratorId() + {buff.append(",").append(expr);} + )* + {buff.append(")");} + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + [ expr = Expression() {buff.append("(").append(expr);}] + {return buff.toString();} +} + +/** + * An echo statement. + * echo anyexpression (, otherexpression)* + */ void EchoStatement() : {} { Expression() ( Expression())* try { - ( | "?>") + } catch (ParseException e) { - errorMessage = "';' expected after 'echo' statement"; - errorLevel = ERROR; - throw e; + if (e.currentToken.next.kind != 4) { + errorMessage = "';' expected after 'echo' statement"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } } } void GlobalStatement() : -{} { - VariableDeclaratorId() ( VariableDeclaratorId())* ( | "?>") + final int pos = jj_input_stream.getPosition(); + String expr; +} +{ + + expr = VariableDeclaratorId() + {if (currentSegment != null) { + currentSegment.add(new PHPGlobalDeclaration(currentSegment, "global",pos,expr)); + }} + ( + expr = VariableDeclaratorId() + {if (currentSegment != null) { + currentSegment.add(new PHPGlobalDeclaration(currentSegment, "global",pos,expr)); + }} + )* + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. a ';' was expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } } void StaticStatement() : {} { - VariableDeclarator() ( VariableDeclarator())* ( | "?>") + VariableDeclarator() ( VariableDeclarator())* + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. a ';' was expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } } void LabeledStatement() : @@ -1060,23 +1929,56 @@ void LabeledStatement() : void Block() : {} { - ( BlockStatement() )* + try { + + } catch (ParseException e) { + errorMessage = "'{' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + ( BlockStatement() | htmlBlock())* + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.image +"', '}' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } } void BlockStatement() : {} { Statement() -| - ClassDeclaration() -| - MethodDeclaration() +| ClassDeclaration() +| MethodDeclaration() +} + +/** + * A Block statement that will not contain any 'break' + */ +void BlockStatementNoBreak() : +{} +{ + StatementNoBreak() +| ClassDeclaration() +| MethodDeclaration() } void LocalVariableDeclaration() : {} { - VariableDeclarator() ( VariableDeclarator() )* + LocalVariableDeclarator() ( LocalVariableDeclarator() )* +} + +void LocalVariableDeclarator() : +{} +{ + VariableDeclaratorId() [ Expression() ] } void EmptyStatement() : @@ -1086,55 +1988,202 @@ 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() -| - PreDecrementExpression() + PreIncDecExpression() | PrimaryExpression() - [ - - | - - | - AssignmentOperator() Expression() - ] + [ + | + | AssignmentOperator() Expression() ] } void SwitchStatement() : -{} { - Expression() - ( SwitchLabel() ( BlockStatement() )* )* - + final int pos = jj_input_stream.getPosition(); +} +{ + + try { + + } catch (ParseException e) { + errorMessage = "'(' expected after 'switch'"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + try { + Expression() + } catch (ParseException e) { + if (errorMessage != null) { + throw e; + } + errorMessage = "expression expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + try { + + } catch (ParseException e) { + errorMessage = "')' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + (switchStatementBrace() | switchStatementColon(pos, pos + 6)) } -void SwitchLabel() : +void switchStatementBrace() : {} { - Expression() + + ( switchLabel0() )* + try { + + } catch (ParseException e) { + errorMessage = "'}' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } +} +/** + * A Switch statement with : ... endswitch; + * @param start the begin offset of the switch + * @param end the end offset of the switch + */ +void switchStatementColon(final int start, final int end) : +{} +{ + + {try { + setMarker(fileToParse, + "Ugly syntax detected, you should switch () {...} instead of switch (): ... enswitch;", + start, + end, + INFO, + "Line " + token.beginLine); + } catch (CoreException e) { + PHPeclipsePlugin.log(e); + }} + (switchLabel0())* + try { + + } catch (ParseException e) { + errorMessage = "'endswitch' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + try { + + } catch (ParseException e) { + errorMessage = "';' expected after 'endswitch' keyword"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } +} + +void switchLabel0() : +{ + Token breakToken = null; + final int line; +} +{ + line = SwitchLabel() + ( BlockStatementNoBreak() | htmlBlock() )* + [ breakToken = BreakStatement() ] + { + try { + if (breakToken == null) { + setMarker(fileToParse, + "You should use put a 'break' at the end of your statement", + line, + INFO, + "Line " + line); + } + } catch (CoreException e) { + PHPeclipsePlugin.log(e); + } + } +} + +Token BreakStatement() : +{ + final Token token; +} +{ + token = [ Expression() ] + try { + + } catch (ParseException e) { + errorMessage = "';' expected after 'break' keyword"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + {return token;} +} + +int SwitchLabel() : +{ + final Token token; +} +{ + token = + try { + Expression() + } catch (ParseException e) { + if (errorMessage != null) throw e; + errorMessage = "expression expected after 'case' keyword"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + try { + + } catch (ParseException e) { + errorMessage = "':' expected after case expression"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + {return token.beginLine;} | - <_DEFAULT> + token = <_DEFAULT> + try { + + } catch (ParseException e) { + errorMessage = "':' expected after 'default' keyword"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + {return token.beginLine;} } void IfStatement() : -/* - * The disambiguating algorithm of JavaCC automatically binds dangling - * else's to the innermost if statement. The LOOKAHEAD specification - * is to tell JavaCC that we know what we are doing. - */ -{} { - Condition("if") Statement() [ LOOKAHEAD(1) ElseIfStatement() ] [ LOOKAHEAD(1) Statement() ] + final Token token; + final int pos = jj_input_stream.getPosition(); +} +{ + token = Condition("if") IfStatement0(pos,pos+token.image.length()) } -void Condition(String keyword) : +void Condition(final String keyword) : {} { try { @@ -1142,7 +2191,9 @@ void Condition(String keyword) : } catch (ParseException e) { errorMessage = "'(' expected after " + keyword + " keyword"; errorLevel = ERROR; - throw e; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length(); + errorEnd = errorStart +1; + processParseException(e); } Expression() try { @@ -1150,8 +2201,75 @@ void Condition(String keyword) : } catch (ParseException e) { errorMessage = "')' expected after " + keyword + " keyword"; errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } +} + +void IfStatement0(final int start,final int end) : +{} +{ + (Statement() | htmlBlock())* (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 { + + } catch (ParseException e) { + errorMessage = "'endif' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + try { + + } catch (ParseException e) { + errorMessage = "';' expected after 'endif' keyword"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; throw e; } +| + (Statement() | htmlBlock()) + ( LOOKAHEAD(1) ElseIfStatement() )* + [ LOOKAHEAD(1) + + try { + Statement() + } catch (ParseException e) { + if (errorMessage != null) { + throw e; + } + errorMessage = "unexpected token '"+e.currentToken.next.image+"', a statement was expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + ] +} + +void ElseIfStatementColon() : +{} +{ + Condition("elseif") (Statement() | htmlBlock())* +} + +void ElseStatementColon() : +{} +{ + (Statement() | htmlBlock())* } void ElseIfStatement() : @@ -1161,15 +2279,46 @@ void ElseIfStatement() : } void WhileStatement() : -{} { - Condition("while") WhileStatement0() + final Token token; + final int pos = jj_input_stream.getPosition(); +} +{ + token = Condition("while") WhileStatement0(pos,pos + token.image.length()) } -void WhileStatement0() : +void WhileStatement0(final int start, final int end) : {} { - (Statement())* ( | "?>") + (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 { + + } catch (ParseException e) { + errorMessage = "'endwhile' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + try { + + } catch (ParseException e) { + errorMessage = "';' expected after 'endwhile' keyword"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } | Statement() } @@ -1177,13 +2326,133 @@ void WhileStatement0() : void DoStatement() : {} { - Statement() Condition("while") ( | "?>") + Statement() Condition("while") + try { + + } catch (ParseException e) { + errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } } -void ForStatement() : +void ForeachStatement() : {} { - [ ForInit() ] [ Expression() ] [ ForUpdate() ] Statement() + + try { + + } catch (ParseException e) { + errorMessage = "'(' expected after 'foreach' keyword"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + try { + Variable() + } catch (ParseException e) { + errorMessage = "variable expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + ( VariableSuffix() )* + try { + + } catch (ParseException e) { + errorMessage = "'as' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + try { + Variable() + } catch (ParseException e) { + errorMessage = "variable expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + [ Expression() ] + try { + + } catch (ParseException e) { + errorMessage = "')' expected after 'foreach' keyword"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + try { + Statement() + } catch (ParseException e) { + if (errorMessage != null) throw e; + errorMessage = "statement expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } +} + +void ForStatement() : +{ +final Token token; +final int pos = jj_input_stream.getPosition(); +} +{ + token = + try { + + } catch (ParseException e) { + errorMessage = "'(' expected after 'for' keyword"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + [ ForInit() ] [ Expression() ] [ StatementExpressionList() ] + ( + Statement() + | + (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 { + + } catch (ParseException e) { + errorMessage = "'endfor' expected"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + try { + + } catch (ParseException e) { + errorMessage = "';' expected after 'endfor' keyword"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } + ) } void ForInit() : @@ -1201,26 +2470,32 @@ void StatementExpressionList() : StatementExpression() ( StatementExpression() )* } -void ForUpdate() : -{} -{ - StatementExpressionList() -} - -void BreakStatement() : -{} -{ - [ ] -} - void ContinueStatement() : {} { - [ ] + [ Expression() ] + try { + + } catch (ParseException e) { + errorMessage = "';' expected after 'continue' statement"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } } void ReturnStatement() : {} { - [ Expression() ] + [ Expression() ] + try { + + } catch (ParseException e) { + errorMessage = "';' expected after 'return' statement"; + errorLevel = ERROR; + errorStart = jj_input_stream.getPosition() - e.currentToken.next.image.length() + 1; + errorEnd = jj_input_stream.getPosition() + 1; + throw e; + } } \ No newline at end of file