Parsing
Parsing is the act of checking whether a stream of lexemes match a grammar. Since a simple "yes/no" answer is rarely useful, it is common to execute user-defined actions during parsing.
grmtools
contains libraries (cfgrammar
and
lrtable
) which allow users to build their own LR parsers in
whatever fashion they want. However, for 99% of cases, the lrpar
library is what users want and need: a (largely) Yacc-compatible parser. Roughly
speaking, the core parts of grammars work identically in Yacc and lrpar
, but
some other parts of the system have been modernised (e.g. to avoid the use of
global variables) and given a more idiomatic Rust feel. Notably, lrpar
is
built from the ground-up to have a powerful, flexible approach to error
recovery.
Yacc variants
grmtools can deal with several different variants of Yacc input.
Grmtools
YaccKind::Grmtools
is grmtools own variant of Yacc syntax. The sole difference
is that rules have a Rust type to which all their production's actions must adhere
to. Consider the following snippet:
R -> Result<i32, ()>:
'a' { Ok(5) }
| 'b' { Err(()) }
Here the rule R
has a Rust return type of Result<X, ()>
(between ->
and
:
). Both of its productions adhere to this type, the first by instantiating
Ok(5)
and the second Err(())
.
“Original” Yacc
Although the name is not fully accurate (grmtools supports a slightly disjoint subset of original Yacc's input), this mode allows users to most easily test externally created Yacc files. Several sub-variants are allowed:
-
YaccKind::Original(YaccOriginalActionKind::GenericParseTree)
does not execute user actions, but instead creates a generic parse tree, where elements are instances of thelrpar::parser::Node
enum. This is useful for quickly testing whether a parser is accepting the intended language. -
YaccKind::Original(YaccOriginalActionKind::NoActions)
parses input and reports errors but does not execute any user actions. This is useful if you are trying to test a large corpus of input for correctness. -
YaccKind::Original(YaccOriginalActionKind::UserAction)
models original Yacc most closely but, in a Rust setting, is probably of little use beyond simple calculator like languages. Instead of Yacc's%union
directive, users can specify%actiontype
which is a Rust type which all production actions must return an instance of. Unless all actions happen to naturally return the same type, this quickly becomes cumbersome to use. For most use cases,YaccKind::Grmtools
is a superior alternative.