use back::compiler::*;
use back::compiler::value::*;
pub struct RuleCompiler<'a>
{
grammar: &'a TGrammar,
rule: Rule
}
impl<'a> RuleCompiler<'a>
{
pub fn compile(grammar: &'a TGrammar, rule: Rule) -> Vec<syn::Item> {
let compiler = RuleCompiler::new(grammar, rule);
vec![
compiler.compile_recognizer(),
compiler.compile_parser()
]
}
fn new(grammar: &'a TGrammar, rule: Rule) -> Self {
RuleCompiler {
grammar: grammar,
rule: rule
}
}
fn compile_recognizer(&self) -> syn::Item {
let mut context = Context::new(self.grammar);
let success = parse_quote!(state.success(()));
let failure = parse_quote!(state.failure());
let body = context.compile(recognizer_compiler,
self.expr(), success, failure);
context.into_recognizer_function(body, self.rule.clone())
}
fn compile_parser(&self) -> syn::Item {
let mut context = Context::new(self.grammar);
if self.parser_equals_recognizer() {
context.into_parser_alias(self.rule.clone())
}
else {
let scope = context.open_scope(self.expr());
let vars = tuple_value(context.free_variables());
let success = parse_quote!(state.success(#vars));
let failure = parse_quote!(state.failure());
let body = context.compile(parser_compiler,
self.expr(), success, failure);
context.close_scope(scope);
context.into_parser_function(body, self.rule.clone())
}
}
fn parser_equals_recognizer(&self) -> bool {
self.grammar[self.expr()].ty == Type::Unit
}
fn expr(&self) -> usize {
self.rule.expr_idx
}
}