OK, found the solution by turning off standard tree construction. > basicRE : simpleRE ((CONCAT^) simpleRE)*; Now, instead of expecting a CONCAT operator, a CONC node is inserted into the AST: basicRE : a:simpleRE (! b:simpleRE {#basicRE = #([CONC,"conc"], #a, #b); } )* ;