1 //! LR(1) interpeter. Just builds up parse trees. Intended for testing.
2
3 use generate::ParseTree;
4 use grammar::repr::*;
5 use lr1::core::*;
6 use lr1::lookahead::*;
7 use std::fmt::{Debug, Display, Error, Formatter};
8 use std::iter::IntoIterator;
9 use util::Sep;
10
11 pub type InterpretError<'grammar, L> = (&'grammar State<'grammar, L>, Token);
12
13 /// Feed in the given tokens and then EOF, returning the final parse tree that is reduced.
interpret<'grammar, L>( states: &'grammar [State<'grammar, L>], tokens: Vec<TerminalString>, ) -> Result<ParseTree, InterpretError<'grammar, L>> where L: LookaheadInterpret,14 pub fn interpret<'grammar, L>(
15 states: &'grammar [State<'grammar, L>],
16 tokens: Vec<TerminalString>,
17 ) -> Result<ParseTree, InterpretError<'grammar, L>>
18 where
19 L: LookaheadInterpret,
20 {
21 println!("interpret(tokens={:?})", tokens);
22 let mut m = Machine::new(states);
23 m.execute(tokens.into_iter())
24 }
25
26 /// Feed in the given tokens and returns the states on the stack.
interpret_partial<'grammar, TOKENS, L>( states: &'grammar [State<'grammar, L>], tokens: TOKENS, ) -> Result<Vec<StateIndex>, InterpretError<'grammar, L>> where TOKENS: IntoIterator<Item = TerminalString>, L: LookaheadInterpret,27 pub fn interpret_partial<'grammar, TOKENS, L>(
28 states: &'grammar [State<'grammar, L>],
29 tokens: TOKENS,
30 ) -> Result<Vec<StateIndex>, InterpretError<'grammar, L>>
31 where
32 TOKENS: IntoIterator<Item = TerminalString>,
33 L: LookaheadInterpret,
34 {
35 let mut m = Machine::new(states);
36 try!(m.execute_partial(tokens.into_iter()));
37 Ok(m.state_stack)
38 }
39
40 struct Machine<'grammar, L: LookaheadInterpret + 'grammar> {
41 states: &'grammar [State<'grammar, L>],
42 state_stack: Vec<StateIndex>,
43 data_stack: Vec<ParseTree>,
44 }
45
46 impl<'grammar, L> Machine<'grammar, L>
47 where
48 L: LookaheadInterpret,
49 {
new(states: &'grammar [State<'grammar, L>]) -> Machine<'grammar, L>50 fn new(states: &'grammar [State<'grammar, L>]) -> Machine<'grammar, L> {
51 Machine {
52 states: states,
53 state_stack: vec![],
54 data_stack: vec![],
55 }
56 }
57
top_state(&self) -> &'grammar State<'grammar, L>58 fn top_state(&self) -> &'grammar State<'grammar, L> {
59 let index = self.state_stack.last().unwrap();
60 &self.states[index.0]
61 }
62
execute_partial<TOKENS>( &mut self, mut tokens: TOKENS, ) -> Result<(), InterpretError<'grammar, L>> where TOKENS: Iterator<Item = TerminalString>,63 fn execute_partial<TOKENS>(
64 &mut self,
65 mut tokens: TOKENS,
66 ) -> Result<(), InterpretError<'grammar, L>>
67 where
68 TOKENS: Iterator<Item = TerminalString>,
69 {
70 assert!(self.state_stack.is_empty());
71 assert!(self.data_stack.is_empty());
72
73 self.state_stack.push(StateIndex(0));
74
75 let mut token = tokens.next();
76 while let Some(terminal) = token.clone() {
77 let state = self.top_state();
78
79 println!("state={:?}", state);
80 println!("terminal={:?}", terminal);
81
82 // check whether we can shift this token
83 if let Some(&next_index) = state.shifts.get(&terminal) {
84 self.data_stack.push(ParseTree::Terminal(terminal.clone()));
85 self.state_stack.push(next_index);
86 token = tokens.next();
87 } else if let Some(production) = L::reduction(state, &Token::Terminal(terminal.clone()))
88 {
89 let more = self.reduce(production);
90 assert!(more);
91 } else {
92 return Err((state, Token::Terminal(terminal.clone())));
93 }
94 }
95
96 Ok(())
97 }
98
execute<TOKENS>(&mut self, tokens: TOKENS) -> Result<ParseTree, InterpretError<'grammar, L>> where TOKENS: Iterator<Item = TerminalString>,99 fn execute<TOKENS>(&mut self, tokens: TOKENS) -> Result<ParseTree, InterpretError<'grammar, L>>
100 where
101 TOKENS: Iterator<Item = TerminalString>,
102 {
103 try!(self.execute_partial(tokens));
104
105 // drain now for EOF
106 loop {
107 let state = self.top_state();
108 match L::reduction(state, &Token::EOF) {
109 None => {
110 return Err((state, Token::EOF));
111 }
112 Some(production) => {
113 if !self.reduce(production) {
114 assert_eq!(self.data_stack.len(), 1);
115 return Ok(self.data_stack.pop().unwrap());
116 }
117 }
118 }
119 }
120 }
121
reduce(&mut self, production: &Production) -> bool122 fn reduce(&mut self, production: &Production) -> bool {
123 println!("reduce={:?}", production);
124
125 let args = production.symbols.len();
126
127 // remove the top N items from the data stack
128 let mut popped = vec![];
129 for _ in 0..args {
130 popped.push(self.data_stack.pop().unwrap());
131 }
132 popped.reverse();
133
134 // remove the top N states
135 for _ in 0..args {
136 self.state_stack.pop().unwrap();
137 }
138
139 // construct the new, reduced tree and push it on the stack
140 let tree = ParseTree::Nonterminal(production.nonterminal.clone(), popped);
141 self.data_stack.push(tree);
142
143 // recover the state and extract the "Goto" action
144 let receiving_state = self.top_state();
145 match receiving_state.gotos.get(&production.nonterminal) {
146 Some(&goto_state) => {
147 self.state_stack.push(goto_state);
148 true // keep going
149 }
150 None => {
151 false // all done
152 }
153 }
154 }
155 }
156
157 impl Debug for ParseTree {
fmt(&self, fmt: &mut Formatter) -> Result<(), Error>158 fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
159 Display::fmt(self, fmt)
160 }
161 }
162
163 impl Display for ParseTree {
fmt(&self, fmt: &mut Formatter) -> Result<(), Error>164 fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
165 match *self {
166 ParseTree::Nonterminal(ref id, ref trees) => {
167 write!(fmt, "[{}: {}]", id, Sep(", ", trees))
168 }
169 ParseTree::Terminal(ref id) => write!(fmt, "{}", id),
170 }
171 }
172 }
173
174 pub trait LookaheadInterpret: Lookahead {
reduction<'grammar>( state: &State<'grammar, Self>, token: &Token, ) -> Option<&'grammar Production>175 fn reduction<'grammar>(
176 state: &State<'grammar, Self>,
177 token: &Token,
178 ) -> Option<&'grammar Production>;
179 }
180
181 impl LookaheadInterpret for Nil {
reduction<'grammar>( state: &State<'grammar, Self>, _token: &Token, ) -> Option<&'grammar Production>182 fn reduction<'grammar>(
183 state: &State<'grammar, Self>,
184 _token: &Token,
185 ) -> Option<&'grammar Production> {
186 state
187 .reductions
188 .iter()
189 .map(|&(_, production)| production)
190 .next()
191 }
192 }
193
194 impl LookaheadInterpret for TokenSet {
reduction<'grammar>( state: &State<'grammar, Self>, token: &Token, ) -> Option<&'grammar Production>195 fn reduction<'grammar>(
196 state: &State<'grammar, Self>,
197 token: &Token,
198 ) -> Option<&'grammar Production> {
199 state
200 .reductions
201 .iter()
202 .filter(|&&(ref tokens, _)| tokens.contains(token))
203 .map(|&(_, production)| production)
204 .next()
205 }
206 }
207