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

View file

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