From 7bc974ab2c29f896a0d9ca952ad306a9ed38f6f2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 7 Jan 2018 21:40:18 +0300 Subject: G: some attributes --- src/parser/event_parser/grammar.rs | 52 +++++++++++++++++++++++++++++++------- src/syntax_kinds.rs | 4 ++- 2 files changed, 46 insertions(+), 10 deletions(-) (limited to 'src') 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) { fn struct_item(p: &mut Parser) { p.expect(IDENT) - && p.curly_block(|p| comma_list(p, struct_field)); + && p.curly_block(|p| comma_list(p, EOF, struct_field)); } fn struct_field(p: &mut Parser) -> bool { @@ -52,19 +52,45 @@ fn fn_item(p: &mut Parser) { // Paths, types, attributes, and stuff // fn inner_attributes(p: &mut Parser) { - many(p, inner_attribute) + many(p, |p| attribute(p, true)) } -fn inner_attribute(p: &mut Parser) -> bool { - if !(p.lookahead(&[EXCL, POUND])) { +fn attribute(p: &mut Parser, inner: bool) -> bool { + let attr_start = inner && p.lookahead(&[POUND, EXCL, L_BRACK]) + || !inner && p.lookahead(&[POUND, L_BRACK]); + if !attr_start { return false; } node(p, ATTR, |p| { - p.bump_n(2); + p.bump_n(if inner { 3 } else { 2 }); + meta_item(p) && p.expect(R_BRACK); }); true } +fn meta_item(p: &mut Parser) -> bool { + node_if(p, IDENT, META_ITEM, |p| { + if p.eat(EQ) { + if !literal(p) { + p.error() + .message("expected literal") + .emit(); + } + } else if p.eat(L_PAREN) { + comma_list(p, R_PAREN, meta_item_inner); + p.expect(R_PAREN); + } + }) +} + +fn meta_item_inner(p: &mut Parser) -> bool { + meta_item(p) || literal(p) +} + +fn literal(p: &mut Parser) -> bool { + p.eat(INT_NUMBER) || p.eat(FLOAT_NUMBER) +} + fn outer_attributes(_: &mut Parser) { } @@ -75,7 +101,12 @@ fn visibility(_: &mut Parser) { // Error recovery and high-order utils // -fn node_if(p: &mut Parser, first: SyntaxKind, node_kind: SyntaxKind, rest: F) -> bool { +fn node_if( + p: &mut Parser, + first: SyntaxKind, + node_kind: SyntaxKind, + rest: F +) -> bool { p.current() == first && { node(p, node_kind, |p| { p.bump(); rest(p); }); true } } @@ -89,10 +120,9 @@ fn many bool>(p: &mut Parser, f: F) { while f(p) { } } -fn comma_list bool>(p: &mut Parser, f: F) { +fn comma_list bool>(p: &mut Parser, end: SyntaxKind, f: F) { many(p, |p| { - f(p); - if p.current() == EOF { + if !f(p) || p.current() == end { false } else { p.expect(COMMA); @@ -157,4 +187,8 @@ impl<'p> Parser<'p> { self.bump(); } } + + fn eat(&mut self, kind: SyntaxKind) -> bool { + self.current() == kind && { self.bump(); true } + } } \ 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); pub const STRUCT_FIELD: SyntaxKind = SyntaxKind(59); pub const FN_ITEM: SyntaxKind = SyntaxKind(60); pub const ATTR: SyntaxKind = SyntaxKind(61); +pub const META_ITEM: SyntaxKind = SyntaxKind(62); -static INFOS: [SyntaxInfo; 62] = [ +static INFOS: [SyntaxInfo; 63] = [ SyntaxInfo { name: "USE_KW" }, SyntaxInfo { name: "FN_KW" }, SyntaxInfo { name: "STRUCT_KW" }, @@ -127,6 +128,7 @@ static INFOS: [SyntaxInfo; 62] = [ SyntaxInfo { name: "STRUCT_FIELD" }, SyntaxInfo { name: "FN_ITEM" }, SyntaxInfo { name: "ATTR" }, + SyntaxInfo { name: "META_ITEM" }, ]; pub(crate) fn syntax_info(kind: SyntaxKind) -> &'static SyntaxInfo { -- cgit v1.2.3