- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一种语言,基本上是为了将列映射到数组中的新结构。该语言旨在让产品经理无需了解大量编程细节即可定义映射。我确信这里还有很多需要改进的地方,但这就是我所拥有的。
大部分情况下,该语言都有效。我遇到的问题是条件语句。
我的解析器有以下规则:
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
帮助构建您自己的节点,但就我个人而言,我发现创建自定义节点类(或多个类)并使用它们最简单。一个演示来澄清:
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();};
我创建了一个 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();
}
}
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/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!