java - Rule variables in ANTLR4 -
i'm trying convert grammar v3 v4 , having trouble.
in v3 have rules this:
dataspec[datalayout layout] returns [dataextractor extractor] @init { dataextractorbuilder builder = new dataextractorbuilder(layout); } @after { extractor = builder.create(); } : first=expr { builder.addall(first); } (comma next=expr { builder.addall(next); })* ; expr returns [list<valueextractor> ext] ...
however, rules in v4 returning these custom context objects instead of explicitly told them return, things messed up. what's v4 way this?
there multiple cases here:
- accessing passed-in variables (
layout
) - accessing current rule's return value (
extractor
) - accessing local variables (
first
,next
)
passed-in variables , current rule's return value
when accessing passed-in variables or return value of current rule need prefix name given in rule definition $
.
layout
becomes$layout
extractor
becomes$extractor
local variables
evidently needs done reference variables' member named according returns
clause of rule returned value.
for example, first
capturing result expr
rule, , expr
names return value ext
, meaning that:
first
becomes$first.ext
next
becomes$next.ext
when use $
form
unlike in v3 reference variables regular java fields, using $
form necessary in all cases, including in actions, in @init
, @after
blocks, , when passing variables other rules.
other traps
if you're capturing optional tokens in local variable, may run null pointer exceptions you're referencing attribute of variable.
single_lname returns [string s] : p=lname_prefix? r=name { $p.text + tonamecase($r.text); } ;
you'll need check whether $p
null, of time result in "missing attribute access" error. antlr4 makes special exception can check this, only applies when used in if
condition (refactoring use ternary operator, example, still result in error).
single_lname returns [string s] : p=lname_prefix? r=name { if ($p == null) { $s = tonamecase($r.text); } else { $s = $p.text + tonamecase($r.text); } } ;
the updated rule
putting together, dataspec
rule becomes:
dataspec[datalayout layout] returns [dataextractor extractor] @init { dataextractorbuilder builder = new dataextractorbuilder($layout); } @after { $extractor = builder.create(); } : first=expr { builder.addall($first.ext); } (comma next=expr { builder.addall($next.ext); })* ;
Comments
Post a Comment