gpt4 book ai didi

java - if then else 条件判断

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:26:19 25 4
gpt4 key购买 nike

我有一种语言,基本上是为了将列映射到数组中的新结构。该语言旨在让产品经理无需了解大量编程细节即可定义映射。我确信这里还有很多需要改进的地方,但这就是我所拥有的。

大部分情况下,该语言都有效。我遇到的问题是条件语句。

我的解析器有以下规则:

conditionalexpr :  IF^ LPAREN! (statement) RPAREN! THEN! LCURLY! statement RCURLY! (ELSE! LCURLY! statement RCURLY!)?;

生成一棵具有三个 child 的树。

我的问题是在条件不允许的情况下避免评估语句。

我很天真地做了:

conditionalexpr returns[Object o]: 
^(IF a=statement b=statement (c=statement)?)
{
$o = (Boolean)$a.o ? $b.o : $c.o != null ? $c.o : "";
}
;

显然这行不通。

我一直在研究句法谓词,但我无法使它们正常工作。

语句当前返回一个对象。大多数语言处理字符串,但我也需要支持 boolean 值和数字(整数和小数)。

如果我添加类似 {$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();};

主程序.java

我创建了一个 Node具有 eval(): Object 的界面方法,还创建了一个抽象类 BinaryNode实现Node并且总是有 2 个 child 。正如您在这些 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, Node right) { super(left, right); }

@Override
public Object eval() {
return (Boolean)super.left.eval() && (Boolean)super.right.eval();
}
}

class LTNode extends BinaryNode {

public LTNode(Node left, Node right) { super(left, right); }

@Override
public Object eval() {
return (Double)super.left.eval() < (Double)super.right.eval();
}
}

class LTEqNode extends BinaryNode {

public LTEqNode(Node left, Node right) { super(left, right); }

@Override
public Object eval() {
return (Double)super.left.eval() <= (Double)super.right.eval();
}
}

class GTNode extends BinaryNode {

public GTNode(Node left, Node right) { super(left, right); }

@Override
public Object eval() {
return (Double)super.left.eval() > (Double)super.right.eval();
}
}

class GTEqNode extends BinaryNode {

public GTEqNode(Node left, Node right) { super(left, right); }

@Override
public Object eval() {
return (Double)super.left.eval() >= (Double)super.right.eval();
}
}

class EqNode extends BinaryNode {

public EqNode(Node left, Node right) { super(left, right); }

@Override
public Object eval() {
return super.left.eval().equals(super.right.eval());
}
}

class NEqNode extends BinaryNode {

public NEqNode(Node left, Node right) { super(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

true正在打印到控制台:

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 .

祝你好运!

关于java - if then else 条件判断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6598975/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com