diff --git a/crates/json-pawarser/src/grammar.rs b/crates/json-pawarser/src/grammar.rs index 36a707e..67af0f3 100644 --- a/crates/json-pawarser/src/grammar.rs +++ b/crates/json-pawarser/src/grammar.rs @@ -1,10 +1,17 @@ use array::array; use enumset::{enum_set, EnumSet}; +use pawarser::parser::ParserBuilder; -use crate::{syntax_error::SyntaxError, syntax_kind::SyntaxKind}; +use crate::{ + syntax_error::SyntaxError, + syntax_kind::{lex, SyntaxKind}, +}; use self::object::object; +mod array; +mod object; + pub(crate) type Parser<'src> = pawarser::Parser<'src, SyntaxKind, SyntaxError>; pub(crate) type CompletedMarker = pawarser::CompletedMarker; @@ -20,5 +27,52 @@ pub fn value(p: &mut Parser) -> bool { } } -mod array; -mod object; +#[cfg(test)] +mod tests { + use super::{ + test_utils::{check_parser, gen_checks}, + value, + }; + + #[test] + fn value_lit() { + gen_checks! {value; + r#""helo world""# => r#"ROOT { STRING "\"helo world\""; }"#, + "42" => r#"ROOT { NUMBER "42"; }"#, + "null" => r#"ROOT { NULL "null"; }"#, + "true" => r#"ROOT { BOOL "true"; }"#, + "false" => r#"ROOT { BOOL "false"; }"# + }; + } +} + +#[cfg(test)] +mod test_utils { + use pawarser::parser::ParserBuilder; + + use crate::syntax_kind::{lex, SyntaxKind}; + + use super::Parser; + + macro_rules! gen_checks { + ($fn_to_test:ident; $($in:literal => $out:literal),+) => { + $(crate::grammar::test_utils::check_parser($in, |p| { $fn_to_test(p); }, $out);)+ + } + } + + pub(super) use gen_checks; + + pub(super) fn check_parser(input: &str, parser_fn: fn(&mut Parser), expected_output: &str) { + let toks = lex(input); + let mut p: Parser = ParserBuilder::new(toks) + .add_meaningless(SyntaxKind::WHITESPACE) + .add_meaningless(SyntaxKind::NEWLINE) + .build(); + + parser_fn(&mut p); + + let out = p.finish(); + + assert_eq!(format!("{out:?}").trim_end(), expected_output); + } +}