Skip to content

Commit 619e02b

Browse files
committed
Add types and review readme
1 parent 597f0da commit 619e02b

File tree

5 files changed

+79
-67
lines changed

5 files changed

+79
-67
lines changed

README.md

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -190,45 +190,52 @@ the Rust compilation stage.
190190

191191
### V0
192192

193-
In the V0 the compilation is a direct style Parsec generation without any
194-
optimisations.
193+
In the V0 the transpilation is a direct style Parsec generation without any
194+
optimisations.
195195

196-
#### Abstract syntax tree
196+
### V1
197+
198+
This version target an aggressive and an efficient parser compilation. For this
199+
purpose the compilation follows a traditional control and data flow mainly inspired
200+
by the paper [A Typed, Algebraic Approach to Parsing](https://www.cl.cam.ac.uk/~jdy22/papers/a-typed-algebraic-approach-to-parsing.pdf)
201+
202+
#### Celma lang in Celma lang
197203

198204
```rust
199-
#[derive(Clone, Debug, Eq, PartialEq)]
200-
pub enum ASTParsec {
201-
PIdent(String),
202-
PChar(char),
203-
PString(String),
204-
PBind(String, Box<ASTParsec>),
205-
PMap(Box<ASTParsec>, String),
206-
PSequence(Box<ASTParsec>, Box<ASTParsec>),
207-
PChoice(Box<ASTParsec>, Box<ASTParsec>),
208-
PNot(Box<ASTParsec>),
209-
PTry(Box<ASTParsec>),
210-
PCheck(Box<ASTParsec>),
211-
POptional(Box<ASTParsec>),
212-
PRepeat(bool, Box<ASTParsec>),
213-
PLookahead(Box<ASTParsec>),
214-
}
205+
let skip:{()} = (' '|'\t'|'\n'|'\r')* -> {}
206+
let ident:{String} = (skip i=#(alpha (alpha|digit|'_')*) skip) -> { i.into_iter().collect() }
215207

216-
#[derive(Clone, Debug, Eq, PartialEq)]
217-
pub struct ASTParsecRule {
218-
pub name: String,
219-
pub input: String,
220-
pub returns: String,
221-
pub rule: Box<ASTParsec>,
222-
}
223-
```
208+
let kind:{String} = (skip '{' v=^'}'* '}' skip) -> { v.into_iter().collect() }
209+
let code:{String} = (skip '{' c=^'}'* '}' skip) -> { c.into_iter().collect() }
224210

225-
### V1
211+
let rules:{Vec<ASTParsecRule<char>>} = rule*
212+
let rule:{ASTParsecRule<char>} = (
213+
skip p="pub"? skip "let" skip n=ident i=kind? r=(':' _=kind)? '=' b=parsec skip
214+
) -> { mk_rule(p.is_some(), n, i, r, b) }
226215

227-
This version target an aggressive and an efficient parser compilation. For this
228-
purpose the compilation follows a traditional control ans data flow and was
229-
mainly inspired by the paper [A Typed, Algebraic Approach to Parsing](https://www.cl.cam.ac.uk/~jdy22/papers/a-typed-algebraic-approach-to-parsing.pdf)
216+
let parsec:{ASTParsec<char>} = (
217+
skip b=!(binding)? a=atom o=('?'|'*'|'+')? d=additional? t=transform? skip
218+
) -> { mk_ast_parsec(b, a, o, d, t) }
219+
220+
let binding:{String} = skip _=ident '=' skip
221+
let additional:{(bool,ASTParsec<char>)} = (skip c='|'? skip p=parsec) -> { (c.is_some(), p) }
230222

223+
let atom:{ASTParsec<char>} = (
224+
skip o=('^'|'!'|'#'|'/')? skip p=(atom_block|atom_ident|atom_char|atom_string|atom_code) skip
225+
) -> { mk_atom(o, p) }
231226

227+
let atom_block:{ASTParsec<char>} = '(' _=parsec ')'
228+
let atom_ident:{ASTParsec<char>} = c=ident -> { PIdent(c) }
229+
let atom_char:{ASTParsec<char>} = c=delimited_char -> { PAtom(c) }
230+
let atom_string:{ASTParsec<char>} = c=delimited_string -> { PAtoms(c.chars().collect()) }
231+
let atom_code:{ASTParsec<char>} = c=code -> { PCode(c) }
232+
233+
let transform:{String} = (skip "->" skip _=code)
234+
235+
// Main entries
236+
let celma_parsec:{ASTParsec<char>} = (_=parsec eos)
237+
let celma_parsec_rules:{Vec<ASTParsecRule<char>>} = (_=rules eos)
238+
```
232239

233240
# License
234241

lang/v0/ast/src/syntax.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,9 @@
1717
#[derive(Clone, Debug, Eq, PartialEq)]
1818
pub enum ASTParsec {
1919
PIdent(String),
20-
// Are these constructors required?
2120
PAtom(char),
2221
PAtoms(Vec<char>),
2322
PBind(String, Box<ASTParsec>),
24-
// --------------------------------
2523
PCode(String),
2624
PMap(Box<ASTParsec>, String),
2725
PSequence(Box<ASTParsec>, Box<ASTParsec>),

lang/v1/ast/src/syntax.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,29 @@
1414
* limitations under the License.
1515
*/
1616

17+
#[derive(Clone, Debug, Eq, PartialEq)]
18+
pub struct ASTParsecRule<I> {
19+
pub public: bool,
20+
pub name: String,
21+
pub input: ASTType,
22+
pub returns: ASTType,
23+
pub rule: ASTParsec<I>,
24+
}
25+
26+
#[derive(Clone, Debug, Eq, PartialEq)]
27+
pub enum ASTType {
28+
PUnit,
29+
PChar,
30+
PString,
31+
POther(String),
32+
}
33+
1734
#[derive(Clone, Debug, Eq, PartialEq)]
1835
pub enum ASTParsec<I> {
1936
PIdent(String),
20-
// Are these constructors required?
2137
PAtom(I),
2238
PAtoms(Vec<I>),
2339
PBind(String, Box<ASTParsec<I>>),
24-
// --------------------------------
2540
PCode(String),
2641
PMap(Box<ASTParsec<I>>, String),
2742
PSequence(Box<ASTParsec<I>>, Box<ASTParsec<I>>),
@@ -34,19 +49,8 @@ pub enum ASTParsec<I> {
3449
PLookahead(Box<ASTParsec<I>>),
3550
}
3651

37-
38-
3952
impl<I> ASTParsec<I> {
4053
pub fn wrap(self) -> Box<Self> {
4154
Box::new(self)
4255
}
4356
}
44-
45-
#[derive(Clone, Debug, Eq, PartialEq)]
46-
pub struct ASTParsecRule<I> {
47-
pub public: bool,
48-
pub name: String,
49-
pub input: String,
50-
pub returns: String,
51-
pub rule: ASTParsec<I>,
52-
}

lang/v1/parser/src/parser.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,28 @@
1717
use celma_v0_core::parser::core::eos;
1818
use celma_v0_core::parser::literal::{delimited_char, delimited_string};
1919

20+
use celma_v0_macro::parsec_rules;
2021
use celma_v1_ast::syntax::ASTParsec::{
2122
PAtom, PAtoms, PBind, PCheck, PChoice, PCode, PIdent, PLookahead, PMap, PNot, POptional,
2223
PRepeat, PSequence, PTry,
2324
};
2425
use celma_v1_ast::syntax::{ASTParsec, ASTParsecRule};
25-
use celma_v0_macro::parsec_rules;
2626

2727
use celma_v0_core::parser::char::{alpha, digit};
28+
use celma_v1_ast::syntax::ASTType::{PChar, POther, PUnit};
2829

2930
fn mk_rule(
3031
public: bool,
3132
name: String,
3233
input: Option<String>,
33-
returns: String,
34+
returns: Option<String>,
3435
body: ASTParsec<char>,
3536
) -> ASTParsecRule<char> {
3637
ASTParsecRule {
3738
public,
3839
name,
39-
input: input.unwrap_or(String::from("char")),
40-
returns,
40+
input: input.map_or_else(|| PChar, POther),
41+
returns: returns.map_or_else(|| PUnit, POther),
4142
rule: body,
4243
}
4344
}
@@ -98,7 +99,7 @@ parsec_rules!(
9899

99100
let rules:{Vec<ASTParsecRule<char>>} = rule*
100101
let rule:{ASTParsecRule<char>} = (
101-
skip p="pub"? skip "let" skip n=ident i=kind? ':' r=kind '=' b=parsec skip
102+
skip p="pub"? skip "let" skip n=ident i=kind? r=(':' _=kind)? '=' b=parsec skip
102103
) -> { mk_rule(p.is_some(), n, i, r, b) }
103104

104105
let parsec:{ASTParsec<char>} = (

lang/v1/parser/tests/parser_tests.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
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_ast::syntax::ASTParsec::{PAtom, PAtoms, PBind, PCheck, PChoice, PCode, PIdent, PLookahead, PNot, POptional, PSequence, PTry};
22-
use celma_v1_ast::syntax::ASTParsecRule;
23-
use celma_v1::parser::{
24-
atom_char, atom_code, atom_ident, atom_string, kind, parsec, rule,
21+
use celma_v1::parser::{atom_char, atom_code, atom_ident, atom_string, kind, parsec, rule};
22+
use celma_v1_ast::syntax::ASTParsec::{
23+
PAtom, PAtoms, PBind, PCheck, PChoice, PCode, PIdent, PLookahead, PNot, POptional,
24+
PSequence, PTry,
2525
};
26+
use celma_v1_ast::syntax::ASTParsecRule;
27+
use celma_v1_ast::syntax::ASTType::{PChar, PUnit};
2628

2729
#[test]
2830
fn should_parse_kind() {
@@ -187,9 +189,9 @@ mod parser_tests {
187189
response.fold(
188190
|v, _, _| v
189191
== PBind(
190-
String::from("a"),
191-
PTry(PIdent(String::from("entry")).wrap()).wrap()
192-
),
192+
String::from("a"),
193+
PTry(PIdent(String::from("entry")).wrap()).wrap()
194+
),
193195
|_, _| false
194196
),
195197
true
@@ -204,9 +206,9 @@ mod parser_tests {
204206
response.fold(
205207
|v, _, _| v
206208
== PBind(
207-
String::from("a"),
208-
PLookahead(PIdent(String::from("entry")).wrap()).wrap()
209-
),
209+
String::from("a"),
210+
PLookahead(PIdent(String::from("entry")).wrap()).wrap()
211+
),
210212
|_, _| false
211213
),
212214
true
@@ -215,16 +217,16 @@ mod parser_tests {
215217

216218
#[test]
217219
fn should_parse_protected_simple_rule() {
218-
let response = rule().parse(CharStream::new("let x:{()} = entry"));
220+
let response = rule().parse(CharStream::new("let x = entry"));
219221

220222
assert_eq!(
221223
response.fold(
222224
|v, _, _| v
223225
== ASTParsecRule::<char> {
224226
public: false,
225227
name: String::from("x"),
226-
input: String::from("char"),
227-
returns: String::from("()"),
228+
input: PChar,
229+
returns: PUnit,
228230
rule: PIdent(String::from("entry"))
229231
},
230232
|_, _| false
@@ -235,16 +237,16 @@ mod parser_tests {
235237

236238
#[test]
237239
fn should_parse_public_simple_rule() {
238-
let response = rule().parse(CharStream::new("pub let x:{()} = entry"));
240+
let response = rule().parse(CharStream::new("pub let x = entry"));
239241

240242
assert_eq!(
241243
response.fold(
242244
|v, _, _| v
243245
== ASTParsecRule::<char> {
244246
public: true,
245247
name: String::from("x"),
246-
input: String::from("char"),
247-
returns: String::from("()"),
248+
input: PChar,
249+
returns: PUnit,
248250
rule: PIdent(String::from("entry"))
249251
},
250252
|_, _| false

0 commit comments

Comments
 (0)