From 7bc974ab2c29f896a0d9ca952ad306a9ed38f6f2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 7 Jan 2018 21:40:18 +0300 Subject: [PATCH] G: some attributes --- grammar.ron | 1 + src/parser/event_parser/grammar.rs | 52 ++++++++++++++--- src/syntax_kinds.rs | 4 +- .../data/parser/ok/0006_inner_attributes.txt | 58 ++++++++++++------- 4 files changed, 83 insertions(+), 32 deletions(-) diff --git a/grammar.ron b/grammar.ron index 39cb0a5431..e3b450d2be 100644 --- a/grammar.ron +++ b/grammar.ron @@ -66,5 +66,6 @@ Grammar( "STRUCT_FIELD", "FN_ITEM", "ATTR", + "META_ITEM", ] ) \ No newline at end of file diff --git a/src/parser/event_parser/grammar.rs b/src/parser/event_parser/grammar.rs index 64c6718cb4..acf27aec94 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 67c840a3e1..eea7819a36 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 { diff --git a/tests/data/parser/ok/0006_inner_attributes.txt b/tests/data/parser/ok/0006_inner_attributes.txt index c837979d10..a19d2f49c0 100644 --- a/tests/data/parser/ok/0006_inner_attributes.txt +++ b/tests/data/parser/ok/0006_inner_attributes.txt @@ -1,44 +1,58 @@ FILE@[0; 236) - ERROR@[0; 236) - err: `expected item` + ATTR@[0; 9) POUND@[0; 1) EXCL@[1; 2) L_BRACK@[2; 3) - IDENT@[3; 7) + META_ITEM@[3; 7) + IDENT@[3; 7) R_BRACK@[7; 8) WHITESPACE@[8; 9) + ATTR@[9; 24) POUND@[9; 10) EXCL@[10; 11) L_BRACK@[11; 12) - IDENT@[12; 16) - L_PAREN@[16; 17) - IDENT@[17; 21) - R_PAREN@[21; 22) + META_ITEM@[12; 22) + IDENT@[12; 16) + L_PAREN@[16; 17) + META_ITEM@[17; 21) + IDENT@[17; 21) + R_PAREN@[21; 22) R_BRACK@[22; 23) WHITESPACE@[23; 24) + ATTR@[24; 40) POUND@[24; 25) EXCL@[25; 26) L_BRACK@[26; 27) - IDENT@[27; 31) - L_PAREN@[31; 32) - IDENT@[32; 37) - R_PAREN@[37; 38) + META_ITEM@[27; 38) + IDENT@[27; 31) + L_PAREN@[31; 32) + META_ITEM@[32; 37) + IDENT@[32; 37) + R_PAREN@[37; 38) R_BRACK@[38; 39) WHITESPACE@[39; 40) + ATTR@[40; 66) POUND@[40; 41) EXCL@[41; 42) L_BRACK@[42; 43) - IDENT@[43; 47) - L_PAREN@[47; 48) - IDENT@[48; 53) - COMMA@[53; 54) - WHITESPACE@[54; 55) - INT_NUMBER@[55; 58) - COMMA@[58; 59) - WHITESPACE@[59; 60) - IDENT@[60; 64) - COMMA@[64; 65) - WHITESPACE@[65; 66) + META_ITEM@[43; 66) + IDENT@[43; 47) + L_PAREN@[47; 48) + META_ITEM@[48; 53) + IDENT@[48; 53) + COMMA@[53; 54) + WHITESPACE@[54; 55) + INT_NUMBER@[55; 58) + COMMA@[58; 59) + META_ITEM@[59; 64) + WHITESPACE@[59; 60) + IDENT@[60; 64) + COMMA@[64; 65) + err: `expected R_PAREN` + WHITESPACE@[65; 66) + err: `expected R_BRACK` + ERROR@[66; 236) + err: `expected item` STRING@[66; 72) COMMA@[72; 73) WHITESPACE@[73; 74)