use back::compiler::*;
use back::compiler::value::*;
use back::name_factory::*;
pub struct NonTerminalCompiler;
impl NonTerminalCompiler
{
pub fn recognizer(id: Ident) -> NonTerminalRecognizerCompiler {
NonTerminalRecognizerCompiler {
path: parse_quote!(#id)
}
}
pub fn parser(id: Ident, this_idx: usize) -> NonTerminalParserCompiler {
NonTerminalParserCompiler {
path: parse_quote!(#id),
this_idx
}
}
pub fn external_recognizer(path: syn::Path) -> NonTerminalRecognizerCompiler {
NonTerminalRecognizerCompiler { path }
}
pub fn external_parser(path: syn::Path, this_idx: usize) -> NonTerminalParserCompiler {
NonTerminalParserCompiler { path, this_idx}
}
}
pub struct NonTerminalRecognizerCompiler
{
path: syn::Path
}
impl CompileExpr for NonTerminalRecognizerCompiler
{
fn compile_expr<'a>(&self, _context: &mut Context<'a>,
continuation: Continuation) -> syn::Expr
{
let recognizer_fn = recognizer_name(self.path.clone());
continuation
.map_success(|success, failure| parse_quote!(
{
state = #recognizer_fn(state);
if state.is_successful() {
state.discard_data();
#success
}
else {
#failure
}
}
))
.unwrap_success()
}
}
pub struct NonTerminalParserCompiler
{
path: syn::Path,
this_idx: usize
}
impl CompileExpr for NonTerminalParserCompiler
{
fn compile_expr<'a>(&self, context: &mut Context<'a>,
continuation: Continuation) -> syn::Expr
{
let parser_fn = parser_name(self.path.clone());
let cardinality = context.expr_cardinality(self.this_idx);
let mut vars_names: Vec<_> = (0..cardinality)
.map(|_| context.next_free_var())
.collect();
vars_names.reverse();
let vars = tuple_pattern(vars_names);
continuation
.map_success(|success, failure| parse_quote!(
{
let stateful = #parser_fn(state);
if stateful.is_successful() {
let (stateless, #vars) = stateful.extract_data();
state = stateless;
#success
}
else {
state = stateful.failure();
#failure
}
}
))
.unwrap_success()
}
}