| syntax XPath(k = 0) { | |
| primitiveTemplate identifier for String default using NAME: | |
| value = "%token%"; | |
| primitiveTemplate stringSymbol for String using STRING: | |
| value = "%token%", | |
| serializer="'\'' + %value%.toCString() + '\''"; | |
| primitiveTemplate integerSymbol for Integer default using INT: | |
| value = "Integer.valueOf(%token%)"; | |
| primitiveTemplate floatSymbol for Double default using FLOAT: | |
| value = "Double.valueOf(%token%)"; | |
| -- Expressions | |
| template Expression main abstract operatored; | |
| template VariableExp | |
| : "$" name | |
| ; | |
| template PathExpression | |
| : | |
| -- (isAbsolute ? "/") | |
| -- steps{separator = "/"} | |
| (isAbsolute ? | |
| "/" steps{separator = "/"} | |
| : | |
| steps{separator = "/", forcedLower = 1} | |
| ) | |
| ; | |
| template Step(disambiguate = "(step)=>") | |
| : | |
| [[ axis nodeTest | |
| | "." -- {{axis <- new SelfAxis, nodeTest <- new IsNodeTest}} -- self::node() | |
| | ".." -- {{axis <- new ParentAxis, nodeTest <- new IsNodeTest}} -- parent::node() | |
| ]] | |
| predicates | |
| ; | |
| template Predicate | |
| : "[" expression "]" | |
| ; | |
| operatorTemplate OperatorCallExp(operators = | |
| opUnion | |
| opMinus1 | |
| opMul opDiv opMod | |
| opPlus opMinus | |
| opLT | |
| opLE | |
| opGT | |
| opGE | |
| opEQ | |
| opNE | |
| opAnd | |
| opOr, | |
| source = 'left', storeOpTo = name, storeRightTo = 'right'); | |
| template FunctionCallExp(disambiguate = "NAME LPAREN") | |
| : name "(" arguments{separator = ","} ")" | |
| ; | |
| template LiteralExp abstract; | |
| template IntegerExp | |
| : symbol | |
| ; | |
| template StringExp | |
| : symbol{as = stringSymbol} | |
| ; | |
| -- End Expressions | |
| -- NodeTests | |
| template NodeTest abstract; | |
| template NameTest | |
| : name | |
| ; | |
| template WildCardTest | |
| : "*" | |
| ; | |
| template IsNodeTest | |
| : "node" "(" ")" | |
| ; | |
| template IsTextTest | |
| : "text" "(" ")" | |
| ; | |
| -- End NodeTests | |
| -- Axes | |
| template Axis abstract; | |
| template AncestorAxis | |
| : "ancestor" "::" | |
| ; | |
| template AncestorOrSelfAxis | |
| : "ancestor-or-self" "::" | |
| ; | |
| template AttributeAxis | |
| : [[ "attribute" "::" | |
| | "@" | |
| ]] | |
| ; | |
| template ChildAxis | |
| : [[ "child" "::" | |
| | -- *nothing* is equivalent to child:: | |
| ]] | |
| ; | |
| template DescendantAxis | |
| : "descendant" "::" | |
| ; | |
| template DescendantOrSelfAxis | |
| : "descendant-or-self" "::" | |
| ; | |
| template FollowingAxis | |
| : "following" "::" | |
| ; | |
| template FollowingSiblingAxis | |
| : "following-sibling" "::" | |
| ; | |
| template NamespaceAxis | |
| : "namespace" "::" | |
| ; | |
| template ParentAxis | |
| : "parent" "::" | |
| ; | |
| template PrecedingAxis | |
| : "preceding" "::" | |
| ; | |
| template PrecedingSiblingAxis | |
| : "preceding-sibling" "::" | |
| ; | |
| template SelfAxis | |
| : "self" "::" | |
| ; | |
| -- End Axes | |
| symbols { | |
| dollar = "$"; | |
| lsquare = "["; | |
| rsquare = "]"; | |
| lparen = "("; | |
| rparen = ")"; | |
| colons = "::"; | |
| point = "."; | |
| pointpoint = ".."; | |
| arobas = "@"; | |
| slash = "/"; | |
| -- operator symbols | |
| pipe = "|"; | |
| minus = "-"; | |
| star = "*"; | |
| slashslash = "//"; | |
| plus = "+"; | |
| eq = "="; | |
| gt = ">"; | |
| lt = "<"; | |
| ge = ">="; | |
| le = "<="; | |
| excleq = "!="; | |
| } | |
| operators { | |
| priority 0 { | |
| -- opPredicate [] | |
| } | |
| priority 1 { | |
| -- opChild = slash, 2; | |
| -- opDescendant = slashslash, 2; | |
| } | |
| priority 2 { | |
| opUnion = pipe, 2; | |
| } | |
| priority 3 { | |
| opMinus1 = minus, 1; | |
| } | |
| priority 4 { | |
| opMul = star, 2; | |
| opDiv = "div", 2; | |
| opMod = "mod", 2; | |
| } | |
| priority 5 { | |
| opPlus = plus, 2; | |
| opMinus = minus, 2; | |
| } | |
| priority 6 { | |
| opLT = lt, 2; | |
| opLE = le, 2; | |
| opGT = gt, 2; | |
| opGE = ge, 2; | |
| } | |
| priority 7 { | |
| opEQ = eq, 2; | |
| opNE = excleq, 2; | |
| } | |
| priority 8 { | |
| opAnd = "and", 2; | |
| } | |
| priority 9 { | |
| opOr = "or", 2; | |
| } | |
| } | |
| token COMMENT : endOfLine(start = "--"); | |
| lexer = " | |
| %options testLiterals = false; | |
| NL | |
| : ( '\\r' '\\n' | |
| | '\\n' '\\r' //Improbable | |
| | '\\r' | |
| | '\\n' | |
| ) | |
| {newline();} | |
| ; | |
| WS | |
| : ( ' ' | |
| | '\\t' | |
| ) | |
| ; | |
| %protected | |
| DIGIT | |
| : '0'..'9' | |
| ; | |
| %protected | |
| ALPHA | |
| : 'a'..'z' | |
| | 'A'..'Z' | |
| | '_' | |
| //For Unicode compatibility (from 0000 to 00ff) | |
| | '\\u00C0' .. '\\u00D6' | |
| | '\\u00D8' .. '\\u00F6' | |
| | '\\u00F8' .. '\\u00FF' | |
| ; | |
| %protected | |
| SNAME | |
| %v2 options { | |
| %v2 testLiterals = true; | |
| %v2 } | |
| : (ALPHA) (ALPHA | DIGIT)* | |
| ; | |
| NAME | |
| : ( | |
| %v3 SNAME | |
| %v2 s:SNAME {if(s.getType() != SNAME) $setType(s.getType());} | |
| | '\"'! | |
| ( ESC | |
| | '\\n' {newline();} | |
| | ~('\\\\'|'\\\"'|'\\n') | |
| )* | |
| '\"'! | |
| %v3 {setText(ei.unescapeString(getText(), 1));} | |
| ) | |
| ; | |
| INT | |
| : (DIGIT)+ | |
| %v2 (('.' DIGIT)=> '.' (DIGIT)+ {$setType(FLOAT);})? | |
| ; | |
| %v3 FLOAT : DIGIT+ (('.' DIGIT)=>'.' DIGIT+)? ; // cannot accept DIGIT '.' because it would conflict with Navigation | |
| %protected | |
| ESC | |
| : '\\\\'! | |
| ( 'n' %v2{%setText(\"\\n\");} | |
| | 'r' %v2{%setText(\"\\r\");} | |
| | 't' %v2{%setText(\"\\t\");} | |
| | 'b' %v2{%setText(\"\\b\");} | |
| | 'f' %v2{%setText(\"\\f\");} | |
| | '\"' %v2{%setText(\"\\\"\");} | |
| | '\\'' %v2{%setText(\"\\'\");} | |
| | '\\\\' %v2{%setText(\"\\\\\");} | |
| | ( | |
| ('0'..'3') | |
| ( | |
| %v2 options { | |
| %v2 warnWhenFollowAmbig = false; | |
| %v2 } | |
| : ('0'..'7') | |
| ( | |
| %v2 options { | |
| %v2 warnWhenFollowAmbig = false; | |
| %v2 } | |
| : '0'..'7' | |
| )? | |
| )? | |
| | ('4'..'7') | |
| ( | |
| %v2 options { | |
| %v2 warnWhenFollowAmbig = false; | |
| %v2 } | |
| : ('0'..'7') | |
| )? | |
| ) | |
| { | |
| %v2 String s = %getText; | |
| %v2 int i; | |
| %v2 int ret = 0; | |
| %v2 String ans; | |
| %v2 for (i=0; i<s.length(); ++i) | |
| %v2 ret = ret*8 + s.charAt(i) - '0'; | |
| %v2 ans = String.valueOf((char) ret); | |
| %v2 %setText(ans); | |
| } | |
| ) | |
| ; | |
| STRING | |
| : '\\''! | |
| ( ESC | |
| | '\\n' {newline();} | |
| | ~('\\\\'|'\\''|'\\n') | |
| )* | |
| '\\''! | |
| %v3 {setText(ei.unescapeString(getText(), 1));} | |
| ; | |
| "; | |
| } |