From 316432856808c238a57508810d05d4fec5231821 Mon Sep 17 00:00:00 2001 From: Schrottkatze Date: Wed, 23 Oct 2024 10:52:44 +0200 Subject: [PATCH] implement multiple members, member_values and trailing commata --- crates/json-pawarser/src/grammar.rs | 21 +++++++++++++++++-- crates/json-pawarser/src/lib.rs | 26 ------------------------ crates/json-pawarser/src/syntax_error.rs | 2 ++ crates/json-pawarser/src/syntax_kind.rs | 3 +++ 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/crates/json-pawarser/src/grammar.rs b/crates/json-pawarser/src/grammar.rs index 466f22c..b7afe02 100644 --- a/crates/json-pawarser/src/grammar.rs +++ b/crates/json-pawarser/src/grammar.rs @@ -33,9 +33,23 @@ mod object { } member(p); + while p.at(SyntaxKind::COMMA) { + // not always an error, later configurable + let potential_unexpected_comma = p.start("potential_unexpected_comma"); + p.eat(SyntaxKind::COMMA); - p.eat(SyntaxKind::BRACE_CLOSE); - Some(obj_start.complete(p, SyntaxKind::OBJECT)) + if member(p).is_none() { + potential_unexpected_comma.complete(p, SyntaxKind::TRAILING_COMMA); + } else { + potential_unexpected_comma.abandon(p); + } + } + + Some(if !p.eat(SyntaxKind::BRACE_CLOSE) { + obj_start.error(p, SyntaxError::UnclosedObject) + } else { + obj_start.complete(p, SyntaxKind::OBJECT) + }) } fn member(p: &mut Parser) -> Option { @@ -56,9 +70,12 @@ mod object { todo!("handle wrong tokens") } + let member_value_start = p.start("member_value_start"); if value(p) { + member_value_start.complete(p, SyntaxKind::MEMBER_VALUE); Some(member_start.complete(p, SyntaxKind::MEMBER)) } else { + member_value_start.abandon(p); let e = member_start.error(p, SyntaxError::MemberMissingValue); Some( e.precede(p, "member but failed already") diff --git a/crates/json-pawarser/src/lib.rs b/crates/json-pawarser/src/lib.rs index 05c529e..89160be 100644 --- a/crates/json-pawarser/src/lib.rs +++ b/crates/json-pawarser/src/lib.rs @@ -1,29 +1,3 @@ mod grammar; mod syntax_error; mod syntax_kind; - -#[cfg(test)] -mod test { - use pawarser::parser::ParserBuilder; - - use crate::{ - grammar::{value, Parser}, - syntax_kind::{lex, SyntaxKind}, - }; - - #[test] - fn test() { - const TEST_DATA: &str = r#"{"hello_world": "meow"}"#; - let toks = lex(TEST_DATA); - - let mut p: Parser = ParserBuilder::new(toks) - .add_meaningless(SyntaxKind::WHITESPACE) - .add_meaningless(SyntaxKind::NEWLINE) - .build(); - - value(&mut p); - - let out = p.finish(); - assert_eq!("", format!("{:#?}", out)) - } -} diff --git a/crates/json-pawarser/src/syntax_error.rs b/crates/json-pawarser/src/syntax_error.rs index 45bb5bd..b607be1 100644 --- a/crates/json-pawarser/src/syntax_error.rs +++ b/crates/json-pawarser/src/syntax_error.rs @@ -2,7 +2,9 @@ use crate::syntax_kind::SyntaxKind; #[derive(Debug, Clone, PartialEq, Eq)] pub enum SyntaxError { + UnclosedObject, DisallowedKeyType(SyntaxKind), MemberMissingValue, + UnexpectedTrailingComma, } impl pawarser::parser::SyntaxError for SyntaxError {} diff --git a/crates/json-pawarser/src/syntax_kind.rs b/crates/json-pawarser/src/syntax_kind.rs index dfaab13..8713b2d 100644 --- a/crates/json-pawarser/src/syntax_kind.rs +++ b/crates/json-pawarser/src/syntax_kind.rs @@ -24,6 +24,9 @@ pub enum SyntaxKind { ARRAY, ELEMENT, + // SyntaxKinds for future json5/etc support + TRAILING_COMMA, + // Tokens // Regexes adapted from [the logos handbook](https://logos.maciej.codes/examples/json_borrowed.html) #[token("true")]