Make a trait for lookahead

This commit is contained in:
Niko Matsakis 2016-02-28 07:48:40 -05:00
parent b0b7735bbc
commit 19a0852539
4 changed files with 48 additions and 28 deletions

View File

@ -3,34 +3,34 @@
use collections::Map;
use grammar::repr::*;
use itertools::Itertools;
use std::fmt::{Debug, Formatter, Error};
use std::fmt::{Debug, Display, Formatter, Error};
use std::rc::Rc;
use util::Prefix;
use super::lookahead::Token;
use super::lookahead::*;
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Item<'grammar, L: Clone> {
pub struct Item<'grammar, L: Lookahead> {
pub production: &'grammar Production,
/// the dot comes before `index`, so `index` would be 1 for X = A (*) B C
pub index: usize,
pub lookahead: L,
}
pub type LR0Item<'grammar> = Item<'grammar, ()>;
pub type LR0Item<'grammar> = Item<'grammar, Nil>;
pub type LR1Item<'grammar> = Item<'grammar, Token>;
impl<'grammar> Item<'grammar, ()> {
impl<'grammar> Item<'grammar, Nil> {
#[cfg(test)]
pub fn lr0(production: &'grammar Production,
index: usize)
-> Self {
Item { production: production, index: index, lookahead: () }
Item { production: production, index: index, lookahead: Nil }
}
}
impl<'grammar, L: Clone> Item<'grammar, L> {
impl<'grammar, L: Lookahead> Item<'grammar, L> {
pub fn prefix(&self) -> &'grammar [Symbol] {
&self.production.symbols[..self.index]
}
@ -53,7 +53,7 @@ impl<'grammar, L: Clone> Item<'grammar, L> {
}
pub fn to_lr0(&self) -> LR0Item<'grammar> {
Item { production: self.production, index: self.index, lookahead: () }
Item { production: self.production, index: self.index, lookahead: Nil }
}
pub fn can_shift(&self) -> bool {
@ -88,15 +88,15 @@ impl<'grammar, L: Clone> Item<'grammar, L> {
pub struct StateIndex(pub usize);
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Items<'grammar, L: Clone> {
pub struct Items<'grammar, L: Lookahead> {
pub vec: Rc<Vec<Item<'grammar, L>>>
}
pub type LR0Items<'grammar> = Items<'grammar, ()>;
pub type LR0Items<'grammar> = Items<'grammar, Nil>;
pub type LR1Items<'grammar> = Items<'grammar, Token>;
#[derive(Debug)]
pub struct State<'grammar, L: Clone> {
pub struct State<'grammar, L: Lookahead> {
pub index: StateIndex,
pub items: Items<'grammar, L>,
pub tokens: Map<Token, Action<'grammar>>,
@ -104,7 +104,7 @@ pub struct State<'grammar, L: Clone> {
pub gotos: Map<NonterminalString, StateIndex>,
}
pub type LR0State<'grammar> = State<'grammar, ()>;
pub type LR0State<'grammar> = State<'grammar, Nil>;
pub type LR1State<'grammar> = State<'grammar, Token>;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@ -131,24 +131,18 @@ pub struct TableConstructionError<'grammar> {
pub states: Vec<LR1State<'grammar>>,
}
impl<'grammar, L: Clone+Debug> Debug for Item<'grammar, L> {
impl<'grammar, L: Lookahead> Debug for Item<'grammar, L> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
let mut lookahead_debug = format!("{:?}", self.lookahead);
if lookahead_debug != "()" {
lookahead_debug = format!(" [{}]", lookahead_debug);
} else {
lookahead_debug = format!("");
}
write!(fmt, "{} ={} (*){}{}",
try!(write!(fmt, "{} ={} (*){}",
self.production.nonterminal,
Prefix(" ", &self.production.symbols[..self.index]),
Prefix(" ", &self.production.symbols[self.index..]),
lookahead_debug)
Prefix(" ", &self.production.symbols[self.index..])));
self.lookahead.fmt_as_item_suffix(fmt)
}
}
impl Debug for Token {
impl Display for Token {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self {
Token::EOF => write!(fmt, "EOF"),
@ -157,13 +151,19 @@ impl Debug for Token {
}
}
impl Debug for Token {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
write!(fmt, "{}", self)
}
}
impl Debug for StateIndex {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
write!(fmt, "S{}", self.0)
}
}
impl<'grammar, L: Clone> State<'grammar, L> {
impl<'grammar, L: Lookahead> State<'grammar, L> {
/// Returns the set of symbols which must appear on the stack to
/// be in this state. This is the *maximum* prefix of any item,
/// basically.

View File

@ -2,6 +2,19 @@ use bit_set::{self, BitSet};
use std::fmt::{Debug, Formatter, Error};
use grammar::repr::*;
pub trait Lookahead: Clone + Debug + PartialEq + Eq + PartialOrd + Ord {
fn fmt_as_item_suffix(&self, fmt: &mut Formatter) -> Result<(), Error>;
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Nil;
impl Lookahead for Nil {
fn fmt_as_item_suffix(&self, _fmt: &mut Formatter) -> Result<(), Error> {
Ok(())
}
}
/// I have semi-arbitrarily decided to say that a "token" is either
/// one of the terminals of our language, or else the pseudo-symbol
/// EOF that represents "end of input".
@ -11,6 +24,12 @@ pub enum Token {
Terminal(TerminalString),
}
impl Lookahead for Token {
fn fmt_as_item_suffix(&self, fmt: &mut Formatter) -> Result<(), Error> {
write!(fmt, " [{}]", self)
}
}
impl Token {
pub fn unwrap_terminal(self) -> TerminalString {
match self {

View File

@ -43,7 +43,7 @@ pub Ty: () = {
// Ty = Ty -> Ty (*) (reduce)
assert!(conflict.production.symbols.len() == 3);
let item = Item { production: conflict.production, index: 1, lookahead: () };
let item = Item::lr0(conflict.production, 1);
println!("item={:?}", item);
let tracer = Tracer::new(&grammar, &states);
let graph = tracer.backtrace_shift(conflict.state, item);

View File

@ -1,5 +1,6 @@
use collections::{Map, map};
use lr1::core::*;
use lr1::lookahead::*;
use lr1::example::*;
use grammar::repr::*;
use petgraph::{EdgeDirection, Graph};
@ -102,7 +103,7 @@ impl<'grammar> Into<TraceGraphNode<'grammar>> for NonterminalString {
}
}
impl<'grammar, L: Clone> Into<TraceGraphNode<'grammar>> for Item<'grammar, L> {
impl<'grammar, L: Lookahead> Into<TraceGraphNode<'grammar>> for Item<'grammar, L> {
fn into(self) -> TraceGraphNode<'grammar> {
TraceGraphNode::Item(self.to_lr0())
}