|
|
|
|
|
|
|
|
Re: Trying to implement simple expressions in XTEXT [message #723226 is a reply to message #723181] |
Thu, 08 September 2011 05:45 |
|
Hi,
still don't get your problem:
Model:decls+=VariableDeclaration*;
Variable: name=ID;
Literal: NumericLiteral | StringLiteral | VarReference;
IntLiteral: value=INT;
DoubleLiteral: value=INT'.'INT;
NumericLiteral: IntLiteral | DoubleLiteral;
StringLiteral: value=STRING;
VarReference: '@' ref=[Variable];
VariableDeclaration:
var=Variable ':=' value+=Literal ('+' value+=Literal)* ';'
;
pasted in a newly create xtext project works like a charm to me
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
|
Re: Trying to implement simple expressions in XTEXT [message #723248 is a reply to message #723226] |
Thu, 08 September 2011 07:21 |
Daniel Missing name Messages: 101 Registered: July 2011 |
Senior Member |
|
|
Hi.
If you want to have a real expression tree like each programming language (and xbase) has, you would create a ruleset like this:
VariableDefinition:
name=ID ':=' value=Expression ';'
;
Expression returns IExpression:
MultiplicativeExpression
;
MultOp: '*' | '/' | '%';
MultiplicativeExpression returns IExpression:
AdditiveExpression ({BinaryExpression.current=this} operator=MultOp right=AdditiveExpression)*
;
AdditiveOp: '+' | '-';
AdditiveExpression returns IExpression:
PrimaryExpression ({BinaryExpression.current=this} operator=AdditiveOp right=PrimaryExpression)*
;
PrimaryExpression returns IExpression:
ILiteral
| ReferenceExpression
| ParenthesizedExpression
;
ParenthesizedExpression returns IExpression:
{ParenthesizedExpression}
'(' expression=Expression ')'
;
ReferenceExpression return IExpression:
{ReferenceExpression}
'@' variable=[VariableDefinition]
;
ILiteral returns IExpression:
StringLiteral
| NumberLiteral
;
StringLiteral returns IExpression:
{StringLiteral}
value=STRING
;
NumberLiteral returns IExpression:
{NumberLiteral}
value=Number
;
Number:
{IntegerNumber} value=INT
| {DoubleNumber} value=DOUBLE
;
terminal DOUBLE ecore::EDouble:
INT '.' INT
;
This will allow you to create a small interpreter using the polymorphic dispatcher (a very quick&dirty notepad version):
public class TypeEvaluationInterpreter {
private PolymorphicDispatcher<EvaluationResult> evalDispatcher =
PolymorphicDispatcher.createForSingleTarget("eval", this);
public EvaluationResult start(IExpression expression) throws EvaluationException {
// TODO: caching and cycle detection
this.evalDispatcher.invoke(expression);
}
protected EvaluationResult eval(BinaryExpression expression) throws EvaluationException {
EvaluationResult leftHandSide = this.evalDispatcher.invoke(reference.getLeft());
EvaluationResult rightHandSide = this.evalDispatcher.invoke(reference.getRight());
Type result = getResultType(Operation.getOperation(expression.getOperator()),
leftHandSide.getType(),
rightHandSide.getType());
return new EvaluationResult(result);
}
protected Type getResultType(Operation op, Type left, Type right) {
switch(op) {
case ADDITION:
// addition works for all types, higher priority type will be result
getHigherPriority(left, right);
break;
case SUBTRACTION:
case DIVISION:
case MODULO:
case MULTIPLICATION:
if(left == Type.STRING || right == Type.STRING) {
throw new EvaluationException("Operation '" + op.getOpString() + "' is undefined for types " + left + " and " + right);
}
getHigherPriority(left, right);
break;
}
}
protected Type getHigherPriority(Type left, Type right) {
if(left.getPriority() > right.getPriority()) {
return left;
}
else {
return right;
}
}
protected EvaluationResult eval(ParenthesizedExpression expression) {
return this.evalDispatcher.invoke(reference.getExpression());
}
protected EvaluationResult eval(ReferenceExpression expression) {
VariableDefinition reference = expression.getVariable();
return this.evalDispatcher.invoke(reference.getValue());
}
protected EvaluationResult eval(StringLiteral expression) {
return new EvaluationResult(Type.STRING);
}
protected EvaluationResult eval(NumberLiteral expression) {
return this.evalDispatcher.invoke(expression.getValue());
}
protected EvaluationResult eval(IntegerNumber expression) {
return new EvaluationResult(Type.INTEGER);
}
protected EvaluationResult eval(DoubleNumber expression) {
return new EvaluationResult(Type.DOUBLE);
}
public static class EvaluationResult {
private Type type;
public Type getType() { return this.type; }
public EvaluationResult(Type type) { this.type = type; }
}
public static enum Type {
INTEGER(0),
DOUBLE(1),
STRING(2);
private int priority;
public int getPriority() { return this.priority; }
public Type(int priority) { this.priority = priority; }
}
public static enum Operation {
ADDITION("+"),
SUBTRACTION("-"),
DIVISION("/"),
MODULO("%"),
MULTIPLICATION("*");
private String opString;
public String getOpString() { return this.opString; }
public Operation(String opString) { this.opString = opString; }
public static Operation getOperation(String opString) {
for(Operation op : values() {
if(op.getOpString().equals(opString)) {
return op;
}
}
return null;
}
}
}
In your java validator you simply call this interpreter and catch the exception to show an error.
The code is quite simple so you should understand it
Or: Simply use xbase for your needs xbase ships with exactly such a (more extended) expression tree and interpreter.
Cheers
Daniel
|
|
|
Powered by
FUDForum. Page generated in 0.03250 seconds