use grammar::repr::Grammar;
use std::io::{self, Write};
macro_rules! rust {
($w:expr, $($args:tt)*) => {
try!(($w).writeln(&::std::fmt::format(format_args!($($args)*))))
}
}
pub struct RustWrite<W: Write> {
write: W,
indent: usize,
}
const TAB: usize = 4;
impl<W:Write> RustWrite<W> {
pub fn new(w: W) -> RustWrite<W> {
RustWrite { write: w, indent: 0 }
}
fn write_indented(&mut self, out: &str) -> io::Result<()> {
writeln!(self.write, "{0:1$}{2}", "", self.indent, out)
}
pub fn writeln(&mut self, out: &str) -> io::Result<()> {
let buf = out.as_bytes();
if buf.is_empty() {
return self.write.write_all("\n".as_bytes());
}
let n = buf.len() - 1;
if buf[0] == ('}' as u8) || buf[0] == (']' as u8) || buf[0] == (')' as u8) {
self.indent -= TAB;
}
try!(self.write_indented(out));
if buf[n] == ('{' as u8) || buf[n] == ('[' as u8) || buf[n] == ('(' as u8) {
self.indent += TAB;
}
Ok(())
}
pub fn write_pub_fn_header(&mut self,
grammar: &Grammar,
name: String,
type_parameters: Vec<String>,
parameters: Vec<String>,
return_type: String,
where_clauses: Vec<String>)
-> io::Result<()>
{
self.write_fn_header_helper(grammar, "pub ", name, type_parameters,
parameters, return_type, where_clauses)
}
fn write_fn_header_helper(&mut self,
grammar: &Grammar,
qualifiers: &str,
name: String,
type_parameters: Vec<String>,
parameters: Vec<String>,
return_type: String,
where_clauses: Vec<String>)
-> io::Result<()>
{
rust!(self, "{}fn {}<", qualifiers, name);
for type_parameter in &grammar.type_parameters {
rust!(self, "{0:1$}{2},", "", TAB, type_parameter);
}
for type_parameter in type_parameters {
rust!(self, "{0:1$}{2},", "", TAB, type_parameter);
}
rust!(self, ">(");
for parameter in &grammar.parameters {
rust!(self, "{}: {},", parameter.name, parameter.ty);
}
for parameter in ¶meters {
rust!(self, "{},", parameter);
}
if !grammar.where_clauses.is_empty() || !where_clauses.is_empty() {
rust!(self, ") -> {} where", return_type);
for where_clause in &grammar.where_clauses {
rust!(self, " {},", where_clause);
}
for where_clause in &where_clauses {
rust!(self, " {},", where_clause);
}
} else {
rust!(self,") -> {}", return_type);
}
Ok(())
}
pub fn write_uses(&mut self,
super_prefix: &str,
grammar: &Grammar)
-> io::Result<()>
{
for u in &grammar.uses {
if u.starts_with("super::") {
rust!(self, "use {}{};", super_prefix, u);
} else {
rust!(self, "use {};", u);
}
}
rust!(self, "extern crate lalrpop_util as {}lalrpop_util;",
grammar.prefix);
rust!(self, "use self::{}lalrpop_util::ParseError as {}ParseError;",
grammar.prefix, grammar.prefix);
Ok(())
}
}