Skip to content

Commit

Permalink
remove Terminal type PartialOrd, Ord trait bound to use `std::mem…
Browse files Browse the repository at this point in the history
…::discriminant`

    (parser) use discriminant instead of enum_index
    (all) cargo clippy
  • Loading branch information
ehwan committed Aug 11, 2024
1 parent 47f3986 commit bd9fb6e
Show file tree
Hide file tree
Showing 16 changed files with 524 additions and 618 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ yacc-like LR(1) and LALR(1) Deterministic Finite Automata (DFA) generator from C

```
[dependencies]
rusty_lr = "1.4.0"
rusty_lr = "1.5.0"
```

## Features
Expand Down
4 changes: 2 additions & 2 deletions rusty_lr/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rusty_lr"
version = "1.4.0"
version = "1.5.0"
edition = "2021"
license = "MIT"
description = "yacc-like, proc-macro based LR(1) and LALR(1) parser generator and code generation"
Expand All @@ -10,7 +10,7 @@ keywords = ["parser", "yacc", "context-free-grammar", "lr", "compiler"]
categories = ["parsing"]

[dependencies]
rusty_lr_core = "1.2"
rusty_lr_core = "1.3"
rusty_lr_derive = "1.2"
# rusty_lr_core = { path = "../rusty_lr_core" }
# rusty_lr_derive = { path = "../rusty_lr_derive" }
Expand Down
2 changes: 1 addition & 1 deletion rusty_lr_core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rusty_lr_core"
version = "1.2.0"
version = "1.3.0"
edition = "2021"
license = "MIT"
description = "yacc-like, proc-macro based LR(1) and LALR(1) parser generator and code generation"
Expand Down
13 changes: 8 additions & 5 deletions rusty_lr_core/src/grammar/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ impl<Term, NonTerm> Grammar<Term, NonTerm> {
NonTerm: Clone + Hash + Eq,
{
let id = self.rules.len();
self.rules_map
.entry(name.clone())
.or_insert_with(Vec::new)
.push(id);
self.rules_map.entry(name.clone()).or_default().push(id);
let rule = ProductionRule { name, rule };
self.rules.push(rule);
id
Expand Down Expand Up @@ -502,7 +499,7 @@ impl<Term, NonTerm> Grammar<Term, NonTerm> {
states[new_state_id]
.ruleset
.rules
.insert(shifted_rule.clone(), BTreeSet::new());
.insert(*shifted_rule, BTreeSet::new());
}
new_state_id
});
Expand Down Expand Up @@ -676,3 +673,9 @@ impl<Term: Display, NonTerm: Display> Display for Grammar<Term, NonTerm> {
Ok(())
}
}

impl<Term, NonTerm> Default for Grammar<Term, NonTerm> {
fn default() -> Self {
Self::new()
}
}
6 changes: 6 additions & 0 deletions rusty_lr_core/src/parser/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ impl Context {
}
}
}

impl Default for Context {
fn default() -> Self {
Self::new()
}
}
117 changes: 53 additions & 64 deletions rusty_lr_core/src/parser/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::fmt::Debug;
use std::fmt::Display;
use std::hash::Hash;

use crate::rule::ShiftedRule;
use crate::rule::ShiftedRuleRef2;
use crate::state::State;
use crate::ProductionRule;
use crate::ShiftedRuleRef;
Expand Down Expand Up @@ -48,75 +48,64 @@ impl<'a, Term, NonTerm, CallbackError, ReduceActionError>
state_stack: &[usize],
) -> Vec<BTreeSet<ShiftedRuleRef>>
where
NonTerm: Eq,
NonTerm: PartialEq,
{
let mut backtrace = Vec::with_capacity(state_stack.len());

// if it is on first state, print all rules
if state_stack.len() == 1 {
backtrace.push(states[0].ruleset.rules.keys().copied().collect());
return backtrace;
} else {
let state = &states[*state_stack.last().unwrap()];
let mut cur_rules = BTreeSet::new();
for (rule, _) in state.ruleset.rules.iter() {
if rule.shifted > 0 {
cur_rules.insert(*rule);
}
}
for prev_state in state_stack.iter().rev().skip(1) {
backtrace.push(cur_rules.clone());
let state = &states[*state_stack.last().unwrap()];
let mut cur_rules: BTreeSet<ShiftedRuleRef> = state.ruleset.rules.keys().copied().collect();
for prev_state in state_stack.iter().rev().skip(1) {
backtrace.push(cur_rules.clone());

// prepare for next iteration
let mut prev_rules = BTreeSet::new();
for mut r in cur_rules.into_iter() {
match r.shifted {
0 => {}
// prepare for next iteration
let mut prev_rules = BTreeSet::new();
for mut r in cur_rules.into_iter() {
match r.shifted {
0 => {}

_ => {
r.shifted -= 1;
prev_rules.insert(r);
}
_ => {
r.shifted -= 1;
prev_rules.insert(r);
}
}
}

loop {
let mut add_rules = BTreeSet::new();
for r in prev_rules.iter() {
// this rule's shift == 0,
// it must be added by other rule start with this rule's non-terminal
if r.shifted == 0 {
let rule_name = &rules[r.rule].name;
for (rule, _) in states[*prev_state].ruleset.rules.iter() {
if let Some(Token::NonTerm(next_token)) =
rules[rule.rule].rule.get(rule.shifted)
{
if next_token == rule_name {
add_rules.insert(*rule);
}
loop {
let mut add_rules = BTreeSet::new();
for r in prev_rules.iter() {
// this rule's shift == 0,
// it must be added by other rule start with this rule's non-terminal
if r.shifted == 0 {
let rule_name = &rules[r.rule].name;
for (rule, _) in states[*prev_state].ruleset.rules.iter() {
if let Some(Token::NonTerm(next_token)) =
rules[rule.rule].rule.get(rule.shifted)
{
if next_token == rule_name {
add_rules.insert(*rule);
}
}
}
}
let len0 = prev_rules.len();
prev_rules.append(&mut add_rules);
if prev_rules.len() == len0 {
break;
}
}

cur_rules = prev_rules;
let len0 = prev_rules.len();
prev_rules.append(&mut add_rules);
if prev_rules.len() == len0 {
break;
}
}
backtrace.push(cur_rules);
backtrace

cur_rules = prev_rules;
}
backtrace.push(cur_rules);
backtrace
}
}

impl<
'a,
Term: Display + Clone + Ord + Hash + Eq,
NonTerm: Display + Clone + Eq,
Term: Display + Hash + Eq,
NonTerm: Display + PartialEq,
CallbackError: Display,
ReduceActionError: Display,
> Display for ParseError<'a, Term, NonTerm, CallbackError, ReduceActionError>
Expand All @@ -129,7 +118,7 @@ impl<
writeln!(f, "Invalid NonTerminal: {}", nonterm)?;
let state = &states[*state_stack.last().unwrap()];

let expected: BTreeSet<Term> = state.expected().into_iter().collect();
let expected = state.expected();
if expected.is_empty() {
writeln!(f, "No expected token")?;
} else {
Expand All @@ -153,8 +142,8 @@ impl<
writeln!(f, "{:-^80}", "Prev state")?;
}
for rule in ruleset.iter() {
let shifted = ShiftedRule {
rule: rules[rule.rule].clone(),
let shifted = ShiftedRuleRef2 {
rule: &rules[rule.rule],
shifted: rule.shifted,
};
writeln!(f, "{}", shifted)?;
Expand All @@ -165,7 +154,7 @@ impl<
writeln!(f, "Invalid Terminal: {}", term,)?;
let state = &states[*state_stack.last().unwrap()];

let expected: BTreeSet<Term> = state.expected().into_iter().collect();
let expected = state.expected();
if expected.is_empty() {
writeln!(f, "No expected token")?;
} else {
Expand All @@ -189,8 +178,8 @@ impl<
writeln!(f, "{:-^80}", "Prev state")?;
}
for rule in ruleset.iter() {
let shifted = ShiftedRule {
rule: rules[rule.rule].clone(),
let shifted = ShiftedRuleRef2 {
rule: &rules[rule.rule],
shifted: rule.shifted,
};
writeln!(f, "{}", shifted)?;
Expand All @@ -209,8 +198,8 @@ impl<
}
impl<
'a,
Term: Debug + Clone + Ord + Hash + Eq,
NonTerm: Debug + Clone + Eq,
Term: Debug + Hash + Eq,
NonTerm: Debug + PartialEq,
CallbackError: Debug,
ReduceActionError: Debug,
> Debug for ParseError<'a, Term, NonTerm, CallbackError, ReduceActionError>
Expand All @@ -223,7 +212,7 @@ impl<
writeln!(f, "Invalid NonTerminal: {:?}", nonterm)?;
let state = &states[*state_stack.last().unwrap()];

let expected: BTreeSet<Term> = state.expected().into_iter().collect();
let expected = state.expected();
if expected.is_empty() {
writeln!(f, "No expected token")?;
} else {
Expand All @@ -247,8 +236,8 @@ impl<
writeln!(f, "{:-^80}", "Prev state")?;
}
for rule in ruleset.iter() {
let shifted = ShiftedRule {
rule: rules[rule.rule].clone(),
let shifted = ShiftedRuleRef2 {
rule: &rules[rule.rule],
shifted: rule.shifted,
};
writeln!(f, "{:?}", shifted)?;
Expand All @@ -259,7 +248,7 @@ impl<
writeln!(f, "Invalid Terminal: {:?}", term,)?;
let state = &states[*state_stack.last().unwrap()];

let expected: BTreeSet<Term> = state.expected().into_iter().collect();
let expected = state.expected();
if expected.is_empty() {
writeln!(f, "No expected token")?;
} else {
Expand All @@ -283,8 +272,8 @@ impl<
writeln!(f, "{:-^80}", "Prev state")?;
}
for rule in ruleset.iter() {
let shifted = ShiftedRule {
rule: rules[rule.rule].clone(),
let shifted = ShiftedRuleRef2 {
rule: &rules[rule.rule],
shifted: rule.shifted,
};
writeln!(f, "{:?}", shifted)?;
Expand Down
43 changes: 43 additions & 0 deletions rusty_lr_core/src/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,49 @@ pub struct ShiftedRuleRef {
/// name -> Token1 Token2 . Token3
///
/// ^^^^^^^^^^^^^ shifted = 2
/// This struct is only for Display purpose.
#[derive(Clone)]
pub(crate) struct ShiftedRuleRef2<'a, Term, NonTerm> {
pub rule: &'a ProductionRule<Term, NonTerm>,
pub shifted: usize,
}
impl<'a, Term: Display, NonTerm: Display> Display for ShiftedRuleRef2<'a, Term, NonTerm> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} -> ", self.rule.name)?;
for (id, token) in self.rule.rule.iter().enumerate() {
if id == self.shifted {
write!(f, "• ")?;
}
write!(f, "{}", token)?;
if id < self.rule.rule.len() - 1 {
write!(f, " ")?;
}
}
if self.shifted == self.rule.rule.len() {
write!(f, " •")?;
}
Ok(())
}
}
impl<'a, Term: Debug, NonTerm: Debug> Debug for ShiftedRuleRef2<'a, Term, NonTerm> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?} -> ", self.rule.name)?;
for (id, token) in self.rule.rule.iter().enumerate() {
if id == self.shifted {
write!(f, "• ")?;
}
write!(f, "{:?}", token)?;
if id < self.rule.rule.len() - 1 {
write!(f, " ")?;
}
}
if self.shifted == self.rule.rule.len() {
write!(f, " •")?;
}
Ok(())
}
}

#[derive(Clone)]
pub struct ShiftedRule<Term, NonTerm> {
pub rule: ProductionRule<Term, NonTerm>,
Expand Down
13 changes: 9 additions & 4 deletions rusty_lr_core/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,14 @@ impl<Term, NonTerm> State<Term, NonTerm> {
}

/// get expected terms set
pub fn expected(&self) -> HashSet<Term>
pub fn expected<'a>(&'a self) -> HashSet<&Term>
where
Term: Clone + Hash + Eq,
Term: Hash + Eq,
{
HashSet::from_iter(
self.shift_goto_map_term
.keys()
.chain(self.reduce_map.keys())
.cloned(),
.chain(self.reduce_map.keys()),
)
}
}
Expand All @@ -82,3 +81,9 @@ impl<Term: Display, NonTerm: Display> Display for State<Term, NonTerm> {
Ok(())
}
}

impl<Term, NonTerm> Default for State<Term, NonTerm> {
fn default() -> Self {
Self::new()
}
}
4 changes: 2 additions & 2 deletions rusty_lr_executable/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rustylr"
version = "0.3.0"
version = "0.3.1"
edition = "2021"
license = "MIT"
description = "LR(1), LALR(1) parser code generation with rusty_lr"
Expand All @@ -16,4 +16,4 @@ clap = { version = "4.5.7", features = ["derive"] }
# rusty_lr_parser = { path = "../rusty_lr_parser" }
rusty_lr_parser = "2.1"
# rusty_lr_core = { path = "../rusty_lr_core", features = ["fxhash"] }
rusty_lr_core = { version = "1.2", features = ["fxhash"] }
rusty_lr_core = { version = "1.3", features = ["fxhash"] }
Loading

0 comments on commit bd9fb6e

Please sign in to comment.