options { LOOKAHEAD = 1; CHOICE_AMBIGUITY_CHECK = 2; OTHER_AMBIGUITY_CHECK = 1; STATIC = true; DEBUG_PARSER = false; DEBUG_LOOKAHEAD = false; DEBUG_TOKEN_MANAGER = false; OPTIMIZE_TOKEN_MANAGER = false; ERROR_REPORTING = true; JAVA_UNICODE_ESCAPE = false; UNICODE_INPUT = false; IGNORE_CASE = true; USER_TOKEN_MANAGER = false; USER_CHAR_STREAM = false; BUILD_PARSER = true; BUILD_TOKEN_MANAGER = true; SANITY_CHECK = true; FORCE_LA_CHECK = false; } PARSER_BEGIN(PHPParser) package test; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.CoreException; import org.eclipse.ui.texteditor.MarkerUtilities; import org.eclipse.jface.preference.IPreferenceStore; import java.util.Hashtable; import java.util.ArrayList; 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.ast.*; import net.sourceforge.phpdt.internal.compiler.parser.OutlineableWithChildren; import net.sourceforge.phpdt.internal.compiler.parser.PHPOutlineInfo; /** * A new php parser. * 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 final class PHPParser extends PHPParserSuperclass { /** The file that is parsed. */ private static IFile fileToParse; /** The current segment. */ private static OutlineableWithChildren currentSegment; private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$ private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$ static PHPOutlineInfo outlineInfo; /** 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; private static int errorStart = -1; private static int errorEnd = -1; private static PHPDocument phpDocument; private static final char[] SYNTAX_ERROR_CHAR = {'s','y','n','t','a','x',' ','e','r','r','o','r'}; /** * The point where html starts. * It will be used by the token manager to create HTMLCode objects */ public static int htmlStart; //ast stack private final static int AstStackIncrement = 100; /** The stack of node. */ private static AstNode[] nodes; /** The cursor in expression stack. */ private static int nodePtr; public final void setFileToParse(final IFile fileToParse) { this.fileToParse = fileToParse; } public PHPParser() { } public PHPParser(final IFile fileToParse) { this(new StringReader("")); this.fileToParse = fileToParse; } /** * Reinitialize the parser. */ private static final void init() { nodes = new AstNode[AstStackIncrement]; nodePtr = -1; htmlStart = 0; } /** * Add an php node on the stack. * @param node the node that will be added to the stack */ private static final void pushOnAstNodes(AstNode node) { try { nodes[++nodePtr] = node; } catch (IndexOutOfBoundsException e) { int oldStackLength = nodes.length; AstNode[] oldStack = nodes; nodes = new AstNode[oldStackLength + AstStackIncrement]; System.arraycopy(oldStack, 0, nodes, 0, oldStackLength); nodePtr = oldStackLength; nodes[nodePtr] = node; } } public final PHPOutlineInfo parseInfo(final Object parent, final String s) { phpDocument = new PHPDocument(parent,"_root".toCharArray()); currentSegment = phpDocument; outlineInfo = new PHPOutlineInfo(parent, currentSegment); final StringReader stream = new StringReader(s); if (jj_input_stream == null) { jj_input_stream = new SimpleCharStream(stream, 1, 1); } ReInit(stream); init(); try { parse(); phpDocument.nodes = new AstNode[nodes.length]; System.arraycopy(nodes,0,phpDocument.nodes,0,nodes.length); if (PHPeclipsePlugin.DEBUG) { PHPeclipsePlugin.log(1,phpDocument.toString()); } } catch (ParseException e) { processParseException(e); } return outlineInfo; } /** * 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 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 = SimpleCharStream.getPosition(); errorEnd = errorStart + 1; } setMarker(e); errorMessage = null; } /** * Create marker for the parse error * @param e the ParseException */ private static void setMarker(final ParseException e) { try { if (errorStart == -1) { setMarker(fileToParse, errorMessage, SimpleCharStream.tokenBegin, SimpleCharStream.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; } } catch (CoreException e2) { PHPeclipsePlugin.log(e2); } } 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; current = output.substring(indx, brIndx); if (current.indexOf(PARSE_WARNING_STRING) != -1 || current.indexOf(PARSE_ERROR_STRING) != -1) { int onLine = current.indexOf("on line "); if (onLine != -1) { lineNumberBuffer.delete(0, lineNumberBuffer.length()); for (int i = onLine; i < current.length(); i++) { ch = current.charAt(i); if ('0' <= ch && '9' >= ch) { lineNumberBuffer.append(ch); } } int lineNumber = Integer.parseInt(lineNumberBuffer.toString()); Hashtable attributes = new Hashtable(); current = current.replaceAll("\n", ""); current = current.replaceAll("", ""); current = current.replaceAll("", ""); MarkerUtilities.setMessage(attributes, current); if (current.indexOf(PARSE_ERROR_STRING) != -1) attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR)); else if (current.indexOf(PARSE_WARNING_STRING) != -1) attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING)); else attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO)); MarkerUtilities.setLineNumber(attributes, lineNumber); MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM); } } } 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); init(); try { parse(); } catch (ParseException e) { processParseException(e); } } /** * Call the php parse command ( php -l -f <filename> ) * and create markers according to the external parser output */ public static void phpExternalParse(final IFile file) { final IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore(); final String filename = file.getLocation().toString(); final String[] arguments = { filename }; final MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF)); final String command = form.format(arguments); final String parserResult = PHPStartApacheAction.getParserOutput(command, "External parser: "); try { // parse the buffer to find the errors and warnings createMarkers(parserResult, file); } catch (CoreException e) { PHPeclipsePlugin.log(e); } } /** * Put a new html block in the stack. */ public static final void createNewHTMLCode() { final int currentPosition = SimpleCharStream.getPosition(); if (currentPosition == htmlStart) { return; } final char[] chars = SimpleCharStream.currentBuffer.substring(htmlStart,currentPosition+1).toCharArray(); pushOnAstNodes(new HTMLCode(chars, htmlStart,currentPosition)); } /** * Create a new task. */ public static final void createNewTask() { final int currentPosition = SimpleCharStream.getPosition(); final String todo = SimpleCharStream.currentBuffer.substring(currentPosition+1, SimpleCharStream.currentBuffer.indexOf("\n", currentPosition)-1); try { setMarker(fileToParse, "todo : " + todo, SimpleCharStream.getBeginLine(), TASK, "Line "+SimpleCharStream.getBeginLine()); } catch (CoreException e) { PHPeclipsePlugin.log(e); } } private static final void parse() throws ParseException { phpFile(); } } PARSER_END(PHPParser) TOKEN : { {PHPParser.createNewHTMLCode();} : PHPPARSING | {PHPParser.createNewHTMLCode();} : PHPPARSING | "> {PHPParser.htmlStart = SimpleCharStream.getPosition();} : DEFAULT } /* Skip any character if we are not in php mode */ SKIP : { < ~[] > } /* WHITE SPACE */ SKIP : { " " | "\t" | "\n" | "\r" | "\f" } /* COMMENTS */ SPECIAL_TOKEN : { "//" : IN_SINGLE_LINE_COMMENT | "#" : IN_SINGLE_LINE_COMMENT | <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT | "/*" : IN_MULTI_LINE_COMMENT } SPECIAL_TOKEN : { : PHPPARSING | "?>" : DEFAULT } SPECIAL_TOKEN : { "todo" {PHPParser.createNewTask();} } SPECIAL_TOKEN : { "*/" : PHPPARSING } SPECIAL_TOKEN : { "*/" : PHPPARSING } MORE : { < ~[] > } /* KEYWORDS */ TOKEN : { | | | | | | | | } /* LANGUAGE CONSTRUCT */ TOKEN : { | | | | | | | | "> | | "> } /* RESERVED WORDS AND LITERALS */ TOKEN : { | | | <_DEFAULT : "default"> | | | | | | | | | | | | | | | | | | | } /* TYPES */ TOKEN : { | | | | | | | | } //Misc token TOKEN : { | | | | | } /* OPERATORS */ TOKEN : { | | | | | | | | | | | | | >"> | >>"> | <_ORL : "OR"> | <_ANDL : "AND"> } /* LITERALS */ TOKEN : { (["l","L"])? | (["l","L"])? | (["l","L"])? > | <#DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* > | <#HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ > | <#OCTAL_LITERAL: "0" (["0"-"7"])* > | )? (["f","F","d","D"])? | "." (["0"-"9"])+ ()? (["f","F","d","D"])? | (["0"-"9"])+ (["f","F","d","D"])? | (["0"-"9"])+ ()? ["f","F","d","D"] > | <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > | | | )> | | | } /* IDENTIFIERS */ TOKEN : { < IDENTIFIER: (|) (||)* > | < #LETTER: ["a"-"z"] | ["A"-"Z"] > | < #DIGIT: ["0"-"9"] > | < #SPECIAL: "_" | ["\u007f"-"\u00ff"] > } /* SEPARATORS */ TOKEN : { | | | | | | | | } /* COMPARATOR */ TOKEN : { "> | | | ="> | "> | | } /* ASSIGNATION */ TOKEN : { | >="> } TOKEN : { > } void phpFile() : {} { try { (PhpBlock())* {PHPParser.createNewHTMLCode();} } 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 = SimpleCharStream.getPosition(); final PHPEchoBlock phpEchoBlock; } { phpEchoBlock = phpEchoBlock() {pushOnAstNodes(phpEchoBlock);} | [ | {try { setMarker(fileToParse, "You should use ' } catch (ParseException e) { errorMessage = "'?>' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; processParseException(e); } } PHPEchoBlock phpEchoBlock() : { final Expression expr; final int pos = SimpleCharStream.getPosition(); PHPEchoBlock echoBlock; } { expr = Expression() [ ] { echoBlock = new PHPEchoBlock(expr,pos,SimpleCharStream.getPosition()); pushOnAstNodes(echoBlock); return echoBlock;} } void Php() : {} { (BlockStatement())* } ClassDeclaration ClassDeclaration() : { final ClassDeclaration classDeclaration; final Token className; Token superclassName = null; final int pos; char[] classNameImage = SYNTAX_ERROR_CHAR; char[] superclassNameImage = null; } { {pos = SimpleCharStream.getPosition();} try { className = {classNameImage = className.image.toCharArray();} } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', identifier expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; processParseException(e); } [ try { superclassName = {superclassNameImage = superclassName.image.toCharArray();} } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', identifier expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; processParseException(e); superclassNameImage = SYNTAX_ERROR_CHAR; } ] { if (superclassNameImage == null) { classDeclaration = new ClassDeclaration(currentSegment, classNameImage, pos, 0); } else { classDeclaration = new ClassDeclaration(currentSegment, classNameImage, superclassNameImage, pos, 0); } currentSegment.add(classDeclaration); currentSegment = classDeclaration; } ClassBody(classDeclaration) {currentSegment = (OutlineableWithChildren) currentSegment.getParent(); classDeclaration.sourceEnd = SimpleCharStream.getPosition(); pushOnAstNodes(classDeclaration); return classDeclaration;} } void ClassBody(ClassDeclaration classDeclaration) : {} { try { } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image + "', '{' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } ( ClassBodyDeclaration(classDeclaration) )* try { } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', 'var', 'function' or '}' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } } /** * A class can contain only methods and fields. */ void ClassBodyDeclaration(ClassDeclaration classDeclaration) : { MethodDeclaration method; FieldDeclaration field; } { method = MethodDeclaration() {classDeclaration.addMethod(method);} | field = FieldDeclaration() {classDeclaration.addField(field);} } /** * A class field declaration : it's var VariableDeclarator() (, VariableDeclarator())*;. */ FieldDeclaration FieldDeclaration() : { VariableDeclaration variableDeclaration; VariableDeclaration[] list; final ArrayList arrayList = new ArrayList(); final int pos = SimpleCharStream.getPosition(); } { variableDeclaration = VariableDeclarator() {arrayList.add(variableDeclaration); outlineInfo.addVariable(new String(variableDeclaration.name));} ( variableDeclaration = VariableDeclarator() {arrayList.add(variableDeclaration); outlineInfo.addVariable(new String(variableDeclaration.name));} )* try { } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected after variable declaration"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; processParseException(e); } {list = new VariableDeclaration[arrayList.size()]; arrayList.toArray(list); return new FieldDeclaration(list, pos, SimpleCharStream.getPosition(), currentSegment);} } VariableDeclaration VariableDeclarator() : { final String varName; Expression initializer = null; final int pos = SimpleCharStream.getPosition(); } { varName = VariableDeclaratorId() [ try { initializer = VariableInitializer() } catch (ParseException e) { errorMessage = "Literal expression expected in variable initializer"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } ] { if (initializer == null) { return new VariableDeclaration(currentSegment, varName.toCharArray(), pos, SimpleCharStream.getPosition()); } return new VariableDeclaration(currentSegment, varName.toCharArray(), initializer, pos); } } /** * A Variable name. * @return the variable name (with suffix) */ String VariableDeclaratorId() : { String expr; Expression expression = null; final StringBuffer buff = new StringBuffer(); final int pos = SimpleCharStream.getPosition(); ConstantIdentifier ex; } { try { expr = Variable() ( LOOKAHEAD(2) {ex = new ConstantIdentifier(expr.toCharArray(), pos, SimpleCharStream.getPosition());} expression = VariableSuffix(ex) )* { if (expression == null) { return expr; } return expression.toStringExpression(); } } catch (ParseException e) { errorMessage = "'$' expected for variable identifier"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } } /** * Return a variablename without the $. * @return a variable name */ String Variable(): { final StringBuffer buff; Expression expression = null; final Token token; final String expr; } { token = [ expression = Expression() ] { if (expression == null) { return token.image.substring(1); } buff = new StringBuffer(token.image); buff.append("{"); buff.append(expression.toStringExpression()); buff.append("}"); return buff.toString(); } | expr = VariableName() {return expr;} } /** * A Variable name (without the $) * @return a variable name String */ String VariableName(): { final StringBuffer buff; String expr = null; Expression expression = null; final Token token; } { expression = Expression() {buff = new StringBuffer("{"); buff.append(expression.toStringExpression()); buff.append("}"); return buff.toString();} | token = [ expression = Expression() ] { if (expression == null) { return token.image; } buff = new StringBuffer(token.image); buff.append("{"); buff.append(expression.toStringExpression()); buff.append("}"); return buff.toString(); } | expr = VariableName() { buff = new StringBuffer("$"); buff.append(expr); return buff.toString(); } | token = {return token.image;} } Expression VariableInitializer() : { final Expression expr; final Token token; final int pos = SimpleCharStream.getPosition(); } { expr = Literal() {return expr;} | (token = | token = ) {return new PrefixedUnaryExpression(new NumberLiteral(token.image.toCharArray(), pos, SimpleCharStream.getPosition()), OperatorIds.MINUS, pos);} | (token = | token = ) {return new PrefixedUnaryExpression(new NumberLiteral(token.image.toCharArray(), pos, SimpleCharStream.getPosition()), OperatorIds.PLUS, pos);} | expr = ArrayDeclarator() {return expr;} | token = {return new ConstantIdentifier(token.image.toCharArray(),pos,SimpleCharStream.getPosition());} } ArrayVariableDeclaration ArrayVariable() : { Expression expr,expr2; } { expr = Expression() [ expr2 = Expression() {return new ArrayVariableDeclaration(expr,expr2);} ] {return new ArrayVariableDeclaration(expr,SimpleCharStream.getPosition());} } ArrayVariableDeclaration[] ArrayInitializer() : { ArrayVariableDeclaration expr; final ArrayList list = new ArrayList(); } { [ expr = ArrayVariable() {list.add(expr);} ( LOOKAHEAD(2) expr = ArrayVariable() {list.add(expr);} )* ] [ {list.add(null);}] { ArrayVariableDeclaration[] vars = new ArrayVariableDeclaration[list.size()]; list.toArray(vars); return vars;} } /** * A Method Declaration. * function MetodDeclarator() Block() */ MethodDeclaration MethodDeclaration() : { final MethodDeclaration functionDeclaration; final Block block; final OutlineableWithChildren seg = currentSegment; } { try { functionDeclaration = MethodDeclarator() {outlineInfo.addVariable(new String(functionDeclaration.name));} } catch (ParseException e) { if (errorMessage != null) throw e; errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function identifier expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } {currentSegment = functionDeclaration;} block = Block() {functionDeclaration.statements = block.statements; currentSegment = seg; return functionDeclaration;} } /** * A MethodDeclarator. * [&] IDENTIFIER(parameters ...). * @return a function description for the outline */ MethodDeclaration MethodDeclarator() : { final Token identifier; Token reference = null; final Hashtable formalParameters; final int pos = SimpleCharStream.getPosition(); char[] identifierChar = SYNTAX_ERROR_CHAR; } { [reference = ] try { identifier = {identifierChar = identifier.image.toCharArray();} } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function identifier expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; processParseException(e); } formalParameters = FormalParameters() {return new MethodDeclaration(currentSegment, identifierChar, formalParameters, reference != null, pos, SimpleCharStream.getPosition());} } /** * FormalParameters follows method identifier. * (FormalParameter()) */ Hashtable FormalParameters() : { VariableDeclaration var; final Hashtable parameters = new Hashtable(); } { try { } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', '(' expected after function identifier"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; processParseException(e); } [ var = FormalParameter() {parameters.put(new String(var.name),var);} ( var = FormalParameter() {parameters.put(new String(var.name),var);} )* ] try { } catch (ParseException e) { errorMessage = "')' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; processParseException(e); } {return parameters;} } /** * A formal parameter. * $varname[=value] (,$varname[=value]) */ VariableDeclaration FormalParameter() : { final VariableDeclaration variableDeclaration; Token token = null; } { [token = ] variableDeclaration = VariableDeclarator() { if (token != null) { variableDeclaration.setReference(true); } return variableDeclaration;} } ConstantIdentifier Type() : {final int pos;} { {pos = SimpleCharStream.getPosition(); return new ConstantIdentifier(Types.STRING,pos,pos-6);} | {pos = SimpleCharStream.getPosition(); return new ConstantIdentifier(Types.BOOL,pos,pos-4);} | {pos = SimpleCharStream.getPosition(); return new ConstantIdentifier(Types.BOOLEAN,pos,pos-7);} | {pos = SimpleCharStream.getPosition(); return new ConstantIdentifier(Types.REAL,pos,pos-4);} | {pos = SimpleCharStream.getPosition(); return new ConstantIdentifier(Types.DOUBLE,pos,pos-5);} | {pos = SimpleCharStream.getPosition(); return new ConstantIdentifier(Types.FLOAT,pos,pos-5);} | {pos = SimpleCharStream.getPosition(); return new ConstantIdentifier(Types.INT,pos,pos-3);} | {pos = SimpleCharStream.getPosition(); return new ConstantIdentifier(Types.INTEGER,pos,pos-7);} | {pos = SimpleCharStream.getPosition(); return new ConstantIdentifier(Types.OBJECT,pos,pos-6);} } Expression Expression() : { final Expression expr; } { expr = PrintExpression() {return expr;} | expr = ListExpression() {return expr;} | LOOKAHEAD(varAssignation()) expr = varAssignation() {return expr;} | expr = ConditionalExpression() {return expr;} } /** * A Variable assignation. * varName (an assign operator) any expression */ VarAssignation varAssignation() : { String varName; final Expression initializer; final int assignOperator; final int pos = SimpleCharStream.getPosition(); } { varName = VariableDeclaratorId() assignOperator = AssignmentOperator() try { initializer = Expression() } catch (ParseException e) { if (errorMessage != null) { throw e; } errorMessage = "expression expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } {return new VarAssignation(varName.toCharArray(), initializer, assignOperator, pos, SimpleCharStream.getPosition());} } int AssignmentOperator() : {} { {return VarAssignation.EQUAL;} | {return VarAssignation.STAR_EQUAL;} | {return VarAssignation.SLASH_EQUAL;} | {return VarAssignation.REM_EQUAL;} | {return VarAssignation.PLUS_EQUAL;} | {return VarAssignation.MINUS_EQUAL;} | {return VarAssignation.LSHIFT_EQUAL;} | {return VarAssignation.RSIGNEDSHIFT_EQUAL;} | {return VarAssignation.AND_EQUAL;} | {return VarAssignation.XOR_EQUAL;} | {return VarAssignation.OR_EQUAL;} | {return VarAssignation.DOT_EQUAL;} | {return VarAssignation.TILDE_EQUAL;} } Expression ConditionalExpression() : { final Expression expr; Expression expr2 = null; Expression expr3 = null; } { expr = ConditionalOrExpression() [ expr2 = Expression() expr3 = ConditionalExpression() ] { if (expr3 == null) { return expr; } return new ConditionalExpression(expr,expr2,expr3); } } Expression ConditionalOrExpression() : { Expression expr,expr2; int operator; } { expr = ConditionalAndExpression() ( ( {operator = OperatorIds.OR_OR;} | <_ORL> {operator = OperatorIds.ORL;} ) expr2 = ConditionalAndExpression() { expr = new BinaryExpression(expr,expr2,operator); } )* {return expr;} } Expression ConditionalAndExpression() : { Expression expr,expr2; int operator; } { expr = ConcatExpression() ( ( {operator = OperatorIds.AND_AND;} | <_ANDL> {operator = OperatorIds.ANDL;}) expr2 = ConcatExpression() {expr = new BinaryExpression(expr,expr2,operator);} )* {return expr;} } Expression ConcatExpression() : { Expression expr,expr2; } { expr = InclusiveOrExpression() ( expr2 = InclusiveOrExpression() {expr = new BinaryExpression(expr,expr2,OperatorIds.DOT);} )* {return expr;} } Expression InclusiveOrExpression() : { Expression expr,expr2; } { expr = ExclusiveOrExpression() ( expr2 = ExclusiveOrExpression() {expr = new BinaryExpression(expr,expr2,OperatorIds.OR);} )* {return expr;} } Expression ExclusiveOrExpression() : { Expression expr,expr2; } { expr = AndExpression() ( expr2 = AndExpression() {expr = new BinaryExpression(expr,expr2,OperatorIds.XOR);} )* {return expr;} } Expression AndExpression() : { Expression expr,expr2; } { expr = EqualityExpression() ( expr2 = EqualityExpression() {expr = new BinaryExpression(expr,expr2,OperatorIds.AND);} )* {return expr;} } Expression EqualityExpression() : { Expression expr,expr2; int operator; } { expr = RelationalExpression() ( ( {operator = OperatorIds.EQUAL_EQUAL;} | {operator = OperatorIds.DIF;} | {operator = OperatorIds.DIF;} | {operator = OperatorIds.BANG_EQUAL_EQUAL;} | {operator = OperatorIds.EQUAL_EQUAL_EQUAL;} ) try { expr2 = RelationalExpression() } catch (ParseException e) { if (errorMessage != null) { throw e; } errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', expression expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } { expr = new BinaryExpression(expr,expr2,operator); } )* {return expr;} } Expression RelationalExpression() : { Expression expr,expr2; int operator; } { expr = ShiftExpression() ( ( {operator = OperatorIds.LESS;} | {operator = OperatorIds.GREATER;} | {operator = OperatorIds.LESS_EQUAL;} | {operator = OperatorIds.GREATER_EQUAL;}) expr2 = ShiftExpression() {expr = new BinaryExpression(expr,expr2,operator);} )* {return expr;} } Expression ShiftExpression() : { Expression expr,expr2; int operator; } { expr = AdditiveExpression() ( ( {operator = OperatorIds.LEFT_SHIFT;} | {operator = OperatorIds.RIGHT_SHIFT;} | {operator = OperatorIds.UNSIGNED_RIGHT_SHIFT;}) expr2 = AdditiveExpression() {expr = new BinaryExpression(expr,expr2,operator);} )* {return expr;} } Expression AdditiveExpression() : { Expression expr,expr2; int operator; } { expr = MultiplicativeExpression() ( ( {operator = OperatorIds.PLUS;} | {operator = OperatorIds.MINUS;} ) expr2 = MultiplicativeExpression() {expr = new BinaryExpression(expr,expr2,operator);} )* {return expr;} } Expression MultiplicativeExpression() : { Expression expr,expr2; int operator; } { try { expr = UnaryExpression() } catch (ParseException e) { if (errorMessage != null) throw e; errorMessage = "unexpected token '"+e.currentToken.next.image+"'"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } ( ( {operator = OperatorIds.MULTIPLY;} | {operator = OperatorIds.DIVIDE;} | {operator = OperatorIds.REMAINDER;}) expr2 = UnaryExpression() {expr = new BinaryExpression(expr,expr2,operator);} )* {return expr;} } /** * An unary expression starting with @, & or nothing */ Expression UnaryExpression() : { Expression expr; final int pos = SimpleCharStream.getPosition(); } { expr = UnaryExpressionNoPrefix() {return new PrefixedUnaryExpression(expr,OperatorIds.AND,pos);} | expr = AtUnaryExpression() {return expr;} } Expression AtUnaryExpression() : { Expression expr; final int pos = SimpleCharStream.getPosition(); } { expr = AtUnaryExpression() {return new PrefixedUnaryExpression(expr,OperatorIds.AT,pos);} | expr = UnaryExpressionNoPrefix() {return expr;} } Expression UnaryExpressionNoPrefix() : { Expression expr; int operator; final int pos = SimpleCharStream.getPosition(); } { ( {operator = OperatorIds.PLUS;} | {operator = OperatorIds.MINUS;}) expr = UnaryExpression() {return new PrefixedUnaryExpression(expr,operator,pos);} | expr = PreIncDecExpression() {return expr;} | expr = UnaryExpressionNotPlusMinus() {return expr;} } Expression PreIncDecExpression() : { final Expression expr; final int operator; final int pos = SimpleCharStream.getPosition(); } { ( {operator = OperatorIds.PLUS_PLUS;} | {operator = OperatorIds.MINUS_MINUS;}) expr = PrimaryExpression() {return new PrefixedUnaryExpression(expr,operator,pos);} } Expression UnaryExpressionNotPlusMinus() : { Expression expr; final int pos = SimpleCharStream.getPosition(); } { expr = UnaryExpression() {return new PrefixedUnaryExpression(expr,OperatorIds.NOT,pos);} | 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 = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } {return expr;} } CastExpression CastExpression() : { final ConstantIdentifier type; final Expression expr; final int pos = SimpleCharStream.getPosition(); } { (type = Type() | {type = new ConstantIdentifier(Types.ARRAY,pos,SimpleCharStream.getPosition());}) expr = UnaryExpression() {return new CastExpression(type,expr,pos,SimpleCharStream.getPosition());} } Expression PostfixExpression() : { Expression expr; int operator = -1; final int pos = SimpleCharStream.getPosition(); } { expr = PrimaryExpression() [ {operator = OperatorIds.PLUS_PLUS;} | {operator = OperatorIds.MINUS_MINUS;}] { if (operator == -1) { return expr; } return new PostfixedUnaryExpression(expr,operator,pos); } } Expression PrimaryExpression() : { final Token identifier; Expression expr; final int pos = SimpleCharStream.getPosition(); } { LOOKAHEAD(2) identifier = expr = ClassIdentifier() {expr = new ClassAccess(new ConstantIdentifier(identifier.image.toCharArray(), pos, SimpleCharStream.getPosition()), expr, ClassAccess.STATIC);} (expr = PrimarySuffix(expr))* {return expr;} | expr = PrimaryPrefix() (expr = PrimarySuffix(expr))* {return expr;} | expr = ArrayDeclarator() {return expr;} } ArrayInitializer ArrayDeclarator() : { final ArrayVariableDeclaration[] vars; final int pos = SimpleCharStream.getPosition(); } { vars = ArrayInitializer() {return new ArrayInitializer(vars,pos,SimpleCharStream.getPosition());} } Expression PrimaryPrefix() : { final Expression expr; final Token token; final String var; final int pos = SimpleCharStream.getPosition(); } { token = {return new ConstantIdentifier(token.image.toCharArray(), pos, SimpleCharStream.getPosition());} | expr = ClassIdentifier() {return new PrefixedUnaryExpression(expr, OperatorIds.NEW, pos);} | var = VariableDeclaratorId() {return new ConstantIdentifier(var.toCharArray(), pos, SimpleCharStream.getPosition());} } PrefixedUnaryExpression classInstantiation() : { Expression expr; final StringBuffer buff; final int pos = SimpleCharStream.getPosition(); } { expr = ClassIdentifier() [ {buff = new StringBuffer(expr.toStringExpression());} expr = PrimaryExpression() {buff.append(expr.toStringExpression()); expr = new ConstantIdentifier(buff.toString().toCharArray(), pos, SimpleCharStream.getPosition());} ] {return new PrefixedUnaryExpression(expr, OperatorIds.NEW, pos);} } ConstantIdentifier ClassIdentifier(): { final String expr; final Token token; final int pos = SimpleCharStream.getPosition(); } { token = {return new ConstantIdentifier(token.image.toCharArray(), pos, SimpleCharStream.getPosition());} | expr = VariableDeclaratorId() {return new ConstantIdentifier(expr.toCharArray(), pos, SimpleCharStream.getPosition());} } AbstractSuffixExpression PrimarySuffix(Expression prefix) : { final AbstractSuffixExpression expr; } { expr = Arguments(prefix) {return expr;} | expr = VariableSuffix(prefix) {return expr;} } AbstractSuffixExpression VariableSuffix(Expression prefix) : { String expr = null; final int pos = SimpleCharStream.getPosition(); Expression expression = null; } { try { expr = VariableName() } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', function call or field access expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } {return new ClassAccess(prefix, new ConstantIdentifier(expr.toCharArray(),pos,SimpleCharStream.getPosition()), ClassAccess.NORMAL);} | [ expression = Expression() | expression = Type() ] //Not good try { } catch (ParseException e) { errorMessage = "']' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } {return new ArrayDeclarator(prefix,expression,SimpleCharStream.getPosition());} } Literal Literal() : { final Token token; final int pos; } { token = {pos = SimpleCharStream.getPosition(); return new NumberLiteral(token.image.toCharArray(),pos-token.image.length(),pos);} | token = {pos = SimpleCharStream.getPosition(); return new NumberLiteral(token.image.toCharArray(),pos-token.image.length(),pos);} | token = {pos = SimpleCharStream.getPosition(); return new StringLiteral(token.image.toCharArray(),pos-token.image.length());} | {pos = SimpleCharStream.getPosition(); return new TrueLiteral(pos-4,pos);} | {pos = SimpleCharStream.getPosition(); return new FalseLiteral(pos-4,pos);} | {pos = SimpleCharStream.getPosition(); return new NullLiteral(pos-4,pos);} } FunctionCall Arguments(Expression func) : { Expression[] args = null; } { [ args = ArgumentList() ] try { } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected to close the argument list"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } {return new FunctionCall(func,args,SimpleCharStream.getPosition());} } /** * An argument list is a list of arguments separated by comma : * argumentDeclaration() (, argumentDeclaration)* * @return an array of arguments */ Expression[] ArgumentList() : { Expression arg; final ArrayList list = new ArrayList(); } { arg = Expression() {list.add(arg);} ( try { arg = Expression() {list.add(arg);} } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. An expression expected after a comma in argument list"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } )* { Expression[] arguments = new Expression[list.size()]; list.toArray(arguments); return arguments;} } /** * A Statement without break. */ Statement StatementNoBreak() : { final Statement statement; Token token = null; } { LOOKAHEAD(2) statement = Expression() try { } catch (ParseException e) { if (e.currentToken.next.kind != PHPParserConstants.PHPEND) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } } {return statement;} | LOOKAHEAD(2) statement = LabeledStatement() {return statement;} | statement = Block() {return statement;} | statement = EmptyStatement() {return statement;} | statement = StatementExpression() try { } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } {return statement;} | statement = SwitchStatement() {return statement;} | statement = IfStatement() {return statement;} | statement = WhileStatement() {return statement;} | statement = DoStatement() {return statement;} | statement = ForStatement() {return statement;} | statement = ForeachStatement() {return statement;} | statement = ContinueStatement() {return statement;} | statement = ReturnStatement() {return statement;} | statement = EchoStatement() {return statement;} | [token=] statement = IncludeStatement() {if (token != null) { ((InclusionStatement)statement).silent = true; } return statement;} | statement = StaticStatement() {return statement;} | statement = GlobalStatement() {return statement;} } /** * A Normal statement. */ Statement Statement() : { final Statement statement; } { statement = StatementNoBreak() {return statement;} | statement = BreakStatement() {return statement;} } /** * An html block inside a php syntax. */ HTMLBlock htmlBlock() : { final int startIndex = nodePtr; AstNode[] blockNodes; int nbNodes; } { (phpEchoBlock())* try { ( | ) } catch (ParseException e) { errorMessage = "unexpected end of file , ' {keyword = InclusionStatement.REQUIRE;} | {keyword = InclusionStatement.REQUIRE_ONCE;} | {keyword = InclusionStatement.INCLUDE;} | {keyword = InclusionStatement.INCLUDE_ONCE;}) try { expr = Expression() } catch (ParseException e) { if (errorMessage != null) { throw e; } errorMessage = "unexpected token '"+ e.currentToken.next.image+"', expression expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } {inclusionStatement = new InclusionStatement(currentSegment, keyword, expr, pos); currentSegment.add(inclusionStatement); } try { } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } {return inclusionStatement;} } PrintExpression PrintExpression() : { final Expression expr; final int pos = SimpleCharStream.getPosition(); } { expr = Expression() {return new PrintExpression(expr,pos,SimpleCharStream.getPosition());} } ListExpression ListExpression() : { String expr = null; Expression expression = null; ArrayList list = new ArrayList(); final int pos = SimpleCharStream.getPosition(); } { try { } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', '(' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } [ expr = VariableDeclaratorId() {list.add(expr);} ] {if (expr == null) list.add(null);} ( try { } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ',' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } expr = VariableDeclaratorId() {list.add(expr);} )* try { } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } [ expression = Expression() { String[] strings = new String[list.size()]; list.toArray(strings); return new ListExpression(strings, expression, pos, SimpleCharStream.getPosition());} ] { String[] strings = new String[list.size()]; list.toArray(strings); return new ListExpression(strings,pos,SimpleCharStream.getPosition());} } /** * An echo statement. * echo anyexpression (, otherexpression)* */ EchoStatement EchoStatement() : { final ArrayList expressions = new ArrayList(); Expression expr; final int pos = SimpleCharStream.getPosition(); } { expr = Expression() {expressions.add(expr);} ( expr = Expression() {expressions.add(expr);} )* try { } catch (ParseException e) { if (e.currentToken.next.kind != 4) { errorMessage = "';' expected after 'echo' statement"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } } {Expression[] exprs = new Expression[expressions.size()]; expressions.toArray(exprs); return new EchoStatement(exprs,pos);} } GlobalStatement GlobalStatement() : { final int pos = SimpleCharStream.getPosition(); String expr; ArrayList vars = new ArrayList(); GlobalStatement global; } { expr = VariableDeclaratorId() {vars.add(expr);} ( expr = VariableDeclaratorId() {vars.add(expr);} )* try { { String[] strings = new String[vars.size()]; vars.toArray(strings); global = new GlobalStatement(currentSegment, strings, pos, SimpleCharStream.getPosition()); currentSegment.add(global); return global;} } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. a ';' was expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } } StaticStatement StaticStatement() : { final int pos = SimpleCharStream.getPosition(); final ArrayList vars = new ArrayList(); VariableDeclaration expr; } { expr = VariableDeclarator() {vars.add(new String(expr.name));} ( expr = VariableDeclarator() {vars.add(new String(expr.name));})* try { { String[] strings = new String[vars.size()]; vars.toArray(strings); return new StaticStatement(strings, pos, SimpleCharStream.getPosition());} } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. a ';' was expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } } LabeledStatement LabeledStatement() : { final int pos = SimpleCharStream.getPosition(); final Token label; final Statement statement; } { label = statement = Statement() {return new LabeledStatement(label.image.toCharArray(),statement,pos,SimpleCharStream.getPosition());} } /** * A Block is * { * statements * }. * @return a block */ Block Block() : { final int pos = SimpleCharStream.getPosition(); final ArrayList list = new ArrayList(); Statement statement; } { try { } catch (ParseException e) { errorMessage = "'{' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } ( statement = BlockStatement() {list.add(statement);} | statement = htmlBlock() {list.add(statement);})* try { } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.image +"', '}' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } { Statement[] statements = new Statement[list.size()]; list.toArray(statements); return new Block(statements,pos,SimpleCharStream.getPosition());} } Statement BlockStatement() : { final Statement statement; } { try { statement = Statement() {if (phpDocument == currentSegment) pushOnAstNodes(statement); return statement;} } catch (ParseException e) { if (errorMessage != null) throw e; errorMessage = "statement expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } | statement = ClassDeclaration() {return statement;} | statement = MethodDeclaration() {if (phpDocument == currentSegment) pushOnAstNodes(statement); currentSegment.add((MethodDeclaration) statement); return statement;} } /** * A Block statement that will not contain any 'break' */ Statement BlockStatementNoBreak() : { final Statement statement; } { statement = StatementNoBreak() {return statement;} | statement = ClassDeclaration() {return statement;} | statement = MethodDeclaration() {currentSegment.add((MethodDeclaration) statement); return statement;} } VariableDeclaration[] LocalVariableDeclaration() : { final ArrayList list = new ArrayList(); VariableDeclaration var; } { var = LocalVariableDeclarator() {list.add(var);} ( var = LocalVariableDeclarator() {list.add(var);})* { VariableDeclaration[] vars = new VariableDeclaration[list.size()]; list.toArray(vars); return vars;} } VariableDeclaration LocalVariableDeclarator() : { final String varName; Expression initializer = null; final int pos = SimpleCharStream.getPosition(); } { varName = VariableDeclaratorId() [ initializer = Expression() ] { if (initializer == null) { return new VariableDeclaration(currentSegment, varName.toCharArray(), pos, SimpleCharStream.getPosition()); } return new VariableDeclaration(currentSegment, varName.toCharArray(), initializer, pos); } } EmptyStatement EmptyStatement() : { final int pos; } { {pos = SimpleCharStream.getPosition(); return new EmptyStatement(pos-1,pos);} } Statement StatementExpression() : { Expression expr,expr2; int operator; } { expr = PreIncDecExpression() {return expr;} | expr = PrimaryExpression() [ {return new PostfixedUnaryExpression(expr, OperatorIds.PLUS_PLUS, SimpleCharStream.getPosition());} | {return new PostfixedUnaryExpression(expr, OperatorIds.MINUS_MINUS, SimpleCharStream.getPosition());} | operator = AssignmentOperator() expr2 = Expression() {return new BinaryExpression(expr,expr2,operator);} ] {return expr;} } SwitchStatement SwitchStatement() : { final Expression variable; final AbstractCase[] cases; final int pos = SimpleCharStream.getPosition(); } { try { } catch (ParseException e) { errorMessage = "'(' expected after 'switch'"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { variable = Expression() } catch (ParseException e) { if (errorMessage != null) { throw e; } errorMessage = "expression expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { } catch (ParseException e) { errorMessage = "')' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } (cases = switchStatementBrace() | cases = switchStatementColon(pos, pos + 6)) {return new SwitchStatement(variable,cases,pos,SimpleCharStream.getPosition());} } AbstractCase[] switchStatementBrace() : { AbstractCase cas; final ArrayList cases = new ArrayList(); } { ( cas = switchLabel0() {cases.add(cas);})* try { { AbstractCase[] abcase = new AbstractCase[cases.size()]; cases.toArray(abcase); return abcase;} } catch (ParseException e) { errorMessage = "'}' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.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 */ AbstractCase[] switchStatementColon(final int start, final int end) : { AbstractCase cas; final ArrayList cases = new ArrayList(); } { {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); }} ( cas = switchLabel0() {cases.add(cas);})* try { } catch (ParseException e) { errorMessage = "'endswitch' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { { AbstractCase[] abcase = new AbstractCase[cases.size()]; cases.toArray(abcase); return abcase;} } catch (ParseException e) { errorMessage = "';' expected after 'endswitch' keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } } AbstractCase switchLabel0() : { final Expression expr; Statement statement; final ArrayList stmts = new ArrayList(); final int pos = SimpleCharStream.getPosition(); } { expr = SwitchLabel() ( statement = BlockStatementNoBreak() {stmts.add(statement);} | statement = htmlBlock() {stmts.add(statement);})* [ statement = BreakStatement() {stmts.add(statement);}] { Statement[] stmtsArray = new Statement[stmts.size()]; stmts.toArray(stmtsArray); if (expr == null) {//it's a default return new DefaultCase(stmtsArray,pos,SimpleCharStream.getPosition()); } return new Case(expr,stmtsArray,pos,SimpleCharStream.getPosition());} } /** * A SwitchLabel. * case Expression() : * default : * @return the if it was a case and null if not */ Expression SwitchLabel() : { final Expression expr; } { token = try { expr = Expression() } catch (ParseException e) { if (errorMessage != null) throw e; errorMessage = "expression expected after 'case' keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { {return expr;} } catch (ParseException e) { errorMessage = "':' expected after case expression"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } | token = <_DEFAULT> try { {return null;} } catch (ParseException e) { errorMessage = "':' expected after 'default' keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } } Break BreakStatement() : { Expression expression = null; final int start = SimpleCharStream.getPosition(); } { [ expression = Expression() ] try { } catch (ParseException e) { errorMessage = "';' expected after 'break' keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } {return new Break(expression, start, SimpleCharStream.getPosition());} } IfStatement IfStatement() : { final int pos = SimpleCharStream.getPosition(); Expression condition; IfStatement ifStatement; } { condition = Condition("if") ifStatement = IfStatement0(condition, pos,pos+2) {return ifStatement;} } Expression Condition(final String keyword) : { final Expression condition; } { try { } catch (ParseException e) { errorMessage = "'(' expected after " + keyword + " keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length(); errorEnd = errorStart +1; processParseException(e); } condition = Expression() try { } catch (ParseException e) { errorMessage = "')' expected after " + keyword + " keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; processParseException(e); } {return condition;} } IfStatement IfStatement0(Expression condition, final int start,final int end) : { Statement statement; Statement stmt; final Statement[] statementsArray; ElseIf elseifStatement; Else elseStatement = null; ArrayList stmts; final ArrayList elseIfList = new ArrayList(); ElseIf[] elseIfs; int pos = SimpleCharStream.getPosition(); int endStatements; } { {stmts = new ArrayList();} ( statement = Statement() {stmts.add(statement);} | statement = htmlBlock() {stmts.add(statement);})* {endStatements = SimpleCharStream.getPosition();} (elseifStatement = ElseIfStatementColon() {elseIfList.add(elseifStatement);})* [elseStatement = 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 = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { } catch (ParseException e) { errorMessage = "';' expected after 'endif' keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } { elseIfs = new ElseIf[elseIfList.size()]; elseIfList.toArray(elseIfs); if (stmts.size() == 1) { return new IfStatement(condition, (Statement) stmts.get(0), elseIfs, elseStatement, pos, SimpleCharStream.getPosition()); } else { statementsArray = new Statement[stmts.size()]; stmts.toArray(statementsArray); return new IfStatement(condition, new Block(statementsArray,pos,endStatements), elseIfs, elseStatement, pos, SimpleCharStream.getPosition()); } } | (stmt = Statement() | stmt = htmlBlock()) ( LOOKAHEAD(1) elseifStatement = ElseIfStatement() {elseIfList.add(elseifStatement);})* [ LOOKAHEAD(1) try { {pos = SimpleCharStream.getPosition();} statement = Statement() {elseStatement = new Else(statement,pos,SimpleCharStream.getPosition());} } catch (ParseException e) { if (errorMessage != null) { throw e; } errorMessage = "unexpected token '"+e.currentToken.next.image+"', a statement was expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } ] { elseIfs = new ElseIf[elseIfList.size()]; elseIfList.toArray(elseIfs); return new IfStatement(condition, stmt, elseIfs, elseStatement, pos, SimpleCharStream.getPosition());} } ElseIf ElseIfStatementColon() : { Expression condition; Statement statement; final ArrayList list = new ArrayList(); final int pos = SimpleCharStream.getPosition(); } { condition = Condition("elseif") ( statement = Statement() {list.add(statement);} | statement = htmlBlock() {list.add(statement);})* { Statement[] stmtsArray = new Statement[list.size()]; list.toArray(stmtsArray); return new ElseIf(condition,stmtsArray ,pos,SimpleCharStream.getPosition());} } Else ElseStatementColon() : { Statement statement; final ArrayList list = new ArrayList(); final int pos = SimpleCharStream.getPosition(); } { ( statement = Statement() {list.add(statement);} | statement = htmlBlock() {list.add(statement);})* { Statement[] stmtsArray = new Statement[list.size()]; list.toArray(stmtsArray); return new Else(stmtsArray,pos,SimpleCharStream.getPosition());} } ElseIf ElseIfStatement() : { Expression condition; Statement statement; final ArrayList list = new ArrayList(); final int pos = SimpleCharStream.getPosition(); } { condition = Condition("elseif") statement = Statement() {list.add(statement);/*todo:do better*/} { Statement[] stmtsArray = new Statement[list.size()]; list.toArray(stmtsArray); return new ElseIf(condition,stmtsArray,pos,SimpleCharStream.getPosition());} } WhileStatement WhileStatement() : { final Expression condition; final Statement action; final int pos = SimpleCharStream.getPosition(); } { condition = Condition("while") action = WhileStatement0(pos,pos + 5) {return new WhileStatement(condition,action,pos,SimpleCharStream.getPosition());} } Statement WhileStatement0(final int start, final int end) : { Statement statement; final ArrayList stmts = new ArrayList(); final int pos = SimpleCharStream.getPosition(); } { (statement = Statement() {stmts.add(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 = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { { Statement[] stmtsArray = new Statement[stmts.size()]; stmts.toArray(stmtsArray); return new Block(stmtsArray,pos,SimpleCharStream.getPosition());} } catch (ParseException e) { errorMessage = "';' expected after 'endwhile' keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } | statement = Statement() {return statement;} } DoStatement DoStatement() : { final Statement action; final Expression condition; final int pos = SimpleCharStream.getPosition(); } { action = Statement() condition = Condition("while") try { {return new DoStatement(condition,action,pos,SimpleCharStream.getPosition());} } catch (ParseException e) { errorMessage = "unexpected token : '"+ e.currentToken.next.image +"'. A ';' was expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } } ForeachStatement ForeachStatement() : { Statement statement; Expression expression; final int pos = SimpleCharStream.getPosition(); ArrayVariableDeclaration variable; } { try { } catch (ParseException e) { errorMessage = "'(' expected after 'foreach' keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { expression = Expression() } catch (ParseException e) { errorMessage = "variable expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { } catch (ParseException e) { errorMessage = "'as' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { variable = ArrayVariable() } catch (ParseException e) { errorMessage = "variable expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { } catch (ParseException e) { errorMessage = "')' expected after 'foreach' keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { statement = Statement() } catch (ParseException e) { if (errorMessage != null) throw e; errorMessage = "statement expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } {return new ForeachStatement(expression, variable, statement, pos, SimpleCharStream.getPosition());} } ForStatement ForStatement() : { final Token token; final int pos = SimpleCharStream.getPosition(); Statement[] initializations = null; Expression condition = null; Statement[] increments = null; Statement action; final ArrayList list = new ArrayList(); final int startBlock, endBlock; } { token = try { } catch (ParseException e) { errorMessage = "'(' expected after 'for' keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } [ initializations = ForInit() ] [ condition = Expression() ] [ increments = StatementExpressionList() ] ( action = Statement() {return new ForStatement(initializations,condition,increments,action,pos,SimpleCharStream.getPosition());} | {startBlock = SimpleCharStream.getPosition();} (action = Statement() {list.add(action);})* { 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); } } {endBlock = SimpleCharStream.getPosition();} try { } catch (ParseException e) { errorMessage = "'endfor' expected"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } try { { Statement[] stmtsArray = new Statement[list.size()]; list.toArray(stmtsArray); return new ForStatement(initializations,condition,increments,new Block(stmtsArray,startBlock,endBlock),pos,SimpleCharStream.getPosition());} } catch (ParseException e) { errorMessage = "';' expected after 'endfor' keyword"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } ) } Statement[] ForInit() : { Statement[] statements; } { LOOKAHEAD(LocalVariableDeclaration()) statements = LocalVariableDeclaration() {return statements;} | statements = StatementExpressionList() {return statements;} } Statement[] StatementExpressionList() : { final ArrayList list = new ArrayList(); Statement expr; } { expr = StatementExpression() {list.add(expr);} ( StatementExpression() {list.add(expr);})* { Statement[] stmtsArray = new Statement[list.size()]; list.toArray(stmtsArray); return stmtsArray;} } Continue ContinueStatement() : { Expression expr = null; final int pos = SimpleCharStream.getPosition(); } { [ expr = Expression() ] try { {return new Continue(expr,pos,SimpleCharStream.getPosition());} } catch (ParseException e) { errorMessage = "';' expected after 'continue' statement"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } } ReturnStatement ReturnStatement() : { Expression expr = null; final int pos = SimpleCharStream.getPosition(); } { [ expr = Expression() ] try { {return new ReturnStatement(expr,pos,SimpleCharStream.getPosition());} } catch (ParseException e) { errorMessage = "';' expected after 'return' statement"; errorLevel = ERROR; errorStart = SimpleCharStream.getPosition() - e.currentToken.next.image.length() + 1; errorEnd = SimpleCharStream.getPosition() + 1; throw e; } }