antlr 中的 goto 语句? [英] goto statement in antlr?

查看:30
本文介绍了antlr 中的 goto 语句?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would really appreciate if someone could give me advice,or point me to tutorial, or sample implementation, anything that could help me implement basic goto statement in ANTLR?

感谢您的帮助

编辑.问题的ver2:

edit. ver2 of question:

假设我有这个树结构:

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

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

Now, I'm interested to know is there a way to select, say, node (PRINT 2) and all nodes that follow that node ((PRINT 2) (PRINT 3) (PRINT 4)) ?

我问这个是因为我正在尝试实施基本的跳转机制.我有这样的打印语句:

I'm asking this because I'm trying to implement basic goto mechanism. I have print statement like this:

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

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

However $print.tree just ignores later nodes, so in input:

label: print 1
print 2
goto label

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

would print 121! (What I would like is infinite loop 1212...)

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

I've also tried taking token address of print statement with getTokenStartIndex() and setting roots node with setTokenStartIndex but that just looped whatever was first node over and over.

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

My question is, how does one implement goto statement in antlr ? Maybe my approach is wrong, as I have overlooked something?

我非常感谢您的帮助.

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

ps. even more detail, it is related to pattern 25 - Language Implementation patterns, I'm trying to add on to examples from that pattern. Also, I've searched quite a bit on the web, looks like it is very hard to find goto example

推荐答案

...有什么可以帮助我在 ANTLR 中实现基本的 goto 语句的吗?

... anything that could help me implement basic goto statement in ANTLR?

请注意,实现这一点的不是 ANTLR.使用 ANTLR,您只需描述您想要解析的语言以获得词法分析器、解析器和可能的树遍历器.之后,由您来操作树并对其进行评估.

Note that it isn't ANTLR that implements this. With ANTLR you merely describe the language you want to parse to get a lexer, parser and possibly a tree-walker. After that, it's up to you to manipulate the tree and evaluate it.

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

Here's a possible way. Please don't look too closely at the code. It's a quick hack: there's a bit of code-duplication and I'm am passing package protected variables around which isn't as it should be done. The grammar also dictates you to start your input source with a label, but this is just a small demo of how you could solve it.

您需要以下文件:

  • Goto.g - 组合语法文件
  • GotoWalker.g - tree walker 语法文件
  • Main.java - 包含语言节点模型类的主类
  • test.goto - 测试输入源文件
  • antlr-3.3.jar - ANTLR JAR(也可能是另一个 3.x 版本)
  • Goto.g - the combined grammar file
  • GotoWalker.g - the tree walker grammar file
  • Main.java - the main class including the Node-model classes of the language
  • test.goto - the test input source file
  • antlr-3.3.jar - the ANTLR JAR (could also be another 3.x version)
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

<小时>

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


To run the demo, do the following:

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 直到您手动终止应用.

Note that the 2 and 3 are repeated until you terminate the app manually.

这篇关于antlr 中的 goto 语句?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆