diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/parser/event_parser/grammar.rs | 52 | ||||
-rw-r--r-- | src/syntax_kinds.rs | 4 |
2 files changed, 46 insertions, 10 deletions
diff --git a/src/parser/event_parser/grammar.rs b/src/parser/event_parser/grammar.rs index 64c6718cb..acf27aec9 100644 --- a/src/parser/event_parser/grammar.rs +++ b/src/parser/event_parser/grammar.rs | |||
@@ -34,7 +34,7 @@ fn item(p: &mut Parser) { | |||
34 | 34 | ||
35 | fn struct_item(p: &mut Parser) { | 35 | fn struct_item(p: &mut Parser) { |
36 | p.expect(IDENT) | 36 | p.expect(IDENT) |
37 | && p.curly_block(|p| comma_list(p, struct_field)); | 37 | && p.curly_block(|p| comma_list(p, EOF, struct_field)); |
38 | } | 38 | } |
39 | 39 | ||
40 | fn struct_field(p: &mut Parser) -> bool { | 40 | fn struct_field(p: &mut Parser) -> bool { |
@@ -52,19 +52,45 @@ fn fn_item(p: &mut Parser) { | |||
52 | // Paths, types, attributes, and stuff // | 52 | // Paths, types, attributes, and stuff // |
53 | 53 | ||
54 | fn inner_attributes(p: &mut Parser) { | 54 | fn inner_attributes(p: &mut Parser) { |
55 | many(p, inner_attribute) | 55 | many(p, |p| attribute(p, true)) |
56 | } | 56 | } |
57 | 57 | ||
58 | fn inner_attribute(p: &mut Parser) -> bool { | 58 | fn attribute(p: &mut Parser, inner: bool) -> bool { |
59 | if !(p.lookahead(&[EXCL, POUND])) { | 59 | let attr_start = inner && p.lookahead(&[POUND, EXCL, L_BRACK]) |
60 | || !inner && p.lookahead(&[POUND, L_BRACK]); | ||
61 | if !attr_start { | ||
60 | return false; | 62 | return false; |
61 | } | 63 | } |
62 | node(p, ATTR, |p| { | 64 | node(p, ATTR, |p| { |
63 | p.bump_n(2); | 65 | p.bump_n(if inner { 3 } else { 2 }); |
66 | meta_item(p) && p.expect(R_BRACK); | ||
64 | }); | 67 | }); |
65 | true | 68 | true |
66 | } | 69 | } |
67 | 70 | ||
71 | fn meta_item(p: &mut Parser) -> bool { | ||
72 | node_if(p, IDENT, META_ITEM, |p| { | ||
73 | if p.eat(EQ) { | ||
74 | if !literal(p) { | ||
75 | p.error() | ||
76 | .message("expected literal") | ||
77 | .emit(); | ||
78 | } | ||
79 | } else if p.eat(L_PAREN) { | ||
80 | comma_list(p, R_PAREN, meta_item_inner); | ||
81 | p.expect(R_PAREN); | ||
82 | } | ||
83 | }) | ||
84 | } | ||
85 | |||
86 | fn meta_item_inner(p: &mut Parser) -> bool { | ||
87 | meta_item(p) || literal(p) | ||
88 | } | ||
89 | |||
90 | fn literal(p: &mut Parser) -> bool { | ||
91 | p.eat(INT_NUMBER) || p.eat(FLOAT_NUMBER) | ||
92 | } | ||
93 | |||
68 | fn outer_attributes(_: &mut Parser) { | 94 | fn outer_attributes(_: &mut Parser) { |
69 | } | 95 | } |
70 | 96 | ||
@@ -75,7 +101,12 @@ fn visibility(_: &mut Parser) { | |||
75 | 101 | ||
76 | // Error recovery and high-order utils // | 102 | // Error recovery and high-order utils // |
77 | 103 | ||
78 | fn node_if<F: FnOnce(&mut Parser)>(p: &mut Parser, first: SyntaxKind, node_kind: SyntaxKind, rest: F) -> bool { | 104 | fn node_if<F: FnOnce(&mut Parser)>( |
105 | p: &mut Parser, | ||
106 | first: SyntaxKind, | ||
107 | node_kind: SyntaxKind, | ||
108 | rest: F | ||
109 | ) -> bool { | ||
79 | p.current() == first && { node(p, node_kind, |p| { p.bump(); rest(p); }); true } | 110 | p.current() == first && { node(p, node_kind, |p| { p.bump(); rest(p); }); true } |
80 | } | 111 | } |
81 | 112 | ||
@@ -89,10 +120,9 @@ fn many<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) { | |||
89 | while f(p) { } | 120 | while f(p) { } |
90 | } | 121 | } |
91 | 122 | ||
92 | fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) { | 123 | fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, end: SyntaxKind, f: F) { |
93 | many(p, |p| { | 124 | many(p, |p| { |
94 | f(p); | 125 | if !f(p) || p.current() == end { |
95 | if p.current() == EOF { | ||
96 | false | 126 | false |
97 | } else { | 127 | } else { |
98 | p.expect(COMMA); | 128 | p.expect(COMMA); |
@@ -157,4 +187,8 @@ impl<'p> Parser<'p> { | |||
157 | self.bump(); | 187 | self.bump(); |
158 | } | 188 | } |
159 | } | 189 | } |
190 | |||
191 | fn eat(&mut self, kind: SyntaxKind) -> bool { | ||
192 | self.current() == kind && { self.bump(); true } | ||
193 | } | ||
160 | } \ No newline at end of file | 194 | } \ No newline at end of file |
diff --git a/src/syntax_kinds.rs b/src/syntax_kinds.rs index 67c840a3e..eea7819a3 100644 --- a/src/syntax_kinds.rs +++ b/src/syntax_kinds.rs | |||
@@ -63,8 +63,9 @@ pub const STRUCT_ITEM: SyntaxKind = SyntaxKind(58); | |||
63 | pub const STRUCT_FIELD: SyntaxKind = SyntaxKind(59); | 63 | pub const STRUCT_FIELD: SyntaxKind = SyntaxKind(59); |
64 | pub const FN_ITEM: SyntaxKind = SyntaxKind(60); | 64 | pub const FN_ITEM: SyntaxKind = SyntaxKind(60); |
65 | pub const ATTR: SyntaxKind = SyntaxKind(61); | 65 | pub const ATTR: SyntaxKind = SyntaxKind(61); |
66 | pub const META_ITEM: SyntaxKind = SyntaxKind(62); | ||
66 | 67 | ||
67 | static INFOS: [SyntaxInfo; 62] = [ | 68 | static INFOS: [SyntaxInfo; 63] = [ |
68 | SyntaxInfo { name: "USE_KW" }, | 69 | SyntaxInfo { name: "USE_KW" }, |
69 | SyntaxInfo { name: "FN_KW" }, | 70 | SyntaxInfo { name: "FN_KW" }, |
70 | SyntaxInfo { name: "STRUCT_KW" }, | 71 | SyntaxInfo { name: "STRUCT_KW" }, |
@@ -127,6 +128,7 @@ static INFOS: [SyntaxInfo; 62] = [ | |||
127 | SyntaxInfo { name: "STRUCT_FIELD" }, | 128 | SyntaxInfo { name: "STRUCT_FIELD" }, |
128 | SyntaxInfo { name: "FN_ITEM" }, | 129 | SyntaxInfo { name: "FN_ITEM" }, |
129 | SyntaxInfo { name: "ATTR" }, | 130 | SyntaxInfo { name: "ATTR" }, |
131 | SyntaxInfo { name: "META_ITEM" }, | ||
130 | ]; | 132 | ]; |
131 | 133 | ||
132 | pub(crate) fn syntax_info(kind: SyntaxKind) -> &'static SyntaxInfo { | 134 | pub(crate) fn syntax_info(kind: SyntaxKind) -> &'static SyntaxInfo { |