... 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 FileGotoWalker.g - walker tree grammar fileMain.java - the main class that includes the Node classes - language Main.javatest.goto - source test input source fileantlr-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.