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