Goto expression in antlr?

I would really appreciate it if someone could give me advice or point me to a tutorial or sample implementation that could help me execute the goto basic statement in ANTLR?

Thanks for any help

to change. ver2 of the question:

Let's say I have this tree structure:

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

Now I am interested to know if there is a way to choose, say, node (PRINT 2) and all subsequent nodes that node ((PRINT 2) (PRINT 3) (PRINT 4))?

I ask about this because I'm trying to implement the basic goto mechanism. I have a print expression as follows:

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

However, $ print.tree simply ignores subsequent nodes, so the input:

 label: print 1 print 2 goto label 

will print 121! (I wish it was an endless 1212 loop ...)

I also tried using the token address of the print statement with getTokenStartIndex () and setting the root of the node using setTokenStartIndex but it just looped on what was the first node again and again.

My question is: how to implement goto statement in antlr? Maybe my approach is wrong, because I missed something?

I would really appreciate any help.

ps. in more detail, this is related to pattern 25 - Language implementations, I'm trying to add examples from this pattern. Also, I searched quite a lot on the Internet, it seems very difficult to find an example for an example

+1
source share
2 answers

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

Note that this is not the ANTLR that implements this. In ANTLR, you simply describe the language you want to parse to get a lexer, parser, and possibly tree-like. After that, you decide to manipulate the tree and evaluate it.

Here is a possible way. Please do not look too closely at the code. This is a quick hack: there is a bit of code duplication, and I skip the package-protected variables, around which is not how it should be done. The grammar also indicates that you start your source with label , but this is just a small demonstration of how you could solve it.

You need the following files:

  • Goto.g - Combined Grammar File
  • GotoWalker.g - walker tree grammar file
  • Main.java - the main class that includes the Node classes - language Main.java
  • test.goto - source test input source file
  • antlr-3.3.jar - ANTLR JAR (may also be a different version 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, $bn);} ; 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 start the demo, follow these steps:

* 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

Window

 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 ... 

Please note that 2 and 3 are repeated until you terminate the application manually.

+3
source

Hi, the above code does not work in antlr4. Any thought in that

0
source

Source: https://habr.com/ru/post/904521/


All Articles