【问题标题】:goto statement in antlr?antlr 中的 goto 语句?
【发布时间】:2011-07-21 17:31:33
【问题描述】:

如果有人能给我建议,或者给我指点教程,或者示例实现,我真的很感激,任何可以帮助我在 ANTLR 中实现基本 goto 语句的东西?

感谢您的帮助

编辑。问题的第 2 版:

假设我有这个树结构:

(BLOCK (PRINT 1) (PRINT 2) (PRINT 3) (PRINT 4) )

现在,我很想知道有没有办法 选择,比如说,节点(PRINT 2)和后面的所有节点 那个节点 ((PRINT 2) (PRINT 3) (PRINT 4)) ?

我问这个是因为我正在尝试实施 基本的goto机制。 我有这样的打印声明:

i=LABEL print 
{interpreter.store($i.text, $print.tree);} //stores in hash table
-> print

然而 $print.tree 只是忽略了后面的节点, 所以输入:

label: print 1
print 2
goto label

将打印 121! (我想要的是无限循环1212...)

我也试过拿令牌 打印语句的地址 getTokenStartIndex() 和设置 具有 setTokenStartIndex 的根节点 但这只是一遍又一遍地循环第一个节点。

我的问题是,如何在 antlr 中实现 goto 语句? 也许我的方法是错误的,因为我忽略了一些东西?

非常感谢任何帮助。

ps。更详细地说,它与模式 25 - 语言实现模式有关,我正在尝试添加该模式的示例。 另外,我在网上搜索了很多,看起来很难找到 goto 示例

【问题讨论】:

  • 这是家庭作业,还是其他类型的作业?如果不是,您要解决的更大问题是什么?
  • 练习,我正在通过 Parr 先生的语言实现模式中的模式 25。我虽然添加了该模式以练习实现 goto 语句,但我被卡住了。我试过这个: i=LABEL print {interpreter.store($i.text, $print.tree);} //stores in hash table -> print 但是 $print.tree 只需要一个节点而不是它之后的任何其他节点.我还尝试使用 getTokenStartIndex() 获取 print 语句的令牌地址并使用 setTokenStartIndex 设置根节点,但这只是一遍又一遍地循环第一个节点。
  • 假设我有这个树结构: (BLOCK (PRINT 1) (PRINT 2) (PRINT 3) (PRINT 4) ) 现在,我很想知道有没有办法选择,比如说, 节点 (PRINT 2) 以及该节点之后的所有节点,即 ((PRINT 2) (PRINT 3) (PRINT 4)) ?所以,基本上我被困住了,所以我欢迎任何建议!
  • Te33Xaz,我建议您在原始帖子中添加所有这些信息。你在正确的轨道上!我会看看我是否可以发布一个我认为可以做到的小演示。

标签: parsing antlr goto abstract-syntax-tree


【解决方案1】:

...任何可以帮助我在 ANTLR 中实现基本 goto 语句的东西?

请注意,实现这一点的不是 ANTLR。使用 ANTLR,您只需描述要解析的语言即可获得词法分析器、解析器和可能的 tree-walker。之后,由您来操作和评估树。

这是一种可能的方法。请不要太仔细地看代码。这是一个快速破解:有一些代码重复,我正在传递包保护的变量,这不是应该做的。语法还要求您以 label 开头输入源,但这只是您如何解决它的一个小演示。

您需要以下文件:

  • Goto.g - 组合语法文件
  • GotoWalker.g - Tree walker 语法文件
  • Main.java - 主类,包括该语言的节点模型类
  • test.goto - 测试输入源文件
  • antlr-3.3.jar - ANTLR JAR(也可能是另一个 3.x 版本)

转到.g

grammar Goto;

options {
  output=AST;
  ASTLabelType=CommonTree;
}

tokens {
  FILE;
  BLOCK;
}

@members {
  java.util.Map<String, CommonTree[]> labels = new java.util.HashMap<String, CommonTree[]>();
}

parse
  :  block EOF -> block
  ;

block
  :  ID ':' stats b=block? {labels.put($ID.text, new CommonTree[]{$stats.tree, $b.tree});} -> ^(BLOCK stats $b?)
  ;

stats
  :  stat*
  ;

stat
  :  Print Number -> ^(Print Number)
  |  Goto ID      -> ^(Goto ID)
  ;

Goto   : 'goto';
Print  : 'print';
Number : '0'..'9'+; 
ID     : ('a'..'z' | 'A'..'Z')+;
Space  : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;};

GotoWalker.g

tree grammar GotoWalker;

options {
  tokenVocab=Goto;
  ASTLabelType=CommonTree;
}

tokens {
  FILE;
  BLOCK;
}

@members {
  java.util.Map<String, CommonTree[]> labels = new java.util.HashMap<String, CommonTree[]>();
}

walk returns [Node n]
  :  block {$n = $block.n;}
  ;

block returns [Node n]
  :  ^(BLOCK stats b=block?) {$n = new BlockNode($stats.n, $b.n);}
  ;

stats returns [Node n]
@init{List<Node> nodes = new ArrayList<Node>();}
  :  (stat {nodes.add($stat.n);})* {$n = new StatsNode(nodes);}
  ;

stat returns [Node n]
  :  ^(Print Number) {$n = new PrintNode($Number.text);}
  |  ^(Goto ID)      {$n = new GotoNode($ID.text, labels);}
  ;

Main.java

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
import java.util.*;

public class Main {
  public static void main(String[] args) throws Exception {
    GotoLexer lexer = new GotoLexer(new ANTLRFileStream("test.goto"));
    GotoParser parser = new GotoParser(new CommonTokenStream(lexer));
    CommonTree tree = (CommonTree)parser.parse().getTree();
    GotoWalker walker = new GotoWalker(new CommonTreeNodeStream(tree));
    walker.labels = parser.labels;
    Node root = walker.walk();
    root.eval();
  }
}

interface Node {
  public static final Node VOID = new Node(){public Object eval(){throw new RuntimeException("VOID.eval()");}};
  public static final Node BREAK = new Node(){public Object eval(){throw new RuntimeException("VOID.eval()");}};
  Object eval();
}

class BlockNode implements Node {

  Node stats;
  Node child;

  BlockNode(Node ns, Node ch) {
    stats = ns;
    child = ch;
  }

  public Object eval() {
    Object o = stats.eval();
    if(o != VOID) {
      return o;
    }
    if(child != null) {
      o = child.eval();
      if(o != VOID) {
        return o;
      }
    }
    return VOID;
  }
}

class StatsNode implements Node {

  List<Node> nodes;

  StatsNode(List<Node> ns) {
    nodes = ns;
  }

  public Object eval() {
    for(Node n : nodes) {
      Object o = n.eval();
      if(o != VOID) {
        return o;
      }
    }
    return VOID;
  }
}

class PrintNode implements Node {

  String text;

  PrintNode(String txt) {
    text = txt;
  }

  public Object eval() {
    System.out.println(text);
    return VOID;
  }
}

class GotoNode implements Node {

  String label;
  Map<String, CommonTree[]> labels;

  GotoNode(String lbl, Map<String, CommonTree[]> lbls) {
    label = lbl;
    labels = lbls;
  }

  public Object eval() {
    CommonTree[] toExecute = labels.get(label);
    try {
      Thread.sleep(1000L);
      GotoWalker walker = new GotoWalker(new CommonTreeNodeStream(toExecute[0]));
      walker.labels = this.labels;
      Node root = walker.stats();
      Object o = root.eval();
      if(o != VOID) {
        return o;
      }
      walker = new GotoWalker(new CommonTreeNodeStream(toExecute[1]));
      walker.labels = this.labels;
      root = walker.block();
      o = root.eval();
      if(o != VOID) {
        return o;
      }
    } catch(Exception e) {
      e.printStackTrace();
    }
    return BREAK;
  }
}

test.goto

root:
print 1
A:
print 2
B:
print 3
goto A
C:
print 4

要运行演示,请执行以下操作:

*nix/MacOS

java -cp antlr-3.3.jar org.antlr.Tool Goto.g
java -cp antlr-3.3.jar org.antlr.Tool GotoWalker.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main

或:

窗口

java -cp antlr-3.3.jar org.antlr.Tool Goto.g
java -cp antlr-3.3.jar org.antlr.Tool GotoWalker.g
javac -cp antlr-3.3.jar *.java
java -cp .;antlr-3.3.jar Main

将打印:

1
2
3
2
3
2
3
2
3
...

请注意,在您手动终止应用程序之前,会重复 2 和 3。

【讨论】:

  • 感谢回答,我得再仔细研究一下,但它很有用。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多