use array::array; use enumset::{enum_set, EnumSet}; use crate::{syntax_error::SyntaxError, syntax_kind::SyntaxKind}; use self::object::object; pub(crate) type Parser<'src> = pawarser::Parser<'src, SyntaxKind, SyntaxError>; pub(crate) type CompletedMarker = pawarser::CompletedMarker; const BASIC_VALUE_TOKENS: EnumSet = enum_set!(SyntaxKind::BOOL | SyntaxKind::NULL | SyntaxKind::NUMBER | SyntaxKind::STRING); pub fn value(p: &mut Parser) -> bool { if BASIC_VALUE_TOKENS.contains(p.current()) { p.do_bump(); return true; } else { object(p).or_else(|| array(p)).is_some() } } mod object { use crate::{grammar::value, syntax_error::SyntaxError, syntax_kind::SyntaxKind}; use super::{CompletedMarker, Parser, BASIC_VALUE_TOKENS}; pub(super) fn object(p: &mut Parser) -> Option { let obj_start = p.start("object"); if !p.eat(SyntaxKind::BRACE_OPEN) { obj_start.abandon(p); return None; } member(p); while p.at(SyntaxKind::COMMA) { // not always an error, later configurable let potential_trailing_comma = p.start("potential_trailing_comma"); p.eat(SyntaxKind::COMMA); if member(p).is_none() { potential_trailing_comma.complete(p, SyntaxKind::TRAILING_COMMA); } else { potential_trailing_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 { let member_start = p.start("member"); if p.at(SyntaxKind::BRACE_CLOSE) { member_start.abandon(p); return None; } else if p.at(SyntaxKind::STRING) { let member_name_start = p.start("member_name"); p.eat(SyntaxKind::STRING); member_name_start.complete(p, SyntaxKind::MEMBER_NAME); } else { return todo!("handle other tokens: {:?}", p.current()); } if !p.eat(SyntaxKind::COLON) { 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") .complete(p, SyntaxKind::MEMBER), ) } } } mod array { use crate::{syntax_error::SyntaxError, syntax_kind::SyntaxKind}; use super::{value, CompletedMarker, Parser}; pub(super) fn array(p: &mut Parser) -> Option { let array_start = p.start("array"); if !p.eat(SyntaxKind::BRACKET_OPEN) { array_start.abandon(p); return None; } let el = p.start("arr_el"); value(p); el.complete(p, SyntaxKind::ELEMENT); while p.at(SyntaxKind::COMMA) { let potential_trailing_comma = p.start("potential_trailing_comma"); p.eat(SyntaxKind::COMMA); let maybe_el = p.start("arr_el"); if !value(p) { maybe_el.abandon(p); potential_trailing_comma.complete(p, SyntaxKind::TRAILING_COMMA); } else { maybe_el.complete(p, SyntaxKind::ELEMENT); potential_trailing_comma.abandon(p); } } Some(if !p.eat(SyntaxKind::BRACKET_CLOSE) { array_start.error(p, SyntaxError::UnclosedArray) } else { array_start.complete(p, SyntaxKind::ARRAY) }) } }