mirror of
https://github.com/fluencelabs/lalrpop
synced 2025-04-01 07:51:03 +00:00
generate a start fn
This commit is contained in:
parent
bc4172b556
commit
e04d65056b
@ -116,7 +116,7 @@ fn parse_and_normalize_grammar(options: &Options) {
|
|||||||
|
|
||||||
let stdout: &mut Write = &mut io::stdout();
|
let stdout: &mut Write = &mut io::stdout();
|
||||||
let mut rust = RustWrite::new(stdout);
|
let mut rust = RustWrite::new(stdout);
|
||||||
lr1::ascent::compile(&grammar, &vec![], &states, &mut rust).unwrap();
|
lr1::ascent::compile(&grammar, &vec![], start_nt, &states, &mut rust).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_error(file_text: &FileText, span: pt::Span, message: &str) -> ! {
|
fn report_error(file_text: &FileText, span: pt::Span, message: &str) -> ! {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//! [recursive ascent]: https://en.wikipedia.org/wiki/Recursive_ascent_parser
|
//! [recursive ascent]: https://en.wikipedia.org/wiki/Recursive_ascent_parser
|
||||||
|
|
||||||
use intern::{intern, InternedString};
|
use intern::{intern, InternedString};
|
||||||
use grammar::repr::{Grammar, Production, Symbol};
|
use grammar::repr::{Grammar, NonterminalString, Production, Symbol};
|
||||||
use lr1::{Action, Lookahead, State, StateIndex};
|
use lr1::{Action, Lookahead, State, StateIndex};
|
||||||
use rust::RustWrite;
|
use rust::RustWrite;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
@ -13,17 +13,19 @@ pub type Path = Vec<InternedString>;
|
|||||||
|
|
||||||
pub fn compile<'grammar>(grammar: &'grammar Grammar,
|
pub fn compile<'grammar>(grammar: &'grammar Grammar,
|
||||||
action_path: &Path,
|
action_path: &Path,
|
||||||
|
start_symbol: NonterminalString,
|
||||||
states: &[State<'grammar>],
|
states: &[State<'grammar>],
|
||||||
out: &mut RustWrite<&mut Write>)
|
out: &mut RustWrite<&mut Write>)
|
||||||
-> io::Result<()>
|
-> io::Result<()>
|
||||||
{
|
{
|
||||||
let mut ascent = RecursiveAscent::new(grammar, action_path, states, out);
|
let mut ascent = RecursiveAscent::new(grammar, action_path, start_symbol, states, out);
|
||||||
ascent.write()
|
ascent.write()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RecursiveAscent<'ascent,'writer:'ascent,'grammar:'ascent> {
|
struct RecursiveAscent<'ascent,'writer:'ascent,'grammar:'ascent> {
|
||||||
grammar: &'grammar Grammar,
|
grammar: &'grammar Grammar,
|
||||||
action_path: &'ascent Path,
|
action_path: &'ascent Path,
|
||||||
|
start_symbol: NonterminalString,
|
||||||
states: &'ascent [State<'grammar>],
|
states: &'ascent [State<'grammar>],
|
||||||
state_prefixes: Vec<&'grammar [Symbol]>,
|
state_prefixes: Vec<&'grammar [Symbol]>,
|
||||||
out: &'ascent mut RustWrite<&'writer mut Write>,
|
out: &'ascent mut RustWrite<&'writer mut Write>,
|
||||||
@ -32,6 +34,7 @@ struct RecursiveAscent<'ascent,'writer:'ascent,'grammar:'ascent> {
|
|||||||
impl<'ascent,'writer,'grammar> RecursiveAscent<'ascent,'writer,'grammar> {
|
impl<'ascent,'writer,'grammar> RecursiveAscent<'ascent,'writer,'grammar> {
|
||||||
fn new(grammar: &'grammar Grammar,
|
fn new(grammar: &'grammar Grammar,
|
||||||
action_path: &'ascent Path,
|
action_path: &'ascent Path,
|
||||||
|
start_symbol: NonterminalString,
|
||||||
states: &'ascent [State<'grammar>],
|
states: &'ascent [State<'grammar>],
|
||||||
out: &'ascent mut RustWrite<&'writer mut Write>)
|
out: &'ascent mut RustWrite<&'writer mut Write>)
|
||||||
-> RecursiveAscent<'ascent,'writer,'grammar>
|
-> RecursiveAscent<'ascent,'writer,'grammar>
|
||||||
@ -43,6 +46,7 @@ impl<'ascent,'writer,'grammar> RecursiveAscent<'ascent,'writer,'grammar> {
|
|||||||
states: states,
|
states: states,
|
||||||
state_prefixes: states.iter().map(|s| s.prefix()).collect(),
|
state_prefixes: states.iter().map(|s| s.prefix()).collect(),
|
||||||
action_path: action_path,
|
action_path: action_path,
|
||||||
|
start_symbol: start_symbol,
|
||||||
out: out,
|
out: out,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,6 +58,9 @@ impl<'ascent,'writer,'grammar> RecursiveAscent<'ascent,'writer,'grammar> {
|
|||||||
try!(self.write_return_type_defn());
|
try!(self.write_return_type_defn());
|
||||||
rust!(self.out, "");
|
rust!(self.out, "");
|
||||||
|
|
||||||
|
try!(self.write_start_fn());
|
||||||
|
rust!(self.out, "");
|
||||||
|
|
||||||
for i in 0..self.states.len() {
|
for i in 0..self.states.len() {
|
||||||
try!(self.write_state_fn(StateIndex(i)));
|
try!(self.write_state_fn(StateIndex(i)));
|
||||||
rust!(self.out, "");
|
rust!(self.out, "");
|
||||||
@ -83,10 +90,27 @@ impl<'ascent,'writer,'grammar> RecursiveAscent<'ascent,'writer,'grammar> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_start_fn(&mut self) -> io::Result<()> {
|
||||||
|
rust!(self.out, "pub fn start<TOKENS: Iterator<Item=Terminal>>(");
|
||||||
|
rust!(self.out, "tokens: &mut TOKENS)");
|
||||||
|
rust!(self.out, "-> Result<(Option<Terminal>, {}), Option<Terminal>>",
|
||||||
|
self.grammar.types.nonterminal_type(self.start_symbol));
|
||||||
|
rust!(self.out, "{{");
|
||||||
|
|
||||||
|
rust!(self.out, "let mut lookahead = tokens.next();");
|
||||||
|
rust!(self.out, "match try!(state0(lookahead, tokens)) {{");
|
||||||
|
rust!(self.out, "(lookahead, Nonterminal::{}(nt)) => (lookahead, nt),",
|
||||||
|
self.start_symbol);
|
||||||
|
rust!(self.out, "_ => unreachable!(),");
|
||||||
|
rust!(self.out, "}}");
|
||||||
|
rust!(self.out, "}}");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn write_state_fn(&mut self, this_index: StateIndex) -> io::Result<()> {
|
fn write_state_fn(&mut self, this_index: StateIndex) -> io::Result<()> {
|
||||||
let this_state = &self.states[this_index.0];
|
let this_state = &self.states[this_index.0];
|
||||||
let this_prefix = self.state_prefixes[this_index.0];
|
let this_prefix = self.state_prefixes[this_index.0];
|
||||||
let terminal_type = self.grammar.types.terminal_type();
|
|
||||||
|
|
||||||
// Leave a comment explaining what this state is.
|
// Leave a comment explaining what this state is.
|
||||||
rust!(self.out, "// State {}", this_index.0);
|
rust!(self.out, "// State {}", this_index.0);
|
||||||
@ -105,17 +129,14 @@ impl<'ascent,'writer,'grammar> RecursiveAscent<'ascent,'writer,'grammar> {
|
|||||||
// set to true if goto actions are worth generating
|
// set to true if goto actions are worth generating
|
||||||
let mut fallthrough = false;
|
let mut fallthrough = false;
|
||||||
|
|
||||||
rust!(self.out, "fn state{}<TOKENS: Iterator<Item={}>>(", this_index.0, terminal_type);
|
rust!(self.out, "fn state{}<TOKENS: Iterator<Item=Terminal>>(", this_index.0);
|
||||||
rust!(self.out, "mut lookahead: Option<{}>,", terminal_type);
|
rust!(self.out, "mut lookahead: Option<Terminal>,");
|
||||||
rust!(self.out, "tokens: &mut TOKENS,");
|
rust!(self.out, "tokens: &mut TOKENS,");
|
||||||
for i in 0..this_prefix.len() {
|
for i in 0..this_prefix.len() {
|
||||||
let terminator = if i < this_prefix.len()-1 {","} else {")"};
|
rust!(self.out, "sym{}: &mut Option<{}>,",
|
||||||
rust!(self.out, "sym{}: &mut Option<{}>{}",
|
i, this_prefix[i].ty(&self.grammar.types));
|
||||||
i, this_prefix[i].ty(&self.grammar.types), terminator);
|
|
||||||
}
|
}
|
||||||
rust!(self.out, "-> Result<(Option<{}>, Nonterminal), Option<{}>>",
|
rust!(self.out, ") -> Result<(Option<Terminal>, Nonterminal), Option<Terminal>> {{");
|
||||||
terminal_type, terminal_type);
|
|
||||||
rust!(self.out, "{{");
|
|
||||||
|
|
||||||
rust!(self.out, "let mut result;");
|
rust!(self.out, "let mut result;");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user