mirror of
https://codeberg.org/icewind/php-literal-parser.git
synced 2026-06-03 18:44:07 +02:00
handle empty arrays and trailing commas
This commit is contained in:
parent
4c4cbefcf5
commit
36b75790f0
4 changed files with 51 additions and 21 deletions
25
src/ast.rs
25
src/ast.rs
|
|
@ -1,3 +1,4 @@
|
|||
use crate::error::UnexpectedTokenError;
|
||||
use crate::error::{ExpectToken, InvalidArrayKeyError, ParseError, ResultExt, SpannedError};
|
||||
use crate::lexer::Token;
|
||||
use crate::string::{unescape_double, unescape_single, UnescapeError};
|
||||
|
|
@ -124,7 +125,20 @@ fn parse_array<'source>(
|
|||
}
|
||||
|
||||
loop {
|
||||
let key_or_value = parse_lexer(source, lexer)?;
|
||||
let key_or_value = match parse_lexer(source, lexer) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
// trailing comma or empty array
|
||||
if matches!(
|
||||
err.error(),
|
||||
ParseError::UnexpectedToken(UnexpectedTokenError { found: None, .. })
|
||||
) {
|
||||
break;
|
||||
} else {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
let key_or_value_span = lexer.span();
|
||||
let next = lexer
|
||||
.next()
|
||||
|
|
@ -202,6 +216,7 @@ fn test_parse() {
|
|||
Value::String("test".to_string()),
|
||||
parse(r#""test""#).unwrap()
|
||||
);
|
||||
assert_eq!(Value::Array(hashmap! {}), parse(r#"array()"#).unwrap());
|
||||
assert_eq!(
|
||||
Value::Array(hashmap! {
|
||||
Key::Int(0) => Value::Int(3),
|
||||
|
|
@ -210,6 +225,14 @@ fn test_parse() {
|
|||
}),
|
||||
parse(r#"array(3,4,5)"#).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Value::Array(hashmap! {
|
||||
Key::Int(0) => Value::Int(3),
|
||||
Key::Int(1) => Value::Int(4),
|
||||
Key::Int(2) => Value::Int(5),
|
||||
}),
|
||||
parse(r#"array(3,4,5,)"#).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Value::Array(hashmap! {
|
||||
Key::Int(1) => Value::Int(3),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ impl<'a, T: Error + Debug> SpannedError<'a, T> {
|
|||
error,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error(&self) -> &T {
|
||||
&self.error
|
||||
}
|
||||
}
|
||||
|
||||
const METRICS: DefaultMetrics = DefaultMetrics::with_tab_stop(4);
|
||||
|
|
|
|||
20
src/lexer.rs
20
src/lexer.rs
|
|
@ -1,5 +1,4 @@
|
|||
use logos::Logos;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Logos, Debug, PartialEq, Clone)]
|
||||
pub enum Token {
|
||||
|
|
@ -30,25 +29,6 @@ pub enum Token {
|
|||
Error,
|
||||
}
|
||||
|
||||
impl Display for Token {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Token::Array => write!(f, "array"),
|
||||
Token::Bool => write!(f, "bool"),
|
||||
Token::Arrow => write!(f, "arrow"),
|
||||
Token::BracketOpen => write!(f, "bracket open"),
|
||||
Token::BracketClose => write!(f, "bracket close"),
|
||||
Token::SquareOpen => write!(f, "square bracket open"),
|
||||
Token::SquareClose => write!(f, "square bracket close"),
|
||||
Token::Comma => write!(f, "comma"),
|
||||
Token::LiteralString => write!(f, "string literal"),
|
||||
Token::Float => write!(f, "float literal"),
|
||||
Token::Integer => write!(f, "integer literal"),
|
||||
Token::Error => write!(f, "invalid token"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lex() {
|
||||
let source = r###"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue