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

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

问题描述

如果有人可以给我建议,或为我提供教程或示例实现,可以帮助我在ANTLR中实现基本的goto语句,我将不胜感激?



谢谢您的帮助



编辑。问题的Ver2:



说我有这个树结构:

  (块(打印1)(打印2)(打印3)(打印4))

现在,我想知道是否有一种方法可以选择
,例如,节点(PRINT 2)以及跟随
该节点的所有节点((PRINT 2)(PRINT 3)(PRINT 4))吗?



我问这个问题是因为我试图实现
基本的goto机制。
我有这样的打印语句:

  i =标签打印
{interpreter.store($ i .text,$ print.tree);} //存储在哈希表
->中打印

但是$ print.tree只会忽略后面的节点,因此
在输入中:

 标签:打印1 
打印2
转到标签

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



我也尝试使用$ b来获取令牌
打印语句的地址$ b getTokenStartIndex()并使用setTokenStartIndex
设置
根节点,但是这只是循环遍历第一个节点。



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



我将非常感谢您的帮助。



ps。更详细地讲,它与模式25-语言实施模式有关,我尝试在该模式的示例中添加其他内容。
另外,我已经在网上搜索了很多东西,看起来很难找到goto示例

解决方案

< blockquote>

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


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



这里是一种可能的方法。请不要仔细查看代码。这是一个快速的技巧:有一些代码重复功能,而我正在传递受程序包保护的变量,但该变量不应该这样做。语法还指示您以标签开头的输入源,但这只是您如何解决问题的一个小示例。



您需要以下文件:




  • Goto.g -组合语法文件

  • GotoWalker.g -树行者语法文件

  • Main.java -主类,包括该语言的节点模型类

  • test.goto -测试输入源文件

  • antlr-3.3.jar -ANTLR JAR(也可能是其他3.x版本)






Goto.g



 语法转到; 

选项{
output = AST;
ASTLabelType = CommonTree;
}

令牌{
文件;
块;
}

@members {
java.util.Map< String,CommonTree []>标签=新的java.util.HashMap< String,CommonTree []>();
}

解析
:阻止EOF->封锁
;

阻止
:ID’:’统计信息b =阻止? {labels.put($ ID.text,new CommonTree [] {$ stats.tree,$ b.tree});}-> ^(块统计$ b?)
;

统计信息
:统计*


stat
:打印号码-> ^(打印号码)
|转到ID-> ^(转到ID)
;

转到:转到;
打印:打印;
数字: 0 .. 9 +;
ID:(‘a’..’z’|‘A’。’’Z’)+;
空格:(’’|’\t |’\r’’\n’){$ channel = HIDDEN;};






GotoWalker.g



 树语法GotoWalker; 

选项{
tokenVocab = Goto;
ASTLabelType = CommonTree;
}

令牌{
文件;
块;
}

@members {
java.util.Map< String,CommonTree []>标签=新的java.util.HashMap< String,CommonTree []>();
}

步行返回[节点n]
:块{$ n = $ block.n;}


块返回[节点n]
:^(块统计b = block?){$ n =新的BlockNode($ stats.n,$ b.n);}
;

统计信息返回[Node n]
@init {List< Node> node = new ArrayList< Node>();}
:(stat {nodes.add($ stat.n);})* {$ n = new StatsNode(nodes ;;)
;

stat返回[节点n]
:^(打印编号){$ n =新的PrintNode($ Number.text);}
| ^(Goto ID){$ n =新的GotoNode($ ID.text,标签);}
;






Main.java



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

公共类Main {
public static void main(String [] args)引发异常{
GotoLexer lexer = new GotoLexer(new ANTLRFileStream( test.goto));
GotoParser解析器= new GotoParser(new CommonTokenStream(lexer));
CommonTree树=(CommonTree)parser.parse()。getTree();
GotoWalker walker = new GotoWalker(new CommonTreeNodeStream(tree));
walker.labels = parser.labels;
节点根= walker.walk();
root.eval();
}
}

接口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());}} ;;
对象eval();
}

类BlockNode实现Node {

Node stats;
节点子节点;

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;
}
}

类StatsNode实现节点{

List< Node>节点

StatsNode(List Node ns){
个节点= ns;
}

公共对象eval(){
for(节点n:节点){
对象o = n.eval();
if(o!= VOID){
return o;
}
}
return VOID;
}
}

类PrintNode实现Node {

字符串文本;

PrintNode(String txt){
text = txt;
}

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

类GotoNode实现Node {

字符串标签;
Map< String,CommonTree []>标签;

GotoNode(String lbl,Map< String,CommonTree []> lbls){
label = lbl;
标签= 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;
节点根= walker.stats();
对象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();
}
返回BREAK;
}
}






test.goto



  root:
打印1
A:
打印2
B:
打印3
转到A
C:
打印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

或:



Windows



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


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?

Thanks for any help

edit. ver2 of question:

Say I have this tree structure:

(BLOCK (PRINT 1) (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

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

label: print 1
print 2
goto label

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

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.

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

I would really appreciate any help.

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

解决方案

... anything that could help me implement basic goto statement in 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.

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.

You need the following files:

  • 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)

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


To run the demo, do the following:

*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

or:

Windows

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

which will print:

1
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天全站免登陆