Skip to content

Commit 5580a9d

Browse files
authored
Merge pull request #13 from Tsukuba-Programming-Lab/#6_ImplSExp
#6 パース結果をS式で受け取れるようにした
2 parents 55fbc36 + b75dce3 commit 5580a9d

File tree

5 files changed

+88
-12
lines changed

5 files changed

+88
-12
lines changed

crates/algorithm_lr1/src/driver.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use pgen_core::cfg::{TokenSet, Syntax};
22
use pgen_core::lex::Token;
3+
use pgen_core::parse::{SExp, SExpBuilder};
34

45
use crate::error::ParseError;
56
use crate::builder::{LRAction, LR1Configure};
@@ -21,8 +22,9 @@ where
2122
pub fn run<'c>(
2223
&self,
2324
lexer: &mut impl Iterator<Item = Token<'a, 'c, T>>,
24-
) -> anyhow::Result<()> {
25+
) -> anyhow::Result<SExp<'a, 'c, T, S>> {
2526
let mut stack = vec![0];
27+
let mut builder = SExpBuilder::new();
2628
loop {
2729
let input = lexer.next();
2830
loop {
@@ -38,23 +40,26 @@ where
3840
),
3941
};
4042
match action {
41-
(LRAction::Shift(new_state), _) => {
43+
(LRAction::Shift(new_state), Some(token)) => {
4244
stack.push(*new_state);
45+
builder.push(token);
4346
break;
4447
}
45-
(LRAction::Reduce(_, goto, elems_cnt), _) => {
48+
(LRAction::Reduce(tag, goto, elems_cnt), _) => {
4649
stack.truncate(stack.len() - elems_cnt);
4750
stack.push(self.0.goto_table[stack[stack.len() - 1]][*goto]);
51+
builder.wrap(*tag, *elems_cnt);
4852
}
4953
(LRAction::Accept, _) => {
50-
return Ok(());
54+
return builder.build();
5155
}
5256
(LRAction::None, Some(token)) => {
5357
return Err(ParseError::new_unexpected_token(token).into());
5458
}
5559
(LRAction::None, None) => {
5660
return Err(ParseError::UnexpectedEOF.into());
5761
}
62+
_ => unreachable!(),
5863
}
5964
}
6065
}

crates/algorithm_lr1/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use serde::{Serialize, Deserialize};
66

77
use pgen_core::cfg::{TokenSet, Syntax};
88
use pgen_core::lex::Token;
9-
use pgen_core::parse::ParserImpl;
9+
use pgen_core::parse::{ParserImpl, SExp};
1010

1111
use builder::LR1Configure;
1212
use driver::LR1Driver;
@@ -24,7 +24,6 @@ where
2424
{
2525
type TokenSet = T;
2626
type Syntax = S;
27-
type Output = ();
2827

2928
fn setup() -> anyhow::Result<Self> {
3029
Ok(LR1(LR1Configure::setup()?))
@@ -33,7 +32,7 @@ where
3332
fn parse<'b>(
3433
&self,
3534
mut lexer: impl Iterator<Item = Token<'a, 'b, T>>,
36-
) -> anyhow::Result<Self::Output> {
35+
) -> anyhow::Result<SExp<'a, 'b, T, S>> {
3736
LR1Driver::new(&self.0).run(&mut lexer)
3837
}
3938
}

crates/core/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::marker::PhantomData;
88
use serde::{Serialize, Deserialize};
99

1010
use lex::Lexer;
11-
use parse::ParserImpl;
11+
use parse::{ParserImpl, SExp};
1212

1313
#[derive(Debug, Serialize, Deserialize)]
1414
pub struct Parser<'a, Algorithm>
@@ -31,7 +31,10 @@ where
3131
})
3232
}
3333

34-
pub fn parse<'b>(&self, input: &'b str) -> anyhow::Result<Algorithm::Output> {
34+
pub fn parse<'b>(
35+
&self,
36+
input: &'b str,
37+
) -> anyhow::Result<SExp<'a, 'b, Algorithm::TokenSet, Algorithm::Syntax>> {
3538
let lexer = Lexer::new::<Algorithm::TokenSet>(input)?;
3639
self.r#impl.parse(lexer)
3740
}

crates/core/src/parse.rs

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::fmt::{Display, Debug};
2+
13
use crate::cfg::{TokenSet, Syntax};
24
use crate::lex::Token;
35

@@ -7,11 +9,78 @@ where
79
{
810
type TokenSet: TokenSet<'a> + 'a;
911
type Syntax: Syntax<'a, TokenSet = Self::TokenSet>;
10-
type Output;
1112

1213
fn setup() -> anyhow::Result<Self>;
1314
fn parse<'b>(
1415
&self,
1516
lexer: impl Iterator<Item = Token<'a, 'b, Self::TokenSet>>,
16-
) -> anyhow::Result<Self::Output>;
17+
) -> anyhow::Result<SExp<'a, 'b, Self::TokenSet, Self::Syntax>>;
18+
}
19+
20+
#[derive(Debug)]
21+
pub enum SExp<'a, 'b, T, S>
22+
where
23+
T: TokenSet<'a> + 'a,
24+
S: Syntax<'a, TokenSet = T>,
25+
{
26+
List {
27+
tag: S,
28+
elems: Vec<SExp<'a, 'b, T, S>>,
29+
},
30+
Atom(Token<'a, 'b, T>),
31+
}
32+
33+
impl<'a, T, S> Display for SExp<'a, '_, T, S>
34+
where
35+
T: TokenSet<'a> + 'a,
36+
S: Syntax<'a, TokenSet = T> + Debug,
37+
{
38+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39+
match self {
40+
SExp::List { tag, elems } => {
41+
write!(f, "({:?}", tag)?;
42+
for elem in elems {
43+
write!(f, " {}", elem)?;
44+
}
45+
write!(f, ")")
46+
}
47+
SExp::Atom(token) => write!(f, "{:?}", token.as_str()),
48+
}
49+
}
50+
}
51+
52+
#[derive(Debug)]
53+
pub struct SExpBuilder<'a, 'b, T, S>
54+
where
55+
T: TokenSet<'a> + 'a,
56+
S: Syntax<'a, TokenSet = T>,
57+
{
58+
stack: Vec<SExp<'a, 'b, T, S>>,
59+
}
60+
61+
impl<'a, 'b, T, S> SExpBuilder<'a, 'b, T, S>
62+
where
63+
T: TokenSet<'a> + 'a,
64+
S: Syntax<'a, TokenSet = T>,
65+
{
66+
pub fn new() -> SExpBuilder<'a, 'b, T, S> {
67+
SExpBuilder { stack: vec![] }
68+
}
69+
70+
pub fn push(&mut self, token: Token<'a, 'b, T>) {
71+
self.stack.push(SExp::Atom(token));
72+
}
73+
74+
pub fn wrap(&mut self, tag: S, cnt: usize) {
75+
let elems = self.stack.split_off(self.stack.len() - cnt);
76+
self.stack.push(SExp::List { tag, elems });
77+
}
78+
79+
pub fn build(mut self) -> anyhow::Result<SExp<'a, 'b, T, S>> {
80+
if self.stack.len() == 1 {
81+
Ok(self.stack.pop().unwrap())
82+
} else {
83+
Err(anyhow::anyhow!("Invalid S-Expression"))
84+
}
85+
}
1786
}

examples/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn main() -> anyhow::Result<()> {
4747
stdin().read_line(&mut input)?;
4848

4949
match ExprParser::new()?.parse(&input) {
50-
Ok(_) => println!("Accepted"),
50+
Ok(sexp) => println!("Accepted : {}", sexp),
5151
Err(e) => {
5252
if let Some(e) = e.downcast_ref::<ParseError>() {
5353
e.pretty_print();

0 commit comments

Comments
 (0)