java – if then else条件评估
|
我有一种语言,基本上是将列映射到数组中的新结构.该语言旨在让产品经理定义映射,而无需了解大量编程细节.我相信这里有很多改进,但这就是我所拥有的. 这种语言主要起作用.我遇到的问题是条件语句. 我的解析器有以下规则: conditionalexpr : IF^ LPAREN! (statement) RPAREN! THEN! LCURLY! statement RCURLY! (ELSE! LCURLY! statement RCURLY!)?; 这适用于生成有三个孩子的树. 我的问题是如果条件不允许,则避免评估语句. 天真地我做了: conditionalexpr returns[Object o]:
^(IF a=statement b=statement (c=statement)?)
{
$o = (Boolean)$a.o ? $b.o : $c.o != null ? $c.o : "";
}
;
显然这不起作用. 我一直在玩语法谓词,但我不能让它们正常工作. 语句当前返回一个对象.主要是语言处理字符串,但我需要支持布尔值和数字(整数和小数). 如果我添加{$a.o}?=>之类的内容我在生成的代码中得到$a. 我查看了antlr-interest列表,但这个问题并没有得到很好的回答,很可能是因为它对他们来说似乎很明显. 我愿意发布完整的语法但是已经把它留下来保持这个简短. 解决方法如果您不希望评估某些子树,则需要让树规则返回节点而不是实际值.您可以扩展CommonTree并提供自定义TreeAdaptor来帮助构建自己的节点,但就个人而言,我发现最简单的方法是创建自定义节点类(或类)并使用它们.一个演示澄清:T.G grammar T;
options {
output=AST;
}
tokens {
ASSIGNMENT;
}
parse
: statement+ EOF -> statement+
;
statement
: ifStatement
| assignment
;
ifStatement
: IF a=expression THEN b=expression (ELSE c=expression)? -> ^(IF $a $b $c?)
;
assignment
: ID '=' expression -> ^(ASSIGNMENT ID expression)
;
expression
: orExpression
;
orExpression
: andExpression (OR^ andExpression)*
;
andExpression
: equalityExpression (AND^ equalityExpression)*
;
equalityExpression
: relationalExpression (('==' | '!=')^ relationalExpression)*
;
relationalExpression
: atom (('<=' | '<' | '>=' | '>')^ atom)*
;
atom
: BOOLEAN
| NUMBER
| ID
| '(' expression ')' -> expression
;
IF : 'if';
THEN : 'then';
ELSE : 'else';
OR : 'or';
AND : 'and';
BOOLEAN : 'true' | 'false';
ID : ('a'..'z' | 'A'..'Z')+;
NUMBER : '0'..'9'+ ('.' '0'..'9'+)?;
SPACE : (' ' | 't' | 'r' | 'n') {skip();};
Main.java 我创建了一个具有eval():Object方法的Node接口,还创建了一个实现Node的抽象类BinaryNode,并且总是有2个子节点.正如您在这些Java类之后的树语法中所看到的,所有规则现在都返回一个Node. import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
public class Main {
public static void main(String[] args) throws Exception {
String source = "a = 3 b = 4 if b > a then b==b else c==c";
TLexer lexer = new TLexer(new ANTLRStringStream(source));
TParser parser = new TParser(new CommonTokenStream(lexer));
TWalker walker = new TWalker(new CommonTreeNodeStream(parser.parse().getTree()));
Node root = walker.walk();
System.out.println(root.eval());
}
}
interface Node {
Object eval();
}
abstract class BinaryNode implements Node {
protected Node left;
protected Node right;
public BinaryNode(Node l,Node r) {
left = l;
right = r;
}
}
class AtomNode implements Node {
private Object value;
public AtomNode(Object v) {
value = v;
}
@Override
public Object eval() {
return value;
}
}
class OrNode extends BinaryNode {
public OrNode(Node left,Node right) { super(left,right); }
@Override
public Object eval() {
return (Boolean)super.left.eval() || (Boolean)super.right.eval();
}
}
class AndNode extends BinaryNode {
public AndNode(Node left,right); }
@Override
public Object eval() {
return (Boolean)super.left.eval() && (Boolean)super.right.eval();
}
}
class LTNode extends BinaryNode {
public LTNode(Node left,right); }
@Override
public Object eval() {
return (Double)super.left.eval() < (Double)super.right.eval();
}
}
class LTEqNode extends BinaryNode {
public LTEqNode(Node left,right); }
@Override
public Object eval() {
return (Double)super.left.eval() <= (Double)super.right.eval();
}
}
class GTNode extends BinaryNode {
public GTNode(Node left,right); }
@Override
public Object eval() {
return (Double)super.left.eval() > (Double)super.right.eval();
}
}
class GTEqNode extends BinaryNode {
public GTEqNode(Node left,right); }
@Override
public Object eval() {
return (Double)super.left.eval() >= (Double)super.right.eval();
}
}
class EqNode extends BinaryNode {
public EqNode(Node left,right); }
@Override
public Object eval() {
return super.left.eval().equals(super.right.eval());
}
}
class NEqNode extends BinaryNode {
public NEqNode(Node left,right); }
@Override
public Object eval() {
return !super.left.eval().equals(super.right.eval());
}
}
class VarNode implements Node {
private java.util.Map<String,Object> memory;
private String var;
VarNode(java.util.Map<String,Object> m,String v) {
memory = m;
var = v;
}
@Override
public Object eval() {
Object value = memory.get(var);
if(value == null) {
throw new RuntimeException("Unknown variable: " + var);
}
return value;
}
}
class IfNode implements Node {
private Node test;
private Node ifTrue;
private Node ifFalse;
public IfNode(Node a,Node b,Node c) {
test = a;
ifTrue = b;
ifFalse = c;
}
@Override
public Object eval() {
return (Boolean)test.eval() ? ifTrue.eval() : ifFalse.eval();
}
}
TWalker.g tree grammar TWalker;
options {
tokenVocab=T;
ASTLabelType=CommonTree;
}
@members {
private java.util.Map<String,Object> memory = new java.util.HashMap<String,Object>();
}
walk returns [Node n]
: (statement {$n = $statement.n;})+
;
statement returns [Node n]
: ifStatement {$n = $ifStatement.n;}
| assignment {$n = null;}
;
assignment
: ^(ASSIGNMENT ID expression) {memory.put($ID.text,$expression.n.eval());}
;
ifStatement returns [Node n]
: ^(IF a=expression b=expression c=expression?) {$n = new IfNode($a.n,$b.n,$c.n);}
;
expression returns [Node n]
: ^(OR a=expression b=expression) {$n = new OrNode($a.n,$b.n);}
| ^(AND a=expression b=expression) {$n = new AndNode($a.n,$b.n);}
| ^('==' a=expression b=expression) {$n = new EqNode($a.n,$b.n);}
| ^('!=' a=expression b=expression) {$n = new NEqNode($a.n,$b.n);}
| ^('<=' a=expression b=expression) {$n = new LTEqNode($a.n,$b.n);}
| ^('<' a=expression b=expression) {$n = new LTNode($a.n,$b.n);}
| ^('>=' a=expression b=expression) {$n = new GTEqNode($a.n,$b.n);}
| ^('>' a=expression b=expression) {$n = new GTNode($a.n,$b.n);}
| BOOLEAN {$n = new AtomNode(Boolean.valueOf($BOOLEAN.text));}
| NUMBER {$n = new AtomNode(Double.valueOf($NUMBER.text));}
| ID {$n = new VarNode(memory,$ID.text);}
;
如果您现在运行主类,并评估: a = 3 b = 4 if b > a then b==b else c==c 正在打印到控制台: bart@hades:~/Programming/ANTLR/Demos/T$java -cp antlr-3.3.jar org.antlr.Tool T.g bart@hades:~/Programming/ANTLR/Demos/T$java -cp antlr-3.3.jar org.antlr.Tool TWalker.g bart@hades:~/Programming/ANTLR/Demos/T$javac -cp antlr-3.3.jar *.java bart@hades:~/Programming/ANTLR/Demos/T$java -cp .:antlr-3.3.jar Main true 但是,如果你检查b< a,导致执行else,你会看到以下内容: Exception in thread "main" java.lang.RuntimeException: Unknown variable: c
at VarNode.eval(Main.java:140)
at EqNode.eval(Main.java:112)
at IfNode.eval(Main.java:160)
at Main.main(Main.java:11)
有关更复杂的语言结构(范围,函数等)的实现,请参阅my blog. 祝好运! (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
