Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e41ea7a
[remove] LexIterator 削除
Yuta1004 May 17, 2024
4d2e4ed
[change] lex::Token の文字列情報の持ち方を変えた
Yuta1004 May 17, 2024
a227129
[fix] core, algorithm のインポート名を変更
Yuta1004 May 17, 2024
5a77edf
[update] Syntax, TokenSet が Debug を要求するようにした
Yuta1004 May 17, 2024
1f963cd
[update] ParseError の設計を変更 & pretty_print できるようにした
Yuta1004 May 17, 2024
b250277
[clean] TODO コメント削除
Yuta1004 May 17, 2024
18aaddb
Merge pull request #9 from Yuta1004/#4_RemoveLexIterator
Yuta1004 May 17, 2024
905ac08
[update] Syntax::into → Syntax::into_ruleset
Yuta1004 May 20, 2024
9c851f2
[change] Syntax の Sized 制約を削除
Yuta1004 May 20, 2024
75dd0c2
[change] Syntax トレイトが持つメソッドの命名を変更
Yuta1004 May 20, 2024
78d215b
[change] TokenSet が持つメソッドの命名を Syntax に合わせた
Yuta1004 May 20, 2024
d6b34e8
[update] 1つの列挙子に対して複数の #rule を指定できるようにした
Yuta1004 May 20, 2024
55fbc36
Merge pull request #12 from Tsukuba-Programming-Lab/#11_UpdateSyntaxT…
Yuta1004 May 20, 2024
b75dce3
[add] パース結果をS式で表現するようにした
Yuta1004 May 20, 2024
5580a9d
Merge pull request #13 from Tsukuba-Programming-Lab/#6_ImplSExp
Yuta1004 May 20, 2024
f73c26b
[update] README.md
Yuta1004 May 20, 2024
3a28831
[update] Cargo.toml (0.1.0 → 0.1.1)
Yuta1004 May 20, 2024
25eb22d
Merge pull request #15 from Tsukuba-Programming-Lab/#14_v0.1.1_Setup
Yuta1004 May 20, 2024
3aec6f9
[fix] README.md
Yuta1004 May 20, 2024
632cc62
Merge pull request #16 from Tsukuba-Programming-Lab/#14_v0.1.1_Setup
Yuta1004 May 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
[package]
name = "parsergen"
version = "0.1.0"
version = "0.1.1"
edition = "2021"

[dependencies]
anyhow = { workspace = true }
thiserror = { workspace = true }
core = { workspace = true }
algorithm = { workspace = true }
pgen_core = { workspace = true }
pgen_algorithm = { workspace = true }

[dev-dependencies]
serde = { workspace = true }
serde_json = "1.0.117"

[features]
default = []
derive = ["core/derive"]
derive = ["pgen_core/derive"]

[workspace]
resolver = "2"
Expand All @@ -31,5 +31,5 @@ thiserror = "1.0.58"
serde = "1.0.197"
regex = "1.10.4"
regex-macro = "0.2.0"
core = { path = "./crates/core" }
algorithm = { path = "./crates/algorithm" }
pgen_core = { package = "core", path = "./crates/core" }
pgen_algorithm = { package = "algorithm", path = "./crates/algorithm" }
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ Rust製パーサジェネレータ
```
$ cargo run --example expr
(10+20)/((30*40)-50)
Accepted
Accepted : (Expr (Term (Term (Num "(" (Expr (Expr (Term (Num "10"))) "+" (Term (Num "20"))) ")")) "/" (Num "(" (Expr (Expr (Term (Num "(" (Expr (Term (Term (Num "30")) "*" (Num "40"))) ")"))) "-" (Term (Num "50"))) ")")))

$ cargo run --example expr
10**
Rejected: Error at (0, 3)
-----
1: 10**
^ here
Error at line 1, column 4.
-----

Rejected : Unexpected token "Mul" found
```
2 changes: 1 addition & 1 deletion crates/algorithm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "algorithm"
version = "0.1.0"
version = "0.1.1"
edition = "2021"

[dependencies]
Expand Down
4 changes: 2 additions & 2 deletions crates/algorithm_lr1/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[package]
name = "algorithm_lr1"
version = "0.1.0"
version = "0.1.1"
edition = "2021"

[dependencies]
anyhow = { workspace = true }
thiserror = { workspace = true }
serde = { workspace = true, features = ["derive"] }
itertools = "0.12.1"
core = { path = "../core", features = ["derive"] }
pgen_core = { package = "core", path = "../core", features = ["derive"] }
16 changes: 6 additions & 10 deletions crates/algorithm_lr1/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::marker::PhantomData;
use serde::{Serialize, Deserialize};
use itertools::Itertools;

use core::cfg::{TokenSet, Syntax, Rule, RuleElem, RuleSet};
use pgen_core::cfg::{TokenSet, Syntax, Rule, RuleElem, RuleSet};

#[derive(Debug, Serialize, Deserialize)]
pub(super) enum LRAction<S> {
Expand Down Expand Up @@ -37,11 +37,8 @@ where
{
pub fn setup() -> anyhow::Result<Self> {
// 1. Pre-process
let rules = S::try_into()?
.into_iter()
.map(|(rule, _)| rule)
.collect::<Vec<_>>();
let ruleset = RuleSet::from(rules);
let rules = S::into_iter().collect::<Vec<_>>();
let ruleset = S::into_ruleset();
let first_set = ruleset.first_set();

// 2. Generate dummy nonterm
Expand Down Expand Up @@ -76,7 +73,7 @@ where
let mut goto_table: Vec<Vec<usize>> = Vec::with_capacity(dfa.0.len());
for _ in 0..dfa.0.len() {
action_table.push(HashMap::from_iter(
T::enum_iter()
T::into_iter()
.map(|token| (token, LRAction::None))
.collect::<Vec<(T, LRAction<S>)>>(),
));
Expand All @@ -85,7 +82,6 @@ where
}

// 5. Setup tables
let rule_table: Vec<S> = S::enum_iter().collect();
for lritem_set in &dfa.0 {
for (token, next) in &lritem_set.next {
match &token {
Expand Down Expand Up @@ -113,7 +109,7 @@ where
let id = lritem_set.id as usize;
let label = action_table[id].get_mut(&t.0).unwrap();
*label = LRAction::Reduce(
rule_table[item.rule.id as usize],
rules[item.rule.id as usize],
*nonterm_table.get(lhs).unwrap(),
item.rule.rhs.len(),
);
Expand All @@ -124,7 +120,7 @@ where
LRAction::Accept
} else {
LRAction::Reduce(
rule_table[item.rule.id as usize],
rules[item.rule.id as usize],
*nonterm_table.get(lhs).unwrap(),
item.rule.rhs.len(),
)
Expand Down
40 changes: 23 additions & 17 deletions crates/algorithm_lr1/src/driver.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use core::cfg::{TokenSet, Syntax};
use core::lex::LexIterator;
use pgen_core::cfg::{TokenSet, Syntax};
use pgen_core::lex::Token;
use pgen_core::parse::{SExp, SExpBuilder};

use super::builder::{LRAction, LR1Configure};
use crate::error::ParseError;
use crate::builder::{LRAction, LR1Configure};

pub(super) struct LR1Driver<'a, 'b, T, S> (&'b LR1Configure<'a, T, S>)
where
Expand All @@ -19,41 +21,45 @@ where

pub fn run<'c>(
&self,
lexer: &mut impl LexIterator<'a, 'c, T>,
) -> anyhow::Result<()> {
lexer: &mut impl Iterator<Item = Token<'a, 'c, T>>,
) -> anyhow::Result<SExp<'a, 'c, T, S>> {
let mut stack = vec![0];
let mut builder = SExpBuilder::new();
loop {
let input = lexer.next();
loop {
let top = stack[stack.len() - 1];
let action = match input {
Some(token) => (
self.0.action_table[top].get(&token.kind).unwrap(),
Some(token.as_str()),
Some(token),
),
None => (
&self.0.eof_action_table[top],
None
),
};
match action.0 {
LRAction::Shift(new_state) => {
match action {
(LRAction::Shift(new_state), Some(token)) => {
stack.push(*new_state);
builder.push(token);
break;
}
LRAction::Reduce(_, goto, elems_cnt) => {
(LRAction::Reduce(tag, goto, elems_cnt), _) => {
stack.truncate(stack.len() - elems_cnt);
stack.push(self.0.goto_table[stack[stack.len() - 1]][*goto]);
builder.wrap(*tag, *elems_cnt);
}
LRAction::None => {
let pos = lexer.pos();
let pos = match action.1 {
Some(raw) => (pos.0, pos.1 - (raw.len() as u32)),
None => pos,
};
return Err(anyhow::anyhow!("Error at {:?}", pos).into());
(LRAction::Accept, _) => {
return builder.build();
}
LRAction::Accept => return Ok(()),
(LRAction::None, Some(token)) => {
return Err(ParseError::new_unexpected_token(token).into());
}
(LRAction::None, None) => {
return Err(ParseError::UnexpectedEOF.into());
}
_ => unreachable!(),
}
}
}
Expand Down
27 changes: 27 additions & 0 deletions crates/algorithm_lr1/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use thiserror::Error;

use pgen_core::error::ParseError as SuperParseError;
use pgen_core::cfg::TokenSet;
use pgen_core::lex::Token;

#[derive(Debug, Error)]
pub enum ParseError {
#[error("Unexpected token {actual:?} found")]
UnexpectedToken {
actual: String,
},
#[error("Unexpected EOF")]
UnexpectedEOF,
}

impl ParseError {
pub fn new_unexpected_token<'a, T>(expected: Token<'a, '_, T>) -> SuperParseError
where
T: TokenSet<'a>,
{
let err = ParseError::UnexpectedToken {
actual: format!("{:?}", expected.kind),
};
SuperParseError::from(err).with(expected)
}
}
25 changes: 10 additions & 15 deletions crates/algorithm_lr1/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
mod error;
mod builder;
mod driver;

use serde::{Serialize, Deserialize};

use core::cfg::{TokenSet, Syntax};
use core::lex::LexIterator;
use core::parse::ParserImpl;
use pgen_core::cfg::{TokenSet, Syntax};
use pgen_core::lex::Token;
use pgen_core::parse::{ParserImpl, SExp};

use builder::LR1Configure;
use driver::LR1Driver;
Expand All @@ -23,24 +24,23 @@ where
{
type TokenSet = T;
type Syntax = S;
type Output = ();

fn setup() -> anyhow::Result<Self> {
Ok(LR1(LR1Configure::setup()?))
}

fn parse<'b>(
&self,
mut lexer: impl LexIterator<'a, 'b, T>,
) -> anyhow::Result<Self::Output> {
mut lexer: impl Iterator<Item = Token<'a, 'b, T>>,
) -> anyhow::Result<SExp<'a, 'b, T, S>> {
LR1Driver::new(&self.0).run(&mut lexer)
}
}

#[cfg(test)]
mod test {
use core::cfg::{TokenSet, Syntax, Rule, RuleElem};
use core::Parser;
use pgen_core::cfg::{TokenSet, Syntax, Rule, RuleElem};
use pgen_core::Parser;

use super::LR1;

Expand All @@ -67,19 +67,14 @@ mod test {
#[derive(Debug, Clone, Copy, Syntax)]
enum TestSyntax {
#[rule("<expr> ::= <expr> Plus <term>")]
ExprPlus,
#[rule("<expr> ::= <expr> Minus <term>")]
ExprMinus,
#[rule("<expr> ::= <term>")]
ExprTerm,
Expr,
#[rule("<term> ::= <term> Mul <num>")]
TermMul,
#[rule("<term> ::= <term> Div <num>")]
TermDiv,
#[rule("<term> ::= <num>")]
TermNum,
Term,
#[rule("<num> ::= BracketL <expr> BracketR")]
NestedNum,
#[rule("<num> ::= Num")]
Num,
}
Expand Down
6 changes: 3 additions & 3 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[package]
name = "core"
version = "0.1.0"
version = "0.1.1"
edition = "2021"

[dependencies]
anyhow = { workspace = true }
thiserror = { workspace = true }
serde = { workspace = true, features = ["derive"]}
regex = { workspace = true }
derive = { package = "core_derive", path = "../core_derive", optional = true }
pgen_core_derive = { package = "core_derive", path = "../core_derive", optional = true }

[features]
default = []
derive = ["dep:derive"]
derive = ["dep:pgen_core_derive"]
2 changes: 1 addition & 1 deletion crates/core/src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mod token;
mod syntax;

#[cfg(feature = "derive")]
pub use derive::{TokenSet, Syntax};
pub use pgen_core_derive::{TokenSet, Syntax};

pub use token::TokenSet;
pub use syntax::{Syntax, Rule, RuleElem, RuleSet};
Loading