/** The cursor in expression stack. */
private static int nodePtr;
- public static final boolean PARSER_DEBUG = true;
+ public static final boolean PARSER_DEBUG = false;
public final void setFileToParse(final IFile fileToParse) {
PHPParser.fileToParse = fileToParse;
|
<#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
|
- <STRING_LITERAL: (<STRING_1> | <STRING_2> | <STRING_3>)>
-| <STRING_1: "\"" ( ~["\"","\\"] | "\\" ~[] )* "\"">
+ <STRING_LITERAL: (<STRING_2> | <STRING_3>)>
+//| <STRING_1: "\"" ( ~["\"","\\"] | "\\" ~[] )* "\"">
| <STRING_2: "'" ( ~["'","\\"] | "\\" ~[] )* "'">
| <STRING_3: "`" ( ~["`","\\"] | "\\" ~[] )* "`">
}
+<IN_STRING,DOLLAR_IN_STRING> SKIP :
+{
+ <ESCAPED : ("\\" ~[])> : IN_STRING
+}
+
+<PHPPARSING> TOKEN :
+{
+ <DOUBLEQUOTE : "\""> : IN_STRING
+}
+
+
+<IN_STRING> TOKEN :
+{
+ <DOLLARS : "$"> : DOLLAR_IN_STRING
+}
+
+<IN_STRING,DOLLAR_IN_STRING> TOKEN :
+{
+ <DOUBLEQUOTE2 : "\""> : PHPPARSING
+}
+
+<DOLLAR_IN_STRING> TOKEN :
+{
+ <LBRACE1 : "{"> : DOLLAR_IN_STRING_EXPR
+}
+
+<IN_STRING> SPECIAL_TOKEN :
+{
+ <"{"> : SKIPSTRING
+}
+
+<SKIPSTRING> SPECIAL_TOKEN :
+{
+ <"}"> : IN_STRING
+}
+
+<SKIPSTRING> SKIP :
+{
+ <~[]>
+}
+
+<DOLLAR_IN_STRING_EXPR> TOKEN :
+{
+ <RBRACE1 : "}"> : DOLLAR_IN_STRING
+}
+
+<DOLLAR_IN_STRING_EXPR> TOKEN :
+{
+ <ID : (~["}"])*>
+}
+
+<IN_STRING> SKIP :
+{
+ <~[]>
+}
+
+<DOLLAR_IN_STRING_EXPR,IN_STRING> SKIP :
+{
+ <~[]>
+}
/* IDENTIFIERS */
<PHPPARSING,IN_VARIABLE> TOKEN : {<DOLLAR : "$"> : IN_VARIABLE}
-<PHPPARSING, IN_VARIABLE> TOKEN :
+<PHPPARSING, IN_VARIABLE, DOLLAR_IN_STRING> TOKEN :
{
<IDENTIFIER: (<LETTER>|<SPECIAL>) (<LETTER>|<DIGIT>|<SPECIAL>)* >
|
>
}
+<DOLLAR_IN_STRING> SPECIAL_TOKEN :
+{
+ < ~[] > : IN_STRING
+}
/* SEPARATORS */
<PHPPARSING,IN_VARIABLE> TOKEN :
Literal Literal() :
{
final Token token;
+ StringLiteral literal;
}
{
token = <INTEGER_LITERAL> {return new NumberLiteral(token);}
| token = <TRUE> {return new TrueLiteral(token);}
| token = <FALSE> {return new FalseLiteral(token);}
| token = <NULL> {return new NullLiteral(token);}
+| literal = evaluableString() {return literal;}
+}
+
+StringLiteral evaluableString() :
+{
+ ArrayList list = new ArrayList();
+ Token start,end;
+ Token token,lbrace,rbrace;
+ AbstractVariable var;
+ Expression expr;
+}
+{
+ start = <DOUBLEQUOTE>
+ (
+ <DOLLARS>
+ (
+ token = <IDENTIFIER> {list.add(new Variable(token.image,
+ token.sourceStart,
+ token.sourceEnd));}
+ |
+ lbrace = <LBRACE1>
+ token = <ID>
+ {list.add(new Variable(token.image,
+ token.sourceStart,
+ token.sourceEnd));}
+ rbrace = <RBRACE1>
+ )
+ )*
+ end = <DOUBLEQUOTE2>
+ {
+ AbstractVariable[] vars = new AbstractVariable[list.size()];
+ list.toArray(vars);
+ return new StringLiteral(SimpleCharStream.currentBuffer.substring(start.sourceEnd,end.sourceStart),
+ start.sourceStart,
+ end.sourceEnd,
+ vars);
+ }
}
FunctionCall Arguments(final Expression func) :
{
Expression[] args = null;
-final Token token;
+final Token token,lparen;
}
{
- <LPAREN> [ args = ArgumentList() ]
+ lparen = <LPAREN> [ args = ArgumentList() ]
try {
token = <RPAREN>
{return new FunctionCall(func,args,token.sourceEnd);}
} catch (ParseException e) {
errorMessage = "unexpected token : '"+ e.currentToken.next.image +"', ')' expected to close the argument list";
errorLevel = ERROR;
- errorStart = args[args.length-1].sourceEnd+1;
- errorEnd = args[args.length-1].sourceEnd+1;
+ if (args == null) {
+ errorStart = lparen.sourceEnd+1;
+ errorEnd = lparen.sourceEnd+2;
+ } else {
+ errorStart = args[args.length-1].sourceEnd+1;
+ errorEnd = args[args.length-1].sourceEnd+2;
+ }
processParseExceptionDebug(e);
}
{return new FunctionCall(func,args,args[args.length-1].sourceEnd);}
token = <_DEFAULT>
try {
<COLON>
- {return null;}
} catch (ParseException e) {
errorMessage = "':' expected after 'default' keyword";
errorLevel = ERROR;
errorEnd = token.sourceEnd+1;
processParseExceptionDebug(e);
}
+ {return null;}
}
Break BreakStatement() :