mirror of
https://codeberg.org/icewind/php-literal-parser.git
synced 2026-06-03 18:44:07 +02:00
fix trailing comma and close bracket handling
This commit is contained in:
parent
36b75790f0
commit
dc96e3190c
2 changed files with 31 additions and 28 deletions
38
src/ast.rs
38
src/ast.rs
|
|
@ -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 => {
|
||||||
|
|
|
||||||
21
src/error.rs
21
src/error.rs
|
|
@ -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),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue