From 19a085253916d2e21c268752efbc453cb56eb79c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 28 Feb 2016 07:48:40 -0500 Subject: [PATCH] Make a trait for lookahead --- lalrpop/src/lr1/core/mod.rs | 52 ++++++++++++------------ lalrpop/src/lr1/lookahead.rs | 19 +++++++++ lalrpop/src/lr1/trace/shift/test.rs | 2 +- lalrpop/src/lr1/trace/trace_graph/mod.rs | 3 +- 4 files changed, 48 insertions(+), 28 deletions(-) diff --git a/lalrpop/src/lr1/core/mod.rs b/lalrpop/src/lr1/core/mod.rs index 1455c36..df1199c 100644 --- a/lalrpop/src/lr1/core/mod.rs +++ b/lalrpop/src/lr1/core/mod.rs @@ -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>> } -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>, @@ -104,7 +104,7 @@ pub struct State<'grammar, L: Clone> { pub gotos: Map, } -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>, } -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!(""); - } + try!(write!(fmt, "{} ={} (*){}", + self.production.nonterminal, + Prefix(" ", &self.production.symbols[..self.index]), + Prefix(" ", &self.production.symbols[self.index..]))); - write!(fmt, "{} ={} (*){}{}", - self.production.nonterminal, - Prefix(" ", &self.production.symbols[..self.index]), - Prefix(" ", &self.production.symbols[self.index..]), - lookahead_debug) + 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. diff --git a/lalrpop/src/lr1/lookahead.rs b/lalrpop/src/lr1/lookahead.rs index 22ea92d..c27e9d6 100644 --- a/lalrpop/src/lr1/lookahead.rs +++ b/lalrpop/src/lr1/lookahead.rs @@ -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 { diff --git a/lalrpop/src/lr1/trace/shift/test.rs b/lalrpop/src/lr1/trace/shift/test.rs index 2509663..ec6e49f 100644 --- a/lalrpop/src/lr1/trace/shift/test.rs +++ b/lalrpop/src/lr1/trace/shift/test.rs @@ -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); diff --git a/lalrpop/src/lr1/trace/trace_graph/mod.rs b/lalrpop/src/lr1/trace/trace_graph/mod.rs index 2c263b1..fc659f1 100644 --- a/lalrpop/src/lr1/trace/trace_graph/mod.rs +++ b/lalrpop/src/lr1/trace/trace_graph/mod.rs @@ -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> for NonterminalString { } } -impl<'grammar, L: Clone> Into> for Item<'grammar, L> { +impl<'grammar, L: Lookahead> Into> for Item<'grammar, L> { fn into(self) -> TraceGraphNode<'grammar> { TraceGraphNode::Item(self.to_lr0()) }