From 31a07da88dc9473a9f05617a98db6180e6e9e3c6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 6 Jan 2018 21:54:55 +0300 Subject: [PATCH] Boolean results --- src/parser/event_parser/grammar.rs | 123 +++++++++---------- src/parser/event_parser/parser.rs | 36 ++---- tests/data/parser/0002_struct_item_field.txt | 2 +- tests/parser.rs | 2 +- 4 files changed, 73 insertions(+), 90 deletions(-) diff --git a/src/parser/event_parser/grammar.rs b/src/parser/event_parser/grammar.rs index 77596fea6d..d09579881b 100644 --- a/src/parser/event_parser/grammar.rs +++ b/src/parser/event_parser/grammar.rs @@ -1,20 +1,17 @@ use super::parser::Parser; - +use {SyntaxKind}; use syntax_kinds::*; // Items // pub fn file(p: &mut Parser) { - p.start(FILE); - shebang(p); - inner_attributes(p); - mod_items(p); - p.finish(); + node(p, FILE, |p| { + shebang(p); + inner_attributes(p); + many(p, |p| skip_to_first(p, item_first, item)); + }) } -type Result = ::std::result::Result<(), ()>; -const OK: Result = Ok(()); -const ERR: Result = Err(()); fn shebang(_: &mut Parser) { //TODO @@ -24,88 +21,86 @@ fn inner_attributes(_: &mut Parser) { //TODO } -fn mod_items(p: &mut Parser) { - loop { - skip_until_item(p); - if p.is_eof() { - return; - } - if item(p).is_err() { - skip_one_token(p); - } +fn item_first(p: &Parser) -> bool { + match p.current() { + Some(STRUCT_KW) => true, + _ => false, } } -fn item(p: &mut Parser) -> Result { - outer_attributes(p)?; - visibility(p)?; - if p.current_is(STRUCT_KW) { - p.start(STRUCT_ITEM); - p.bump(); - let _ = struct_item(p); - p.finish(); - return OK; - } - ERR +fn item(p: &mut Parser) { + outer_attributes(p); + visibility(p); + node_if(p, STRUCT_KW, STRUCT_ITEM, struct_item); } -fn struct_item(p: &mut Parser) -> Result { - p.expect(IDENT)?; - p.curly_block(|p| { - comma_list(p, struct_field) +fn struct_item(p: &mut Parser) { + p.expect(IDENT) + && p.curly_block(|p| comma_list(p, struct_field)); +} + +fn struct_field(p: &mut Parser) -> bool { + node_if(p, IDENT, STRUCT_FIELD, |p| { + p.expect(COLON) && p.expect(IDENT); }) } -fn struct_field(p: &mut Parser) -> Result { - if !p.current_is(IDENT) { - return ERR; - } - p.start(STRUCT_FIELD); - p.bump(); - ignore_errors(|| { - p.expect(COLON)?; - p.expect(IDENT)?; - OK - }); - p.finish(); - OK -} - // Paths, types, attributes, and stuff // -fn outer_attributes(_: &mut Parser) -> Result { - OK +fn outer_attributes(_: &mut Parser) { } -fn visibility(_: &mut Parser) -> Result { - OK +fn visibility(_: &mut Parser) { } // Expressions // // Error recovery and high-order utils // -fn skip_until_item(_: &mut Parser) { - //TODO +fn node_if(p: &mut Parser, first: SyntaxKind, node_kind: SyntaxKind, rest: F) -> bool { + p.current_is(first) && { node(p, node_kind, |p| { p.bump(); rest(p); }); true } } -fn skip_one_token(p: &mut Parser) { - p.start(ERROR); - p.bump().unwrap(); +fn node(p: &mut Parser, node_kind: SyntaxKind, rest: F) { + p.start(node_kind); + rest(p); p.finish(); } -fn ignore_errors Result>(f: F) { - drop(f()); +fn many bool>(p: &mut Parser, f: F) { + while f(p) { } } -fn comma_list Result>(p: &mut Parser, element: F) { +fn comma_list bool>(p: &mut Parser, f: F) { + many(p, |p| { + f(p); + p.expect(COMMA) + }) +} + + +fn skip_to_first(p: &mut Parser, cond: C, f: F) -> bool +where + C: Fn(&Parser) -> bool, + F: FnOnce(&mut Parser), +{ loop { - if element(p).is_err() { - return + if cond(p) { + f(p); + return true; } - if p.expect(COMMA).is_err() { - return + if p.bump().is_none() { + return false; } } +} + +impl<'p> Parser<'p> { + fn current_is(&self, kind: SyntaxKind) -> bool { + self.current() == Some(kind) + } + + pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { + self.current_is(kind) && { self.bump(); true } + } } \ No newline at end of file diff --git a/src/parser/event_parser/parser.rs b/src/parser/event_parser/parser.rs index 04ef4fb284..07e3ccc236 100644 --- a/src/parser/event_parser/parser.rs +++ b/src/parser/event_parser/parser.rs @@ -60,10 +60,6 @@ impl<'t> Parser<'t> { Some(self.raw_tokens[idx].kind) } - pub(crate) fn current_is(&self, kind: SyntaxKind) -> bool { - self.current() == Some(kind) - } - pub(crate) fn bump(&mut self) -> Option { let kind = self.current()?; match kind { @@ -76,31 +72,23 @@ impl<'t> Parser<'t> { Some(kind) } - pub(crate) fn expect(&mut self, kind: SyntaxKind) -> Result<(), ()> { - if kind == self.current().ok_or(())? { - self.bump(); - Ok(()) - } else { - Err(()) - } - } - - pub(crate) fn curly_block(&mut self, f: F) -> Result<(), ()> { + pub(crate) fn curly_block(&mut self, f: F) -> bool { let level = self.curly_level; - self.expect(L_CURLY)?; + if !self.expect(L_CURLY) { + return false + } f(self); assert!(self.curly_level > level); - if self.expect(R_CURLY).is_ok() { - return Ok(()); - } - self.start(ERROR); - while self.curly_level > level { - if self.bump().is_none() { - break; + if !self.expect(R_CURLY) { + self.start(ERROR); + while self.curly_level > level { + if self.bump().is_none() { + break; + } } + self.finish(); } - self.finish(); - Ok(()) //??? + true } 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 b1673ade3e..87ab3f7a9b 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) WHITESPACE@[19; 20) IDENT@[20; 23) WHITESPACE@[23; 24) - R_CURLY@[24; 25) \ No newline at end of file + R_CURLY@[24; 25) diff --git a/tests/parser.rs b/tests/parser.rs index 5c63be3be1..6c31463ad3 100644 --- a/tests/parser.rs +++ b/tests/parser.rs @@ -49,7 +49,7 @@ fn parser_test_case(path: &Path) { return } if expected.trim() == actual.trim() { - panic!("Whitespace difference!") + panic!("Whitespace difference! {}", path.display()) } assert_diff!(expected, actual, "\n", 0) }