How can I execute an ANTLR parser action for each item in a rule that can match more than one item?
- by Chris Farmer
I am trying to write an ANTLR parser rule that matches a list of things, and I want to write a parser action that can deal with each item in the list independently.
Some example input for these rules is:
$(A1 A2 A3)
I'd like this to result in an evaluator that contains a list of three MyIdentEvaluator objects -- one for each of A1, A2, and A3.
Here's a snippet of my grammar:
my_list returns [IEvaluator e]
: { $e = new MyListEvaluator(); }
'$'
LPAREN
op=my_ident+ {
/* want to do something here for each 'my_ident'. */
/* the following seems to see only the 'A3' my_ident */
$e.Add($op.e);
}
RPAREN
;
my_ident returns [IEvaluator e]
: IDENT { $e = new MyIdentEvaluator($IDENT.text); }
;
I think my_ident is defined correctly, because I can see the three MyIdentEvaluators getting created as expected for my input string, but only the last my_ident ever gets added to the list (A3 in my example input).
How can I best treat each of these elements independently, either through a grammar change or a parser action change?
It also occurred to me that my vocabulary for these concepts is not what it should be, so if it looks like I'm misusing a term, I probably am.
EDIT in response to Wayne's comment:
I tried to use op+=my_ident+. In that case, the $op in my action becomes an IList (in C#) that contains Antlr.Runtime.Tree.CommonTree instances. It does give me one entry per matched token in $op, so I see my three matches, but I don't have the MyIdentEvaluator instances that I really want. I was hoping I could then find a rule attribute in the ANTLR docs that might help with this, but nothing seemed to help me get rid of this IList.
Result...
Based on chollida's answer, I ended up with this which works well:
my_list returns [IEvaluator e]
: { $e = new MyListEvaluator(); }
'$'
LPAREN
(op=my_ident { $e.Add($op.e); } )+
RPAREN
;
The Add method gets called for each match of my_ident.