use grammar::repr::{Grammar, NonterminalString, TypeParameter};
use lr1::core::*;
use rust::RustWrite;
use std::io::{self, Write};
use util::Sep;
use super::base::CodeGenerator;
pub fn compile<'grammar, W: Write>(grammar: &'grammar Grammar,
user_start_symbol: NonterminalString,
start_symbol: NonterminalString,
states: &[LR1State<'grammar>],
out: &mut RustWrite<W>)
-> io::Result<()> {
let mut ascent = CodeGenerator::new_test_all(grammar,
user_start_symbol,
start_symbol,
states,
out);
ascent.write()
}
struct TestAll;
impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TestAll> {
fn new_test_all(grammar: &'grammar Grammar,
user_start_symbol: NonterminalString,
start_symbol: NonterminalString,
states: &'ascent [LR1State<'grammar>],
out: &'ascent mut RustWrite<W>)
-> Self {
CodeGenerator::new(grammar,
user_start_symbol,
start_symbol,
states,
out,
true,
"super",
TestAll)
}
fn write(&mut self) -> io::Result<()> {
self.write_parse_mod(|this| {
try!(this.write_parser_fn());
rust!(this.out, "mod {}ascent {{", this.prefix);
try!(super::ascent::compile(this.grammar,
this.user_start_symbol,
this.start_symbol,
this.states,
"super::super::super",
this.out));
rust!(this.out,
"pub use self::{}parse{}::parse_{};",
this.prefix,
this.start_symbol,
this.user_start_symbol);
rust!(this.out, "}}");
rust!(this.out, "mod {}parse_table {{", this.prefix);
try!(super::parse_table::compile(this.grammar,
this.user_start_symbol,
this.start_symbol,
this.states,
"super::super::super",
this.out));
rust!(this.out,
"pub use self::{}parse{}::parse_{};",
this.prefix,
this.start_symbol,
this.user_start_symbol);
rust!(this.out, "}}");
Ok(())
})
}
fn write_parser_fn(&mut self) -> io::Result<()> {
try!(self.start_parser_fn());
try!(self.call_delegate("ascent"));
try!(self.call_delegate("parse_table"));
rust!(self.out,
"assert_eq!({}ascent, {}parse_table);",
self.prefix,
self.prefix);
rust!(self.out, "return {}ascent;", self.prefix);
try!(self.end_parser_fn());
Ok(())
}
fn call_delegate(&mut self, delegate: &str) -> io::Result<()> {
let non_lifetimes: Vec<_> =
self.grammar.type_parameters
.iter()
.filter(|&tp| match *tp {
TypeParameter::Lifetime(_) => false,
TypeParameter::Id(_) => true,
})
.cloned()
.collect();
let parameters = if non_lifetimes.is_empty() {
String::new()
} else {
format!("::<{}>", Sep(", ", &non_lifetimes))
};
rust!(self.out,
"let {}{} = {}{}::parse_{}{}(",
self.prefix,
delegate,
self.prefix,
delegate,
self.user_start_symbol,
parameters);
for parameter in &self.grammar.parameters {
rust!(self.out, "{},", parameter.name);
}
if self.grammar.intern_token.is_none() {
rust!(self.out, "{}tokens0.clone(),", self.prefix);
}
rust!(self.out, ");");
Ok(())
}
}