Action code and return types
Action code
Action code is normal Rust code with the addition of the following special variables:
-
$1
...$n
refer to the respective symbol in the production, numbered from 1 (i.e.$1
refers to the first symbol in the production). If the symbol references a ruleR
then an instance ofR
's type will be stored in the$i
variable. If the symbol references a lexeme then aResult<Lexeme<StorageT>, Lexeme<StorageT>>
instance is returned where theOk
variant is used for lexemes that are directly derived from the user's input and theErr
variant is used for lexemes that have been inserted by error recovery. -
$lexer
allows access to the lexer and its various functions. The most commonly used of these is thespan_str
function, which allows us to extract&'input str
s from aSpan
(e.g. to extract the string represented by aLexeme
, we would use$lexer.span_str(lexeme.span())
). As this may suggest, actions may also reference the special lifetime'input
(without any$
prefix), which allows strings to be returned / stored by the grammar without copying memory. -
$span
is acfgrammar::Span
which captures how much of the user's input the current production matched. -
$$
is equivalent to$
in normal Rust code.
Any other variables beginning with $
are treated as errors.
Return types
Productions' return types can be any arbitrary Rust type. You may in addition make use of the following:
-
The generic parameter
StorageT
references the type of lexemes and is typically used with theLexeme
type i.e.Lexeme<StorageT>
. This allows you to return lexemes from rules. -
The lifetime
'input
allows you to extract strings whose lifetime is tied to the lexer and return them from rules / store them in structs without copying.Lexer::span_str
returns such strings and the typical idiom of use is&'input str
.
Additional parse parameter
A single extra parameter can be passed to action functions if the %parse-param <var>: <type>
declaration is used. The variable <var>
is then visible in all
action code. <type>
must implement the Clone
trait (note that Copy
bounds imply Clone
, and &
references implement Copy
).
For example if a grammar has a declaration:
%parse-param p: u64
then the statically generated parse
function will take two paramaters
(lexer: &..., p: u64)
and the variable p
can be used in action code e.g.:
R -> ...:
'ID' { format!("{}{}", p, ...) }
;