mirror of
https://github.com/fluencelabs/lalrpop
synced 2025-03-31 07:21:04 +00:00
build up action tables
This commit is contained in:
parent
c66f7e2d40
commit
077ed9060d
@ -18,8 +18,14 @@ struct LR1<'grammar> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct State<'grammar> {
|
struct State<'grammar> {
|
||||||
items: Items<'grammar>,
|
items: Items<'grammar>,
|
||||||
shifts: Vec<(TerminalString, StateIndex)>,
|
tokens: Map<Lookahead, Action<'grammar>>,
|
||||||
gotos: Vec<(NonterminalString, StateIndex)>,
|
gotos: Map<NonterminalString, StateIndex>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Action<'grammar> {
|
||||||
|
Shift(StateIndex),
|
||||||
|
Reduce(&'grammar Production),
|
||||||
}
|
}
|
||||||
|
|
||||||
type Items<'grammar> = Rc<Vec<Item<'grammar>>>;
|
type Items<'grammar> = Rc<Vec<Item<'grammar>>>;
|
||||||
@ -40,11 +46,27 @@ struct Item<'grammar> {
|
|||||||
lookahead: Lookahead,
|
lookahead: Lookahead,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct StateSet<'grammar> {
|
struct StateSet<'grammar> {
|
||||||
states: Vec<State<'grammar>>,
|
states: Vec<State<'grammar>>,
|
||||||
state_map: Map<Items<'grammar>, StateIndex>,
|
state_map: Map<Items<'grammar>, StateIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TableConstructionError<'grammar> {
|
||||||
|
// when in this state:
|
||||||
|
items: Items<'grammar>,
|
||||||
|
|
||||||
|
// and looking at this token:
|
||||||
|
lookahead: Lookahead,
|
||||||
|
|
||||||
|
// we can reduce using this production:
|
||||||
|
production: &'grammar Production,
|
||||||
|
|
||||||
|
// but we can also:
|
||||||
|
conflict: Action<'grammar>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'grammar> LR1<'grammar> {
|
impl<'grammar> LR1<'grammar> {
|
||||||
fn new(grammar: &'grammar Grammar) -> LR1 {
|
fn new(grammar: &'grammar Grammar) -> LR1 {
|
||||||
LR1 {
|
LR1 {
|
||||||
@ -53,7 +75,9 @@ impl<'grammar> LR1<'grammar> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_states(&self, start_nt: NonterminalString) -> Vec<State<'grammar>> {
|
fn build_states(&self, start_nt: NonterminalString)
|
||||||
|
-> Result<Vec<State<'grammar>>, TableConstructionError<'grammar>>
|
||||||
|
{
|
||||||
let mut state_set = StateSet::new();
|
let mut state_set = StateSet::new();
|
||||||
|
|
||||||
// create the starting state
|
// create the starting state
|
||||||
@ -76,22 +100,41 @@ impl<'grammar> LR1<'grammar> {
|
|||||||
let items = self.transitive_closure(items);
|
let items = self.transitive_closure(items);
|
||||||
let next_state = state_set.add_state(items);
|
let next_state = state_set.add_state(items);
|
||||||
|
|
||||||
// FIXME check for conflicts
|
let this_state = &mut state_set.states[counter];
|
||||||
match symbol {
|
match symbol {
|
||||||
Symbol::Terminal(t) => {
|
Symbol::Terminal(s) => {
|
||||||
state_set.states[counter].shifts.push((t, next_state));
|
let action = Action::Shift(next_state);
|
||||||
|
let prev = this_state.tokens.insert(Lookahead::Terminal(s), action);
|
||||||
|
assert!(prev.is_none()); // cannot have a shift/shift conflict
|
||||||
}
|
}
|
||||||
Symbol::Nonterminal(t) => {
|
|
||||||
state_set.states[counter].gotos.push((t, next_state));
|
Symbol::Nonterminal(s) => {
|
||||||
|
let prev = this_state.gotos.insert(s, next_state);
|
||||||
|
assert!(prev.is_none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// finally, consider the reductions
|
||||||
|
let this_state = &mut state_set.states[counter];
|
||||||
|
for item in items.iter().filter(|i| i.can_reduce()) {
|
||||||
|
let action = Action::Reduce(item.production);
|
||||||
|
let prev = this_state.tokens.insert(item.lookahead, action);
|
||||||
|
if let Some(conflict) = prev {
|
||||||
|
return Err(TableConstructionError {
|
||||||
|
items: items.clone(),
|
||||||
|
lookahead: item.lookahead,
|
||||||
|
production: item.production,
|
||||||
|
conflict: conflict,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// extract a new state
|
// extract a new state
|
||||||
counter += 1;
|
counter += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
state_set.states
|
Ok(state_set.states)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn items(&self,
|
fn items(&self,
|
||||||
@ -191,9 +234,7 @@ impl<'grammar> StateSet<'grammar> {
|
|||||||
let states = &mut self.states;
|
let states = &mut self.states;
|
||||||
*self.state_map.entry(items.clone()).or_insert_with(|| {
|
*self.state_map.entry(items.clone()).or_insert_with(|| {
|
||||||
let index = StateIndex(states.len());
|
let index = StateIndex(states.len());
|
||||||
states.push(State { items: items,
|
states.push(State { items: items, tokens: map(), gotos: map() });
|
||||||
shifts: Vec::new(),
|
|
||||||
gotos: Vec::new() });
|
|
||||||
index
|
index
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
211
src/lr1/test.rs
211
src/lr1/test.rs
@ -92,212 +92,9 @@ grammar Foo {
|
|||||||
"#);
|
"#);
|
||||||
|
|
||||||
let lr1 = LR1::new(&grammar);
|
let lr1 = LR1::new(&grammar);
|
||||||
let mut states = lr1.build_states(nt("S"));
|
|
||||||
for state in &mut states {
|
|
||||||
state.shifts.sort();
|
|
||||||
state.gotos.sort();
|
|
||||||
}
|
|
||||||
expect_debug(&states, r#"[
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
S = (*) E [EOF],
|
|
||||||
E = (*) E "-" T [EOF],
|
|
||||||
E = (*) T [EOF],
|
|
||||||
E = (*) E "-" T ["-"],
|
|
||||||
E = (*) T ["-"],
|
|
||||||
T = (*) "N" [EOF],
|
|
||||||
T = (*) "(" E ")" [EOF],
|
|
||||||
T = (*) "N" ["-"],
|
|
||||||
T = (*) "(" E ")" ["-"]
|
|
||||||
],
|
|
||||||
shifts: [
|
|
||||||
("(", S4),
|
|
||||||
("N", S3)
|
|
||||||
],
|
|
||||||
gotos: [
|
|
||||||
(E, S2),
|
|
||||||
(T, S1)
|
|
||||||
]
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
E = T (*) [EOF],
|
|
||||||
E = T (*) ["-"]
|
|
||||||
],
|
|
||||||
shifts: [],
|
|
||||||
gotos: []
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
S = E (*) [EOF],
|
|
||||||
E = E (*) "-" T [EOF],
|
|
||||||
E = E (*) "-" T ["-"]
|
|
||||||
],
|
|
||||||
shifts: [
|
|
||||||
("-", S5)
|
|
||||||
],
|
|
||||||
gotos: []
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
T = "N" (*) [EOF],
|
|
||||||
T = "N" (*) ["-"]
|
|
||||||
],
|
|
||||||
shifts: [],
|
|
||||||
gotos: []
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
T = "(" (*) E ")" [EOF],
|
|
||||||
T = "(" (*) E ")" ["-"],
|
|
||||||
E = (*) E "-" T [")"],
|
|
||||||
E = (*) T [")"],
|
|
||||||
E = (*) E "-" T ["-"],
|
|
||||||
E = (*) T ["-"],
|
|
||||||
T = (*) "N" [")"],
|
|
||||||
T = (*) "(" E ")" [")"],
|
|
||||||
T = (*) "N" ["-"],
|
|
||||||
T = (*) "(" E ")" ["-"]
|
|
||||||
],
|
|
||||||
shifts: [
|
|
||||||
("(", S8),
|
|
||||||
("N", S9)
|
|
||||||
],
|
|
||||||
gotos: [
|
|
||||||
(E, S7),
|
|
||||||
(T, S6)
|
|
||||||
]
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
E = E "-" (*) T [EOF],
|
|
||||||
E = E "-" (*) T ["-"],
|
|
||||||
T = (*) "N" [EOF],
|
|
||||||
T = (*) "(" E ")" [EOF],
|
|
||||||
T = (*) "N" ["-"],
|
|
||||||
T = (*) "(" E ")" ["-"]
|
|
||||||
],
|
|
||||||
shifts: [
|
|
||||||
("(", S4),
|
|
||||||
("N", S3)
|
|
||||||
],
|
|
||||||
gotos: [
|
|
||||||
(T, S10)
|
|
||||||
]
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
E = T (*) [")"],
|
|
||||||
E = T (*) ["-"]
|
|
||||||
],
|
|
||||||
shifts: [],
|
|
||||||
gotos: []
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
T = "(" E (*) ")" [EOF],
|
|
||||||
T = "(" E (*) ")" ["-"],
|
|
||||||
E = E (*) "-" T [")"],
|
|
||||||
E = E (*) "-" T ["-"]
|
|
||||||
],
|
|
||||||
shifts: [
|
|
||||||
(")", S12),
|
|
||||||
("-", S11)
|
|
||||||
],
|
|
||||||
gotos: []
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
T = "(" (*) E ")" [")"],
|
|
||||||
T = "(" (*) E ")" ["-"],
|
|
||||||
E = (*) E "-" T [")"],
|
|
||||||
E = (*) T [")"],
|
|
||||||
E = (*) E "-" T ["-"],
|
|
||||||
E = (*) T ["-"],
|
|
||||||
T = (*) "N" [")"],
|
|
||||||
T = (*) "(" E ")" [")"],
|
|
||||||
T = (*) "N" ["-"],
|
|
||||||
T = (*) "(" E ")" ["-"]
|
|
||||||
],
|
|
||||||
shifts: [
|
|
||||||
("(", S8),
|
|
||||||
("N", S9)
|
|
||||||
],
|
|
||||||
gotos: [
|
|
||||||
(E, S13),
|
|
||||||
(T, S6)
|
|
||||||
]
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
T = "N" (*) [")"],
|
|
||||||
T = "N" (*) ["-"]
|
|
||||||
],
|
|
||||||
shifts: [],
|
|
||||||
gotos: []
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
E = E "-" T (*) [EOF],
|
|
||||||
E = E "-" T (*) ["-"]
|
|
||||||
],
|
|
||||||
shifts: [],
|
|
||||||
gotos: []
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
E = E "-" (*) T [")"],
|
|
||||||
E = E "-" (*) T ["-"],
|
|
||||||
T = (*) "N" [")"],
|
|
||||||
T = (*) "(" E ")" [")"],
|
|
||||||
T = (*) "N" ["-"],
|
|
||||||
T = (*) "(" E ")" ["-"]
|
|
||||||
],
|
|
||||||
shifts: [
|
|
||||||
("(", S8),
|
|
||||||
("N", S9)
|
|
||||||
],
|
|
||||||
gotos: [
|
|
||||||
(T, S14)
|
|
||||||
]
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
T = "(" E ")" (*) [EOF],
|
|
||||||
T = "(" E ")" (*) ["-"]
|
|
||||||
],
|
|
||||||
shifts: [],
|
|
||||||
gotos: []
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
T = "(" E (*) ")" [")"],
|
|
||||||
T = "(" E (*) ")" ["-"],
|
|
||||||
E = E (*) "-" T [")"],
|
|
||||||
E = E (*) "-" T ["-"]
|
|
||||||
],
|
|
||||||
shifts: [
|
|
||||||
(")", S15),
|
|
||||||
("-", S11)
|
|
||||||
],
|
|
||||||
gotos: []
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
E = E "-" T (*) [")"],
|
|
||||||
E = E "-" T (*) ["-"]
|
|
||||||
],
|
|
||||||
shifts: [],
|
|
||||||
gotos: []
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
items: [
|
|
||||||
T = "(" E ")" (*) [")"],
|
|
||||||
T = "(" E ")" (*) ["-"]
|
|
||||||
],
|
|
||||||
shifts: [],
|
|
||||||
gotos: []
|
|
||||||
}
|
|
||||||
]"#);
|
|
||||||
|
|
||||||
|
// for now, just test that process does not result in an error
|
||||||
|
// and yields expected number of states.
|
||||||
|
let states = lr1.build_states(nt("S")).unwrap();
|
||||||
|
assert_eq!(states.len(), 16);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user