Skip to content

Commit 9697446

Browse files
committed
Review celma lang grammar
1 parent 619e02b commit 9697446

File tree

9 files changed

+107
-44
lines changed

9 files changed

+107
-44
lines changed

README.md

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Generalization is the capability to design a parser based on pipelined parsers a
1616
In order to have a seamless parser definition two dedicated `proc_macro` are designed:
1717

1818
```rust
19-
parsec_rules = "let" ident ('{' rust_type '}')? ':' '{' rust_type '}' "=" parser)+
19+
parsec_rules = "pub"? "let" ident ('{' rust_type '}')? (':' '{' rust_type '}')? "=" parser)+
2020
parser = binding? atom occurrence? additional? transform?
2121
```
2222

@@ -113,11 +113,11 @@ parsec_rules!(
113113

114114
```rust
115115
parsec_rules!(
116-
let STRING:{String} = delimited_string
117-
let NUMBER:{f64} = c=#(INT ('.' NAT)? (('E'|'e') INT)?) -> {mk_f64(c)}
118-
let INT:{()} = ('-'|'+')? NAT -> {}
119-
let NAT:{()} = digit+ -> {}
120-
let S:{()} = space* -> {}
116+
let STRING:{String} = delimited_string
117+
let NUMBER:{f64} = c=#(INT ('.' NAT)? (('E'|'e') INT)?) -> {mk_f64(c)}
118+
let INT = ('-'|'+')? NAT -> {}
119+
let NAT = digit+ -> {}
120+
let S = space* -> {}
121121
);
122122
```
123123

@@ -136,7 +136,7 @@ parsec_rules!(
136136
let token:{Token} = S _=(int|keyword) S
137137
let int:{Token} = c=!(#(('-'|'+')? digit+)) -> {Token::Int(mk_i64(c))}
138138
let keyword:{Token} = s=('+'|'*'|'('|')') -> {Token::Keyword(s)}
139-
let S:{()} = space* -> {}
139+
let S = space* -> {}
140140
);
141141
```
142142

@@ -146,10 +146,10 @@ The Lexeme parser recognizes simple token keywords.
146146

147147
```rust
148148
parsec_rules!(
149-
let PLUS{Token}:{()} = {kwd('+')} -> {}
150-
let MULT{Token}:{()} = {kwd('*')} -> {}
151-
let LPAREN{Token}:{()} = {kwd('(')} -> {}
152-
let RPAREN{Token}:{()} = {kwd(')')} -> {}
149+
let PLUS{Token} = {kwd('+')} -> {}
150+
let MULT{Token} = {kwd('*')} -> {}
151+
let LPAREN{Token} = {kwd('(')} -> {}
152+
let RPAREN{Token} = {kwd(')')} -> {}
153153
);
154154
```
155155

@@ -202,11 +202,19 @@ by the paper [A Typed, Algebraic Approach to Parsing](https://www.cl.cam.ac.uk/~
202202
#### Celma lang in Celma lang
203203

204204
```rust
205-
let skip:{()} = (' '|'\t'|'\n'|'\r')* -> {}
205+
let skip = (' '|'\t'|'\n'|'\r')* -> {}
206206
let ident:{String} = (skip i=#(alpha (alpha|digit|'_')*) skip) -> { i.into_iter().collect() }
207207

208-
let kind:{String} = (skip '{' v=^'}'* '}' skip) -> { v.into_iter().collect() }
209-
let code:{String} = (skip '{' c=^'}'* '}' skip) -> { c.into_iter().collect() }
208+
let rkind = (/'>' -> {})
209+
| (^('<'|'>')+ rkind -> {})
210+
| ('<' rkind '>' rkind -> {})
211+
212+
let rcode = (/'}' -> {})
213+
| (^('}'|'{')+ rcode -> {})
214+
| ('{' rcode '}' rcode -> {})
215+
216+
let kind:{String} = (skip '<' c=#rkind '>' skip) -> { c.into_iter().collect() }
217+
let code:{String} = (skip '{' c=#rcode '}' skip) -> { c.into_iter().collect() }
210218

211219
let rules:{Vec<ASTParsecRule<char>>} = rule*
212220
let rule:{ASTParsecRule<char>} = (

genlex/src/parser.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ where
4545
}
4646

4747
parsec_rules!(
48-
let INT:{()} = ('-'|'+')? NAT -> {}
49-
let NAT:{()} = digit+ -> {}
50-
let SPACES:{()} = space* -> {}
48+
let INT = ('-'|'+')? NAT -> {}
49+
let NAT = digit+ -> {}
50+
let SPACES = space* -> {}
5151
);
5252

5353
parsec_rules!(

lang/v0/macro/benches/json.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ parsec_rules!(
7373
parsec_rules!(
7474
let STRING:{String} = delimited_string
7575
let NUMBER:{f64} = c=#(INT ('.' NAT)? (('E'|'e') INT)?) -> {mk_f64(c)}
76-
let INT:{()} = ('-'|'+')? NAT -> {}
77-
let NAT:{()} = digit+ -> {}
78-
let S:{()} = space* -> {}
76+
let INT = ('-'|'+')? NAT -> {}
77+
let NAT = digit+ -> {}
78+
let S = space* -> {}
7979
);
8080

8181
// -------------------------------------------------------------------------------------------------

lang/v0/macro/tests/expression.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ mod tests_transpiler {
7373

7474
parsec_rules!(
7575
let NUMBER:{f64} = c=#(INT ('.' NAT)? (('E'|'e') INT)?) -> {mk_f64(c)}
76-
let INT:{()} = ('-'|'+')? NAT -> {}
77-
let NAT:{()} = digit+ -> {}
78-
let S:{()} = space* -> {}
76+
let INT = ('-'|'+')? NAT -> {}
77+
let NAT = digit+ -> {}
78+
let S = space* -> {}
7979
);
8080

8181
#[test]

lang/v0/macro/tests/pipeline.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ mod tests_transpiler {
123123
let keyword{char}:{Token} = s=('+'|'*'|'('|')') -> { Token::Keyword(s) }
124124

125125
let INT{char}:{i64} = c=#(('-'|'+')? NAT) -> { mk_string(c).parse().unwrap() }
126-
let NAT{char}:{()} = digit+ -> {}
127-
let S{char}:{()} = space* -> {}
126+
let NAT{char} = digit+ -> {}
127+
let S{char} = space* -> {}
128128
);
129129

130130
// ---------------------------------------------------------------------------------------------
@@ -133,10 +133,10 @@ mod tests_transpiler {
133133

134134
// Lexemes
135135
parsec_rules!(
136-
let PLUS{Token}:{()} = {kwd('+')} -> {}
137-
let MULT{Token}:{()} = {kwd('*')} -> {}
138-
let LPAREN{Token}:{()} = {kwd('(')} -> {}
139-
let RPAREN{Token}:{()} = {kwd(')')} -> {}
136+
let PLUS{Token} = {kwd('+')} -> {}
137+
let MULT{Token} = {kwd('*')} -> {}
138+
let LPAREN{Token} = {kwd('(')} -> {}
139+
let RPAREN{Token} = {kwd(')')} -> {}
140140
);
141141

142142
// Parser

lang/v0/macro/tests/transpiler_rules.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ mod tests_transpiler {
100100
#[test]
101101
fn it_parse_with_recursive_parser() {
102102
parsec_rules!(
103-
let parens:{()} = ('(' parens ')')? -> { () }
103+
let parens = ('(' parens ')')? -> { () }
104104
);
105105

106106
let response = parens()

lang/v0/parser/src/parser.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,20 @@ where
8686
.and_left(skip())
8787
.and(kind().opt())
8888
.and_left(skip())
89-
.and_left(a_char(':'))
90-
.and_left(skip())
91-
.and(kind())
89+
.and(a_char(':').and_right(skip()).and_right(kind()).opt())
9290
.and_left(skip())
9391
.and_left(string("="))
9492
.and_left(skip())
9593
.and(parsec())
9694
.and_left(skip())
9795
.map(
98-
|(((n, i), r), b): (((String, Option<String>), String), ASTParsec)| ASTParsecRule {
99-
name: n,
100-
input: i.unwrap_or(String::from("char")),
101-
returns: r,
102-
rule: b,
96+
|(((n, i), r), b): (((String, Option<String>), Option<String>), ASTParsec)| {
97+
ASTParsecRule {
98+
name: n,
99+
input: i.unwrap_or(String::from("char")),
100+
returns: r.unwrap_or(String::from("()")),
101+
rule: b,
102+
}
103103
},
104104
)
105105
.rep()

lang/v1/parser/src/parser.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,19 @@ fn mk_atom(operation: Option<char>, parsec: ASTParsec<char>) -> ASTParsec<char>
9191
}
9292

9393
parsec_rules!(
94-
let skip:{()} = (' '|'\t'|'\n'|'\r')* -> {}
94+
let skip = (' '|'\t'|'\n'|'\r')* -> {}
9595
let ident:{String} = (skip i=#(alpha (alpha|digit|'_')*) skip) -> { i.into_iter().collect() }
9696

97-
let kind:{String} = (skip '{' v=^'}'* '}' skip) -> { v.into_iter().collect() }
98-
let code:{String} = (skip '{' c=^'}'* '}' skip) -> { c.into_iter().collect() }
97+
let rkind = (/'>' -> {})
98+
| (^('<'|'>')+ rkind -> {})
99+
| ('<' rkind '>' rkind -> {})
100+
101+
let rcode = (/'}' -> {})
102+
| (^('}'|'{')+ rcode -> {})
103+
| ('{' rcode '}' rcode -> {})
104+
105+
let kind:{String} = (skip '<' c=#rkind '>' skip) -> { c.into_iter().collect() }
106+
let code:{String} = (skip '{' c=#rcode '}' skip) -> { c.into_iter().collect() }
99107

100108
let rules:{Vec<ASTParsecRule<char>>} = rule*
101109
let rule:{ASTParsecRule<char>} = (

lang/v1/parser/tests/parser_tests.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
mod parser_tests {
1919
use celma_v0_core::parser::specs::Parse;
2020
use celma_v0_core::stream::char_stream::CharStream;
21-
use celma_v1::parser::{atom_char, atom_code, atom_ident, atom_string, kind, parsec, rule};
21+
use celma_v0_core::stream::specs::Len;
22+
use celma_v1::parser::{
23+
atom_char, atom_code, atom_ident, atom_string, code, kind, rcode, parsec, rule,
24+
};
2225
use celma_v1_ast::syntax::ASTParsec::{
2326
PAtom, PAtoms, PBind, PCheck, PChoice, PCode, PIdent, PLookahead, PNot, POptional,
2427
PSequence, PTry,
@@ -28,9 +31,9 @@ mod parser_tests {
2831

2932
#[test]
3033
fn should_parse_kind() {
31-
let response = kind().parse(CharStream::new("{hello()}"));
34+
let response = kind().parse(CharStream::new("<hello>"));
3235

33-
assert_eq!(response.fold(|v, _, _| v == "hello()", |_, _| false), true);
36+
assert_eq!(response.fold(|v, _, _| v == "hello", |_, _| false), true);
3437
}
3538

3639
#[test]
@@ -73,6 +76,50 @@ mod parser_tests {
7376
);
7477
}
7578

79+
#[test]
80+
fn should_parse_ident_empty_rcode() {
81+
let response = rcode().parse(CharStream::new("}"));
82+
83+
assert_eq!(response.fold(|_, s, _| s.len() == 1, |_, _| false), true);
84+
}
85+
86+
#[test]
87+
fn should_parse_ident_body_with_block_rcode() {
88+
let response = rcode().parse(CharStream::new("tutu { titi } toto }"));
89+
90+
assert_eq!(response.fold(|_, s, _| s.len() == 1, |_, _| false), true);
91+
}
92+
93+
#[test]
94+
fn should_parse_ident_body_with_block_unbalanced_rcode() {
95+
let response = rcode().parse(CharStream::new("{ titi }"));
96+
97+
assert_eq!(response.fold(|_, _, _| false, |_, _| true), true);
98+
}
99+
100+
#[test]
101+
fn should_parse_ident_body_code() {
102+
let response = code().parse(CharStream::new("{ titi }"));
103+
104+
assert_eq!(
105+
response.fold(|v, _, _| v == String::from(" titi "), |_, _| false),
106+
true
107+
);
108+
}
109+
110+
#[test]
111+
fn should_parse_ident_body_code_with_block() {
112+
let response = code().parse(CharStream::new("{ {titi} }"));
113+
114+
assert_eq!(
115+
response.fold(
116+
|v, s, _| v == String::from(" {titi} ") && s.is_empty(),
117+
|_, _| false
118+
),
119+
true
120+
);
121+
}
122+
76123
#[test]
77124
fn should_parse_ident_body() {
78125
let response = parsec().parse(CharStream::new("entry"));

0 commit comments

Comments
 (0)