A Practical Example
We’re going to make a parser for a configuration file. That file contains the options to generate a parser with Lexigram.
There are currently two ways of setting the options when you generate a parser with Lexigram: the command-line options arguments and the option’s fluent methods used when generating the parser programmatically.
Here is an example of options to generate the little example discussed in the tutorial overview:
lexigram --indent 4 -c example.lg -l parser.rs tag example_lexer\
-p parser.rs tag example_parser\
--lib "super::user_types::*"
And here is the equivalent if the parser is generated programmatically:
#![allow(unused)]
fn main() {
static GRAMMAR_FILENAME: &str = "example.lg";
static PARSER_FILENAME: &str = "parser.rs";
let options = OptionsBuilder::new()
.indent(4)
.combined_spec(genspec!(filename: GRAMMAR_FILENAME))
.lexer_code(gencode!(filename: PARSER_FILENAME, tag: "example_lexer"))
// grammar is combined with lexicon, no need to define parser_spec
.parser_code(gencode!(filename: PARSER_FILENAME, tag: "example_parser"))
.libs(["super::user_types::*"])
.build()
.expect("should have no error");
match try_gen_parser(action, options) {
Ok(log) => {
if action == Action::Generate {
println!("Code generated");
}
assert!(
log.has_no_warnings(),
"unexpected warning(s):\n{}",
log.get_warnings().join("\n"));
}
Err(build_error) => panic!("{build_error}"),
}
}
What we would like is a text-based input that specifies the same options, and which could be stored in a configuration file, or maybe combined with the lexicon and the grammar:
def GRAMMAR_FILENAME = "example.lg";
def PARSER_FILENAME = "parser.rs";
lexer {
combined: GRAMMAR_FILENAME,
output: PARSER_FILENAME ["example_lexer"]
}
parser {
output: PARSER_FILENAME ["example_parser"]
}
options {
libs: { "super::user_types::*" },
indent: 4
}