[antlr-interest] Embedding expressions in plain text -- how to?
Rob Greene
robgreene at gmail.com
Sat Nov 10 11:59:25 PST 2007
How should I go about embedding an expression language in plain text. The
expression is wrapped in '${' and '}' but may occur zero to many times
within plain text. When in plain text, I want to keep the whitespace, but
within the expression, it should be ignored.
I've currently placed a boolean into a ThreadLocal and check that before
calling skip() in my whitespace rule. But, that causes issues with the
actual expressions.
For instance, "${true}" returns Boolean.TRUE while "${ true }" returns a
null. If I take out the test in WS, I can have those spaces within an
expression, but the plain text loses all white space.
I'm certain this is a simple fix, but I haven't a clue what to do!
I'm using ANTLR 3.0.1.
Thanks!
-Rob
/**
* Language is the simple expression language used throughout the XML
Template Engine.
* General language constructs:
* - functionName(argument, argument, ...)
* - object.method.method
* - 'string constant'
* - "string constant"
* - 1234.56
* - true
* - false
* - null
* - [ array, values, ... ]
*/
grammar Language;
/**
* Use the embeddedExpression entry for expressions that are embedded within
other
* forms of text.
* <p>
* Note that unknown magic occurs because the plainText is somehow
* glommed together into one string instead of character
* by character.
*/
embeddedExpression returns [List<Object> list]
@init { list = new ArrayList<Object>(); }
: ( '${' expression '}' { list.add($expression.value); }
| plainText { list.add($plainText.value); }
)*
;
/**
* Handle plain text that wraps around the expression.
*/
plainText returns [String value]
@init { ThreadState.current().ignoreWhitespace = false; }
@after { ThreadState.current().ignoreWhitespace = true; }
: '\\' '$' { $value = "$"; }
| '\\' b=~('$') { $value = $b.text; }
| a=~('$') { $value = $a.text; }
;
/**
* This is the bare expression evaluation. Evaluates one expression and
returns
* an Object.
*/
expression returns [Object value]
: function { $value = $function.value; }
| constant { $value = $constant.value; }
| reference { $value = $reference.value; }
;
/**
* Evaluate a function invocation, along with parameters and return the
Object result.
*/
function returns [Object value]
: ID '(' arguments ')' { $value =
Helper.invoke($ID.text,$arguments.value);
}
;
catch [LanguageException le] {
emitErrorMessage(le.getMessage());
throw new RuntimeException(le);
}
/**
* Evaluate a constant value and return that value.
*/
constant returns [Object value]
: STRING { $value =
$STRING.text.substring(1,$STRING.text.length()-1); }
| NUMBER { $value = Double.valueOf($NUMBER.text); }
| 'true' { $value = Boolean.TRUE; }
| 'false' { $value = Boolean.FALSE; }
| 'null' { $value = null; }
| '[' arguments ']' { $value = $arguments.value; }
;
/**
* Evaluate an object reference and any nested evaluations and return that
value.
*/
reference returns [Object value]
: a=ID { $value = Helper.find($a.text); }
('.' b=ID { $value = Helper.reflect($value,$b.text); }
)*
;
catch [LanguageException le] {
emitErrorMessage(le.getMessage());
throw new RuntimeException(le);
}
/**
* A comma-separated argument list. Use for the function invocation and
array list.
*/
arguments returns [List<Object> value]
@init { value = new ArrayList<Object>(); }
: (a=expression { $value.add($a.value); }
(',' b=expression { $value.add($b.value); }
)* )?
;
ID : Char (Char|Digit)*
;
STRING : '"' ~('"')* '"'
| '\'' ~('\'')* '\''
;
NUMBER : ('-'|'+')? Digit+ ('.' Digit+)?
;
WS
: (' '|'\t'|'\r'|'\n')+ { if
(!ThreadState.current().ignoreWhitespace) skip(); }
;
fragment Char
: 'a'..'z' | 'A'..'Z' | '_'
;
fragment Digit
: '0'..'9'
;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org/pipermail/antlr-interest/attachments/20071110/3fecfd0b/attachment-0001.html
More information about the antlr-interest
mailing list