parol
parol
is a LL(k) parser generator for Rust written in Rust with the following features
This project contains some introductory grammar examples from entry level up to a more complex C-like expression language and an acceptor for Oberon-0 grammar.
Two of the examples describe the principles of language processing by using semantic actions in the way parol
advocates it.
Last but not least parol
's parser for its own input language is generated by parol
itself. So this application of language processing is an additional and very practical example.
It's worth mentioning that there exists another opportunity to process the parse result.
The parse tree the parser generates can be processed by user created tools too. So no one is tied to parol
's approach to semantic actions although this approach is easy and compelling.
parol
worksparol
first transforms the input grammar into an expanded form where optional expressions, groups and repetitions are substituted by equivalent production sets. Then it analyzes this pre-transformed input grammar for several properties that prevent a successful processing. Those properties are
If there are no objections against the input grammar the next step is to left-factor the grammar that was produced by the previous expansion. This step is crucial for decreasing the number of necessary lookahead symbols.
This finally transformed grammar is the basis for the parser generation and can or better should be written to file for later reference. By convention this expanded grammar is stored to files names \ The actual parser generation then starts witch generating the lookahead automata for the non-terminals. In this phase it determines if the grammar is LL(k) for k starting with 1 and increasing it by one until a solution is found or the maximum lookahead size is exceeded. If your grammar is more than LL(5) the needed amount of processing power and memory consumption makes it inefficient to work with. In such a case you should rework your grammar design thoroughly. Or you can use a super fast machine to generate your parser's sources and compile and run the generated parser on an ordinary one. Internally the maximum lookahead size is currently limited to 10 though. To determine if your grammar is LL(k) If a solution is found The first one contains all scanner and parser data. The second one provides two traits. The first of these traits is important for the user's grammar processing. It contains for each production an empty default implementations of the corresponding semantic action. The semantic actions of the user can be provided by implementing this trait and providing own implementations for any production needed. The trait's name can be defined per command line argument. The second trait in this file provides bindings of semantic actions so that the parser can call them via production number during parse time. It's name is always Parsers generated by parol
generates equation systems for both FIRST(k) and FOLLOW(k) sets and tries to solve them iteratively until a fix point is reached which indicates the solution. This is the most expensive task for parol
.parol
generates all necessary data to feed the scanner and parser with. Based on this data parol
then generates two source files.UserActionsTrait
.Dependencies
parol
have to add a dependency to the parolruntime crate which provides the scanner and parser implementations needed. The parolruntime crate is very lightweight.Further readings