fix trailing comma and close bracket handling

This commit is contained in:
Robin Appelman 2020-12-01 23:01:06 +01:00
commit dc96e3190c
2 changed files with 31 additions and 28 deletions

View file

@ -110,6 +110,15 @@ enum ArraySyntax {
Long, Long,
} }
impl ArraySyntax {
fn close_bracket(&self) -> Token {
match self {
ArraySyntax::Long => Token::BracketClose,
ArraySyntax::Short => Token::SquareClose,
}
}
}
fn parse_array<'source>( fn parse_array<'source>(
source: &'source str, source: &'source str,
lexer: &mut Lexer<Token>, lexer: &mut Lexer<Token>,
@ -129,32 +138,27 @@ fn parse_array<'source>(
Ok(value) => value, Ok(value) => value,
Err(err) => { Err(err) => {
// trailing comma or empty array // trailing comma or empty array
if matches!( match err.error() {
err.error(), ParseError::UnexpectedToken(UnexpectedTokenError {
ParseError::UnexpectedToken(UnexpectedTokenError { found: None, .. }) found: Some(token),
) { ..
break; }) if token == &syntax.close_bracket() => break,
} else { _ => return Err(err),
return Err(err);
} }
} }
}; };
let key_or_value_span = lexer.span(); let key_or_value_span = lexer.span();
let next = lexer let next = lexer
.next() .next()
.expect_token(if syntax == ArraySyntax::Long { .expect_token(&[syntax.close_bracket(), Token::Comma, Token::Arrow])
&[Token::BracketClose, Token::Comma, Token::Arrow]
} else {
&[Token::SquareClose, Token::Comma, Token::Arrow]
})
.with_span(lexer.span(), source)?; .with_span(lexer.span(), source)?;
match next { match next {
Token::BracketClose if syntax == ArraySyntax::Long => { Token::BracketClose => {
builder.push_value(key_or_value); builder.push_value(key_or_value);
break; break;
} }
Token::SquareClose if syntax == ArraySyntax::Short => { Token::SquareClose => {
builder.push_value(key_or_value); builder.push_value(key_or_value);
break; break;
} }
@ -177,11 +181,7 @@ fn parse_array<'source>(
match lexer match lexer
.next() .next()
.expect_token(if syntax == ArraySyntax::Long { .expect_token(&[syntax.close_bracket(), Token::Comma])
&[Token::BracketClose, Token::Comma]
} else {
&[Token::SquareClose, Token::Comma]
})
.with_span(lexer.span(), source)? .with_span(lexer.span(), source)?
{ {
Token::BracketClose => { Token::BracketClose => {

View file

@ -98,13 +98,16 @@ impl From<UnescapeError> for ParseError {
#[derive(Error, Debug)] #[derive(Error, Debug)]
#[error("Unexpected token, found {found:?} expected one of {expected:?}")] #[error("Unexpected token, found {found:?} expected one of {expected:?}")]
pub struct UnexpectedTokenError { pub struct UnexpectedTokenError {
pub expected: &'static [Token], pub expected: Vec<Token>,
pub found: Option<Token>, pub found: Option<Token>,
} }
impl UnexpectedTokenError { impl UnexpectedTokenError {
pub fn new(expected: &'static [Token], found: Option<Token>) -> Self { pub fn new(expected: &[Token], found: Option<Token>) -> Self {
UnexpectedTokenError { expected, found } UnexpectedTokenError {
expected: expected.to_vec(),
found,
}
} }
} }
@ -113,13 +116,13 @@ impl UnexpectedTokenError {
pub struct InvalidArrayKeyError(pub Value); pub struct InvalidArrayKeyError(pub Value);
pub trait ExpectToken { pub trait ExpectToken {
fn expect_token(self, expected: &'static [Token]) -> Result<Token, UnexpectedTokenError>; fn expect_token(self, expected: &[Token]) -> Result<Token, UnexpectedTokenError>;
} }
impl ExpectToken for Option<Token> { impl ExpectToken for Option<Token> {
fn expect_token(self, expected: &'static [Token]) -> Result<Token, UnexpectedTokenError> { fn expect_token(self, expected: &[Token]) -> Result<Token, UnexpectedTokenError> {
self.ok_or_else(|| UnexpectedTokenError { self.ok_or_else(|| UnexpectedTokenError {
expected, expected: expected.to_vec(),
found: None, found: None,
}) })
.and_then(|token| token.expect_token(expected)) .and_then(|token| token.expect_token(expected))
@ -127,13 +130,13 @@ impl ExpectToken for Option<Token> {
} }
impl ExpectToken for Token { impl ExpectToken for Token {
fn expect_token(self, expected: &'static [Token]) -> Result<Token, UnexpectedTokenError> { fn expect_token(self, expected: &[Token]) -> Result<Token, UnexpectedTokenError> {
if expected.iter().any(|expect| self.eq(expect)) { if expected.iter().any(|expect| self.eq(expect)) {
Ok(self) Ok(self)
} else { } else {
Err(UnexpectedTokenError { Err(UnexpectedTokenError {
expected, expected: expected.to_vec(),
found: None, found: Some(self),
}) })
} }
} }