diff options
-rw-r--r-- | src/parser/event_parser/grammar.rs | 121 | ||||
-rw-r--r-- | src/parser/event_parser/parser.rs | 36 | ||||
-rw-r--r-- | tests/data/parser/0002_struct_item_field.txt | 2 | ||||
-rw-r--r-- | tests/parser.rs | 2 |
4 files changed, 72 insertions, 89 deletions
diff --git a/src/parser/event_parser/grammar.rs b/src/parser/event_parser/grammar.rs index 77596fea6..d09579881 100644 --- a/src/parser/event_parser/grammar.rs +++ b/src/parser/event_parser/grammar.rs | |||
@@ -1,20 +1,17 @@ | |||
1 | use super::parser::Parser; | 1 | use super::parser::Parser; |
2 | 2 | use {SyntaxKind}; | |
3 | use syntax_kinds::*; | 3 | use syntax_kinds::*; |
4 | 4 | ||
5 | // Items // | 5 | // Items // |
6 | 6 | ||
7 | pub fn file(p: &mut Parser) { | 7 | pub fn file(p: &mut Parser) { |
8 | p.start(FILE); | 8 | node(p, FILE, |p| { |
9 | shebang(p); | 9 | shebang(p); |
10 | inner_attributes(p); | 10 | inner_attributes(p); |
11 | mod_items(p); | 11 | many(p, |p| skip_to_first(p, item_first, item)); |
12 | p.finish(); | 12 | }) |
13 | } | 13 | } |
14 | 14 | ||
15 | type Result = ::std::result::Result<(), ()>; | ||
16 | const OK: Result = Ok(()); | ||
17 | const ERR: Result = Err(()); | ||
18 | 15 | ||
19 | fn shebang(_: &mut Parser) { | 16 | fn shebang(_: &mut Parser) { |
20 | //TODO | 17 | //TODO |
@@ -24,88 +21,86 @@ fn inner_attributes(_: &mut Parser) { | |||
24 | //TODO | 21 | //TODO |
25 | } | 22 | } |
26 | 23 | ||
27 | fn mod_items(p: &mut Parser) { | 24 | fn item_first(p: &Parser) -> bool { |
28 | loop { | 25 | match p.current() { |
29 | skip_until_item(p); | 26 | Some(STRUCT_KW) => true, |
30 | if p.is_eof() { | 27 | _ => false, |
31 | return; | ||
32 | } | ||
33 | if item(p).is_err() { | ||
34 | skip_one_token(p); | ||
35 | } | ||
36 | } | 28 | } |
37 | } | 29 | } |
38 | 30 | ||
39 | fn item(p: &mut Parser) -> Result { | 31 | fn item(p: &mut Parser) { |
40 | outer_attributes(p)?; | 32 | outer_attributes(p); |
41 | visibility(p)?; | 33 | visibility(p); |
42 | if p.current_is(STRUCT_KW) { | 34 | node_if(p, STRUCT_KW, STRUCT_ITEM, struct_item); |
43 | p.start(STRUCT_ITEM); | ||
44 | p.bump(); | ||
45 | let _ = struct_item(p); | ||
46 | p.finish(); | ||
47 | return OK; | ||
48 | } | ||
49 | ERR | ||
50 | } | 35 | } |
51 | 36 | ||
52 | fn struct_item(p: &mut Parser) -> Result { | 37 | fn struct_item(p: &mut Parser) { |
53 | p.expect(IDENT)?; | 38 | p.expect(IDENT) |
54 | p.curly_block(|p| { | 39 | && p.curly_block(|p| comma_list(p, struct_field)); |
55 | comma_list(p, struct_field) | ||
56 | }) | ||
57 | } | 40 | } |
58 | 41 | ||
59 | fn struct_field(p: &mut Parser) -> Result { | 42 | fn struct_field(p: &mut Parser) -> bool { |
60 | if !p.current_is(IDENT) { | 43 | node_if(p, IDENT, STRUCT_FIELD, |p| { |
61 | return ERR; | 44 | p.expect(COLON) && p.expect(IDENT); |
62 | } | 45 | }) |
63 | p.start(STRUCT_FIELD); | ||
64 | p.bump(); | ||
65 | ignore_errors(|| { | ||
66 | p.expect(COLON)?; | ||
67 | p.expect(IDENT)?; | ||
68 | OK | ||
69 | }); | ||
70 | p.finish(); | ||
71 | OK | ||
72 | } | 46 | } |
73 | 47 | ||
74 | // Paths, types, attributes, and stuff // | 48 | // Paths, types, attributes, and stuff // |
75 | 49 | ||
76 | fn outer_attributes(_: &mut Parser) -> Result { | 50 | fn outer_attributes(_: &mut Parser) { |
77 | OK | ||
78 | } | 51 | } |
79 | 52 | ||
80 | fn visibility(_: &mut Parser) -> Result { | 53 | fn visibility(_: &mut Parser) { |
81 | OK | ||
82 | } | 54 | } |
83 | 55 | ||
84 | // Expressions // | 56 | // Expressions // |
85 | 57 | ||
86 | // Error recovery and high-order utils // | 58 | // Error recovery and high-order utils // |
87 | 59 | ||
88 | fn skip_until_item(_: &mut Parser) { | 60 | fn node_if<F: FnOnce(&mut Parser)>(p: &mut Parser, first: SyntaxKind, node_kind: SyntaxKind, rest: F) -> bool { |
89 | //TODO | 61 | p.current_is(first) && { node(p, node_kind, |p| { p.bump(); rest(p); }); true } |
90 | } | 62 | } |
91 | 63 | ||
92 | fn skip_one_token(p: &mut Parser) { | 64 | fn node<F: FnOnce(&mut Parser)>(p: &mut Parser, node_kind: SyntaxKind, rest: F) { |
93 | p.start(ERROR); | 65 | p.start(node_kind); |
94 | p.bump().unwrap(); | 66 | rest(p); |
95 | p.finish(); | 67 | p.finish(); |
96 | } | 68 | } |
97 | 69 | ||
98 | fn ignore_errors<F: FnOnce() -> Result>(f: F) { | 70 | fn many<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) { |
99 | drop(f()); | 71 | while f(p) { } |
100 | } | 72 | } |
101 | 73 | ||
102 | fn comma_list<F: Fn(&mut Parser) -> Result>(p: &mut Parser, element: F) { | 74 | fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) { |
75 | many(p, |p| { | ||
76 | f(p); | ||
77 | p.expect(COMMA) | ||
78 | }) | ||
79 | } | ||
80 | |||
81 | |||
82 | fn skip_to_first<C, F>(p: &mut Parser, cond: C, f: F) -> bool | ||
83 | where | ||
84 | C: Fn(&Parser) -> bool, | ||
85 | F: FnOnce(&mut Parser), | ||
86 | { | ||
103 | loop { | 87 | loop { |
104 | if element(p).is_err() { | 88 | if cond(p) { |
105 | return | 89 | f(p); |
90 | return true; | ||
106 | } | 91 | } |
107 | if p.expect(COMMA).is_err() { | 92 | if p.bump().is_none() { |
108 | return | 93 | return false; |
109 | } | 94 | } |
110 | } | 95 | } |
96 | } | ||
97 | |||
98 | impl<'p> Parser<'p> { | ||
99 | fn current_is(&self, kind: SyntaxKind) -> bool { | ||
100 | self.current() == Some(kind) | ||
101 | } | ||
102 | |||
103 | pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { | ||
104 | self.current_is(kind) && { self.bump(); true } | ||
105 | } | ||
111 | } \ No newline at end of file | 106 | } \ No newline at end of file |
diff --git a/src/parser/event_parser/parser.rs b/src/parser/event_parser/parser.rs index 04ef4fb28..07e3ccc23 100644 --- a/src/parser/event_parser/parser.rs +++ b/src/parser/event_parser/parser.rs | |||
@@ -60,10 +60,6 @@ impl<'t> Parser<'t> { | |||
60 | Some(self.raw_tokens[idx].kind) | 60 | Some(self.raw_tokens[idx].kind) |
61 | } | 61 | } |
62 | 62 | ||
63 | pub(crate) fn current_is(&self, kind: SyntaxKind) -> bool { | ||
64 | self.current() == Some(kind) | ||
65 | } | ||
66 | |||
67 | pub(crate) fn bump(&mut self) -> Option<SyntaxKind> { | 63 | pub(crate) fn bump(&mut self) -> Option<SyntaxKind> { |
68 | let kind = self.current()?; | 64 | let kind = self.current()?; |
69 | match kind { | 65 | match kind { |
@@ -76,31 +72,23 @@ impl<'t> Parser<'t> { | |||
76 | Some(kind) | 72 | Some(kind) |
77 | } | 73 | } |
78 | 74 | ||
79 | pub(crate) fn expect(&mut self, kind: SyntaxKind) -> Result<(), ()> { | 75 | pub(crate) fn curly_block<F: FnOnce(&mut Parser)>(&mut self, f: F) -> bool { |
80 | if kind == self.current().ok_or(())? { | ||
81 | self.bump(); | ||
82 | Ok(()) | ||
83 | } else { | ||
84 | Err(()) | ||
85 | } | ||
86 | } | ||
87 | |||
88 | pub(crate) fn curly_block<F: FnOnce(&mut Parser)>(&mut self, f: F) -> Result<(), ()> { | ||
89 | let level = self.curly_level; | 76 | let level = self.curly_level; |
90 | self.expect(L_CURLY)?; | 77 | if !self.expect(L_CURLY) { |
78 | return false | ||
79 | } | ||
91 | f(self); | 80 | f(self); |
92 | assert!(self.curly_level > level); | 81 | assert!(self.curly_level > level); |
93 | if self.expect(R_CURLY).is_ok() { | 82 | if !self.expect(R_CURLY) { |
94 | return Ok(()); | 83 | self.start(ERROR); |
95 | } | 84 | while self.curly_level > level { |
96 | self.start(ERROR); | 85 | if self.bump().is_none() { |
97 | while self.curly_level > level { | 86 | break; |
98 | if self.bump().is_none() { | 87 | } |
99 | break; | ||
100 | } | 88 | } |
89 | self.finish(); | ||
101 | } | 90 | } |
102 | self.finish(); | 91 | true |
103 | Ok(()) //??? | ||
104 | } | 92 | } |
105 | 93 | ||
106 | fn event(&mut self, event: Event) { | 94 | fn event(&mut self, event: Event) { |
diff --git a/tests/data/parser/0002_struct_item_field.txt b/tests/data/parser/0002_struct_item_field.txt index b1673ade3..87ab3f7a9 100644 --- a/tests/data/parser/0002_struct_item_field.txt +++ b/tests/data/parser/0002_struct_item_field.txt | |||
@@ -12,4 +12,4 @@ FILE@[0; 25) | |||
12 | WHITESPACE@[19; 20) | 12 | WHITESPACE@[19; 20) |
13 | IDENT@[20; 23) | 13 | IDENT@[20; 23) |
14 | WHITESPACE@[23; 24) | 14 | WHITESPACE@[23; 24) |
15 | R_CURLY@[24; 25) \ No newline at end of file | 15 | R_CURLY@[24; 25) |
diff --git a/tests/parser.rs b/tests/parser.rs index 5c63be3be..6c31463ad 100644 --- a/tests/parser.rs +++ b/tests/parser.rs | |||
@@ -49,7 +49,7 @@ fn parser_test_case(path: &Path) { | |||
49 | return | 49 | return |
50 | } | 50 | } |
51 | if expected.trim() == actual.trim() { | 51 | if expected.trim() == actual.trim() { |
52 | panic!("Whitespace difference!") | 52 | panic!("Whitespace difference! {}", path.display()) |
53 | } | 53 | } |
54 | assert_diff!(expected, actual, "\n", 0) | 54 | assert_diff!(expected, actual, "\n", 0) |
55 | } | 55 | } |