在antlr中转到声明?

时间:2011-07-21 17:31:33

标签: parsing antlr goto abstract-syntax-tree

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

感谢您的帮助

修改。问题的问题2:

说我有这种树结构:

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

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

我问这个是因为我正在努力实施 基本的转到机制。 我有这样的印刷声明:

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示例

1 个答案:

答案 0 :(得分:3)

  

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

请注意,实现此功能的不是ANTLR。使用ANTLR,您只需描述要解析的语言,以获取词法分析器,解析器以及可能的树木助行器。在那之后,你可以操纵树并进行评估。

这是一种可行的方法。请不要仔细查看代码。这是一个快速的黑客攻击:有一些代码重复,我正在传递包受保护的变量,而不是应该做的。该语法还要求您使用label开始输入源,但这只是 可以解决它的一个小演示。

您需要以下文件:

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

Goto.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,直到您手动终止应用程序。