Anssssss wrote:
As soon as I try to change the way the tree is created using the ^ symbol, I get an exception from the form:
When trying to make the parser rule a root of the tree inside p as follows:
p : a^ b; a : AA; b : BB;
ANTLR does not know which of a is the root of rule a . Of course, there cannot be two roots.
Inline-tree operators are convenient in some cases, but in this case they do not correspond to the task. You cannot assign a root within a production rule that may not have content, such as your remaining_data rule. In this case, you need to create "imaginary tokens" in the tokens { ... } section tokens { ... } your grammar and use the rewrite rule ( -> ^( ... ) ) to create your AST.
Demo
The following grammar:
grammar FlexByteArray_HexGrammar; options { output=AST; } tokens { ROOT; ARRAY; LENGTH; DATA; } expr : array* EOF -> ^(ROOT array*) ; array @init { int index = 0; } : array_length array_data[$array_length.value] -> ^(ARRAY array_length array_data) ; array_length returns [int value] : a=hex_byte b=hex_byte {$value = $a.value*16*16 + $b.value;} -> ^(LENGTH hex_byte hex_byte) ; array_data [int length] : ({length > 0}?=> hex_byte {length--;})* {length == 0}? -> ^(DATA hex_byte*) ; hex_byte returns [int value] : a=HEX_DIGIT b=HEX_DIGIT {$value = Integer.parseInt($a.text+$b.text, 16);} ; HEX_DIGIT : '0'..'9' | 'a'..'f' | 'A'..'F' ;
will analyze the following input:
0001ff0002abcd
to the following AST:

as you can see using the following main class:
import org.antlr.runtime.*; import org.antlr.runtime.tree.*; import org.antlr.stringtemplate.*; public class Main { public static void main(String[] args) throws Exception { FlexByteArray_HexGrammarLexer lexer = new FlexByteArray_HexGrammarLexer(new ANTLRStringStream("0001ff0002abcd")); FlexByteArray_HexGrammarParser parser = new FlexByteArray_HexGrammarParser(new CommonTokenStream(lexer)); CommonTree tree = (CommonTree)parser.expr().getTree(); DOTTreeGenerator gen = new DOTTreeGenerator(); StringTemplate st = gen.toDOT(tree); System.out.println(st); } }
More details
EDIT
To give a brief description of the array_data rule:
array_data [int length] : ({length > 0}?=> hex_byte {length--;})* {length == 0}? -> ^(DATA hex_byte*) ;
As you mentioned in the comments, you can pass one or more parameters to the rules by adding [TYPE IDENTIFIER] after the rule.
The first (gated) semantic predicate, {length > 0}?=> , Checks to see if length greater than. If so, the parser tries to match a hex_byte , after which the length variable is reduced by one. All this stops when length is zero or when the parser no longer has the hex_byte that occurs when the EOF is in the queue. Since it can parse less than the required number of hex_byte s, is there a (verifying) semantic predicate {length == 0}? at the very end of the rule {length == 0}? , which ensures that the correct amount of hex_byte been parsed (no more, no less!).
Hope this clarifies a bit.