Skip to content

Commit 27160b8

Browse files
authored
Merge pull request #37 from Tsukuba-Programming-Lab/#36_LALR1
#36 LALR1 新版
2 parents 252ae0f + e8e93f8 commit 27160b8

File tree

15 files changed

+592
-38
lines changed

15 files changed

+592
-38
lines changed

Cargo.lock

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ copager_parse_lr_common = { path = "./crates/parse_lr_common", optional = true }
1818
copager_parse_lr_lr0 = { path = "./crates/parse_lr_lr0", optional = true }
1919
copager_parse_lr_lr1 = { path = "./crates/parse_lr_lr1", optional = true }
2020
copager_parse_lr_slr1 = { path = "./crates/parse_lr_slr1", optional = true }
21+
copager_parse_lr_lalr1 = { path = "./crates/parse_lr_lalr1", optional = true }
2122
copager_ir = { path = "./crates/ir" }
2223
copager_ir_void = { path = "./crates/ir_void", optional = true }
2324
copager_ir_sexp = { path = "./crates/ir_sexp", optional = true }
@@ -54,6 +55,7 @@ regexlex = ["dep:copager_lex_regex"]
5455
lr0 = ["dep:copager_parse_lr_lr0"]
5556
lr1 = ["dep:copager_parse_lr_lr1"]
5657
slr1 = ["dep:copager_parse_lr_slr1"]
58+
lalr1 = ["dep:copager_parse_lr_lalr1"]
5759

5860
# ir
5961
void = ["dep:copager_ir_void"]
@@ -76,6 +78,7 @@ members = [
7678
"./crates/parse_lr_lr0",
7779
"./crates/parse_lr_lr1",
7880
"./crates/parse_lr_slr1",
81+
"./crates/parse_lr_lalr1",
7982
"./crates/ir",
8083
"./crates/ir_void",
8184
"./crates/ir_sexp",

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Rust製パーサジェネレータ
1919

2020
- `lr0` : [crates/parse_lr0](crates/parse_lr0)
2121
- `lr1` : [crates/parse_lr1](crates/parse_lr1)
22+
- `slr1` : [crates/parse_slr1](crates/parse_slr1)
23+
- `lalr1` : [crates/parse_lalr1](crates/parse_lalr1)
2224

2325
### IR
2426

crates/parse_common/src/rule/first.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ where
5353
firsts.remove(&RuleElem::Epsilon);
5454
continue
5555
}
56-
break
56+
return firsts.into_iter().collect();
5757
}
58+
firsts.insert(&RuleElem::EOF);
5859
firsts.into_iter().collect()
5960
}
6061
}

crates/parse_lr_common/src/automaton.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use copager_cfg::rule::RuleElem;
33

44
pub mod lr0;
55
pub mod lr1;
6+
pub mod lalr1;
67

78
pub trait Automaton<'a: 'b, 'b, T: TokenTag + 'a> {
89
fn len(&self) -> usize;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pub mod dfa;
2+
pub mod item;
3+
4+
pub use dfa::LALR1DFA;
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
use std::collections::{HashMap, HashSet};
2+
use std::rc::Rc;
3+
use std::sync::RwLock;
4+
5+
use copager_cfg::token::TokenTag;
6+
use copager_cfg::rule::{Rule, RuleElem, RuleTag};
7+
8+
use crate::automaton::lr1::dfa::{LR1DFA, LR1DFANode};
9+
use crate::lalr1::item::{LALR1Item, LALR1ItemSet};
10+
use crate::automaton::Automaton;
11+
12+
#[derive(Debug)]
13+
pub struct LALR1DFANode<'a, T, R>
14+
where
15+
T: TokenTag,
16+
R: RuleTag<T>,
17+
{
18+
pub id: usize,
19+
pub itemset: LALR1ItemSet<'a, T, R>,
20+
}
21+
22+
impl<'a, T, R> LALR1DFANode<'a, T, R>
23+
where
24+
T: TokenTag,
25+
R: RuleTag<T>,
26+
{
27+
fn from_lr1_nodes<'b>(id: usize, lr1_dfa_nodes: Vec<Rc<RwLock<LR1DFANode<'a, 'b, T, R>>>>) -> Self {
28+
let mut rule_la_tokens_map = HashMap::new();
29+
for lr1_dfa_node in &lr1_dfa_nodes {
30+
for rule in &lr1_dfa_node.read().unwrap().itemset.items {
31+
rule_la_tokens_map
32+
.entry((rule.rule, rule.dot_pos))
33+
.or_insert_with(HashSet::new)
34+
.insert(rule.la_token);
35+
}
36+
}
37+
38+
let grouped_items = rule_la_tokens_map
39+
.into_iter()
40+
.map(|((rule, dot_pos), la_tokens)| {
41+
LALR1Item::new(rule, dot_pos, la_tokens.into_iter().collect())
42+
})
43+
.collect();
44+
let itemset = LALR1ItemSet::new(grouped_items);
45+
46+
LALR1DFANode { id, itemset }
47+
}
48+
}
49+
50+
impl<'a, T, R> LALR1DFANode<'a, T, R>
51+
where
52+
T: TokenTag,
53+
R: RuleTag<T>,
54+
{
55+
pub fn find_all(&self, rule: &Rule<T, R>) -> impl Iterator<Item = (&'a Rule<T, R>, &[&'a RuleElem<T>])> {
56+
self.find_all_by(move |item| item.rule == rule)
57+
}
58+
59+
pub fn find_all_by<F>(&self, cond: F) -> impl Iterator<Item = (&'a Rule<T, R>, &[&'a RuleElem<T>])>
60+
where
61+
F: Fn(&&LALR1Item<'a, T, R>) -> bool
62+
{
63+
self.itemset
64+
.items
65+
.iter()
66+
.filter(cond)
67+
.map(|item| (item.rule, item.la_tokens.as_slice()))
68+
}
69+
}
70+
71+
#[derive(Debug)]
72+
pub struct LALR1DFA<'a, T, R>
73+
where
74+
T: TokenTag,
75+
R: RuleTag<T>,
76+
{
77+
pub nodes: Vec<LALR1DFANode<'a, T, R>>,
78+
pub edges: Vec<(usize, usize, &'a RuleElem<T>)>,
79+
}
80+
81+
impl<'a, 'b, T, R> From<LR1DFA<'a, 'b, T, R>> for LALR1DFA<'a, T, R>
82+
where
83+
T: TokenTag,
84+
R: RuleTag<T>,
85+
{
86+
fn from(lr1_dfa: LR1DFA<'a, 'b, T, R>) -> Self {
87+
let lalr1_dfa_keys = lr1_dfa.nodes
88+
.into_iter()
89+
.map(LALR1DFAKey::from)
90+
.collect::<Vec<_>>();
91+
92+
let mut managed_keys = vec![];
93+
let mut managed_lr1_nodes: Vec<Vec<_>> = vec![];
94+
for lalr1_dfa_key in lalr1_dfa_keys {
95+
let managed_idx = managed_keys.iter().position(|key| key == &lalr1_dfa_key);
96+
if let Some(managed_idx) = managed_idx {
97+
let lr1_node = Rc::clone(&lalr1_dfa_key.0);
98+
managed_lr1_nodes[managed_idx].push(lr1_node);
99+
} else {
100+
managed_lr1_nodes.push(vec![Rc::clone(&lalr1_dfa_key.0)]);
101+
managed_keys.push(lalr1_dfa_key);
102+
}
103+
}
104+
105+
let mut lalr1_cand_node_sets = managed_keys
106+
.into_iter()
107+
.zip(managed_lr1_nodes.into_iter())
108+
.collect::<Vec<_>>();
109+
lalr1_cand_node_sets.sort_by_cached_key(|(key, _)| key.0.read().unwrap().id);
110+
111+
let mut id_map = HashMap::new();
112+
let mut lalr1_nodes = vec![];
113+
for (new_id, (_, lalr1_cand_node_set)) in lalr1_cand_node_sets.into_iter().enumerate() {
114+
for lalr1_cand_node in &lalr1_cand_node_set {
115+
let old_id = lalr1_cand_node.read().unwrap().id;
116+
id_map.insert(old_id, new_id);
117+
}
118+
lalr1_nodes.push(LALR1DFANode::from_lr1_nodes(new_id, lalr1_cand_node_set));
119+
}
120+
121+
let lalr1_edges = lr1_dfa.edges
122+
.into_iter()
123+
.map(|(from, to, cond)| {
124+
let from = id_map.get(&from).unwrap();
125+
let to = id_map.get(&to).unwrap();
126+
(*from, *to, cond)
127+
})
128+
.collect();
129+
130+
LALR1DFA {
131+
nodes: lalr1_nodes,
132+
edges: lalr1_edges,
133+
}
134+
}
135+
}
136+
137+
impl<'a: 'b, 'b, T, R> Automaton<'a, 'b, T> for LALR1DFA<'a, T, R>
138+
where
139+
T: TokenTag,
140+
R: RuleTag<T>,
141+
{
142+
fn len(&self) -> usize {
143+
self.nodes.len()
144+
}
145+
146+
fn edges(&'b self) -> impl Iterator<Item = &'b (usize, usize, &'a RuleElem<T>)> {
147+
self.edges.iter()
148+
}
149+
}
150+
151+
#[derive(Debug)]
152+
struct LALR1DFAKey<'a, 'b, T, R> (Rc<RwLock<LR1DFANode<'a, 'b, T, R>>>)
153+
where
154+
T: TokenTag,
155+
R: RuleTag<T>;
156+
157+
impl<'a, 'b, T, R> PartialEq for LALR1DFAKey<'a, 'b, T, R>
158+
where
159+
T: TokenTag,
160+
R: RuleTag<T>,
161+
{
162+
fn eq(&self, other: &Self) -> bool {
163+
let self_node = self.0.read().unwrap();
164+
let other_node = other.0.read().unwrap();
165+
166+
if self_node.itemset.items.len() != other_node.itemset.items.len() {
167+
return false;
168+
}
169+
170+
'outer: for item in &self_node.itemset.items {
171+
for other_item in &other_node.itemset.items {
172+
if item.rule == other_item.rule && item.dot_pos == other_item.dot_pos {
173+
continue 'outer;
174+
}
175+
}
176+
return false;
177+
}
178+
179+
true
180+
}
181+
}
182+
183+
impl<'a, 'b, T, R> Eq for LALR1DFAKey<'a, 'b, T, R>
184+
where
185+
T: TokenTag,
186+
R: RuleTag<T>,
187+
{}
188+
189+
impl<'a, 'b, T, R> From<Rc<RwLock<LR1DFANode<'a, 'b, T, R>>>> for LALR1DFAKey<'a, 'b, T, R>
190+
where
191+
T: TokenTag,
192+
R: RuleTag<T>,
193+
{
194+
fn from(lr1_dfa_node: Rc<RwLock<LR1DFANode<'a, 'b, T, R>>>) -> Self {
195+
Self (lr1_dfa_node)
196+
}
197+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use std::fmt::{Display, Debug};
2+
use std::hash::Hash;
3+
4+
use copager_cfg::token::TokenTag;
5+
use copager_cfg::rule::{Rule, RuleElem, RuleTag};
6+
7+
#[derive(Clone, Hash, PartialEq, Eq)]
8+
pub struct LALR1Item<'a, T, R>
9+
where
10+
T: TokenTag,
11+
R: RuleTag<T>,
12+
{
13+
pub rule: &'a Rule<T, R>,
14+
pub dot_pos: usize,
15+
pub la_tokens: Vec<&'a RuleElem<T>>,
16+
}
17+
18+
impl<'a, T, R> Display for LALR1Item<'a, T, R>
19+
where
20+
T: TokenTag,
21+
R: RuleTag<T>,
22+
{
23+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24+
write!(f, "{} -> ", self.rule.lhs)?;
25+
for (i, elem) in self.rule.rhs.iter().enumerate() {
26+
if i == self.dot_pos {
27+
write!(f, "• ")?;
28+
}
29+
write!(f, "{} ", elem)?;
30+
}
31+
if self.dot_pos == self.rule.rhs.len() {
32+
write!(f, "•")?;
33+
}
34+
write!(f, "[{:?}]", self.la_tokens)
35+
}
36+
}
37+
38+
impl<'a, T, R> Debug for LALR1Item<'a, T, R>
39+
where
40+
T: TokenTag,
41+
R: RuleTag<T>,
42+
{
43+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44+
write!(f, "{}", self)
45+
}
46+
}
47+
48+
impl<'a, T, R> LALR1Item<'a, T, R>
49+
where
50+
T: TokenTag,
51+
R: RuleTag<T>,
52+
{
53+
pub fn new(rule: &'a Rule<T, R>, dot_pos: usize, la_tokens: Vec<&'a RuleElem<T>>) -> Self {
54+
LALR1Item { rule, dot_pos, la_tokens }
55+
}
56+
57+
pub fn check_next_elem(&self) -> Option<&'a RuleElem<T>> {
58+
if self.dot_pos < self.rule.rhs.len() {
59+
Some(&self.rule.rhs[self.dot_pos])
60+
} else {
61+
None
62+
}
63+
}
64+
}
65+
66+
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
67+
pub struct LALR1ItemSet<'a, T, R>
68+
where
69+
T: TokenTag,
70+
R: RuleTag<T>,
71+
{
72+
pub items: Vec<LALR1Item<'a, T, R>>,
73+
}
74+
75+
impl <'a, T, R> LALR1ItemSet<'a, T, R>
76+
where
77+
T: TokenTag,
78+
R: RuleTag<T>,
79+
{
80+
pub fn new(items: Vec<LALR1Item<'a, T, R>>) -> Self {
81+
LALR1ItemSet { items }
82+
}
83+
}

0 commit comments

Comments
 (0)