mirror of
https://codeberg.org/icewind/php-literal-parser.git
synced 2026-06-03 18:44:07 +02:00
handle null
This commit is contained in:
parent
6975a89b63
commit
27b1552c94
4 changed files with 33 additions and 30 deletions
|
|
@ -13,6 +13,7 @@ fn main() {
|
|||
"array" => [1,2,3,4],
|
||||
"bool" => false,
|
||||
"negative" => -1,
|
||||
"null" => null,
|
||||
)
|
||||
"###;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ pub enum Token {
|
|||
Array,
|
||||
#[regex("true|false")]
|
||||
Bool,
|
||||
#[regex("null")]
|
||||
Null,
|
||||
#[token("=>")]
|
||||
Arrow,
|
||||
#[token("(")]
|
||||
|
|
@ -43,6 +45,7 @@ fn test_lex() {
|
|||
"array" => [1,2,3,4],
|
||||
"bool" => false,
|
||||
"negative" => -1,
|
||||
"null" => null,
|
||||
)
|
||||
"###;
|
||||
let mut lex = Token::lexer(source);
|
||||
|
|
@ -105,6 +108,11 @@ fn test_lex() {
|
|||
assert_eq!(lex.next(), Some(Token::Integer));
|
||||
assert_eq!(lex.next(), Some(Token::Comma));
|
||||
|
||||
assert_eq!(lex.next(), Some(Token::LiteralString));
|
||||
assert_eq!(lex.next(), Some(Token::Arrow));
|
||||
assert_eq!(lex.next(), Some(Token::Null));
|
||||
assert_eq!(lex.next(), Some(Token::Comma));
|
||||
|
||||
assert_eq!(lex.next(), Some(Token::BracketClose));
|
||||
|
||||
assert_eq!(lex.next(), None);
|
||||
|
|
|
|||
24
src/lib.rs
24
src/lib.rs
|
|
@ -18,13 +18,13 @@
|
|||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
mod ast;
|
||||
mod error;
|
||||
mod lexer;
|
||||
mod parser;
|
||||
mod string;
|
||||
|
||||
pub use ast::parse;
|
||||
pub use error::{ParseError, SpannedError};
|
||||
pub use parser::parse;
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
|
@ -37,6 +37,7 @@ pub enum Value {
|
|||
Float(f64),
|
||||
String(String),
|
||||
Array(HashMap<Key, Value>),
|
||||
Null,
|
||||
}
|
||||
|
||||
/// A php value, can be either a bool, int, float, string or array
|
||||
|
|
@ -46,7 +47,8 @@ pub enum Value {
|
|||
///
|
||||
/// ## Indexing
|
||||
///
|
||||
/// If the value is a php array, you can directly index into the `Value`, this will panic if the `Value` is not an array
|
||||
/// If the value is a php array, you can directly index into the `Value`, this will null if the `Value` is not an array
|
||||
/// or the key is not found
|
||||
///
|
||||
/// ```rust
|
||||
/// # use maplit::hashmap;
|
||||
|
|
@ -59,6 +61,7 @@ pub enum Value {
|
|||
/// });
|
||||
/// assert_eq!(value["key"], "value");
|
||||
/// assert_eq!(value[10], false);
|
||||
/// assert!(value["not"]["found"].is_null());
|
||||
/// # }
|
||||
/// ```
|
||||
impl Value {
|
||||
|
|
@ -87,6 +90,11 @@ impl Value {
|
|||
matches!(self, Value::Array(_))
|
||||
}
|
||||
|
||||
/// Check if the value is null
|
||||
pub fn is_null(&self) -> bool {
|
||||
matches!(self, Value::Null)
|
||||
}
|
||||
|
||||
/// Convert the value into a bool if it is one
|
||||
pub fn into_bool(self) -> Option<bool> {
|
||||
match self {
|
||||
|
|
@ -282,8 +290,8 @@ where
|
|||
|
||||
fn index(&self, index: &Q) -> &Self::Output {
|
||||
match self {
|
||||
Value::Array(map) => map.index(index),
|
||||
_ => panic!("index into non array value"),
|
||||
Value::Array(map) => map.get(index).unwrap_or(&Value::Null),
|
||||
_ => &Value::Null,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -293,8 +301,8 @@ impl Index<Key> for Value {
|
|||
|
||||
fn index(&self, index: Key) -> &Self::Output {
|
||||
match self {
|
||||
Value::Array(map) => map.index(&index),
|
||||
_ => panic!("index into non array value"),
|
||||
Value::Array(map) => map.get(&index).unwrap_or(&Value::Null),
|
||||
_ => &Value::Null,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -305,7 +313,7 @@ impl Index<i64> for Value {
|
|||
fn index(&self, index: i64) -> &Self::Output {
|
||||
match self {
|
||||
Value::Array(map) => map.index(&Key::Int(index)),
|
||||
_ => panic!("index into non array value"),
|
||||
_ => &Value::Null,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,17 +40,19 @@ pub fn parse_lexer<'source>(
|
|||
Token::Integer,
|
||||
Token::Float,
|
||||
Token::LiteralString,
|
||||
Token::Null,
|
||||
Token::Array,
|
||||
Token::SquareOpen,
|
||||
])
|
||||
.with_span(lexer.span(), source)?;
|
||||
let value = match token {
|
||||
Token::Bool => parse_literal(token, lexer.slice()).with_span(lexer.span(), source)?,
|
||||
Token::Integer => parse_literal(token, lexer.slice()).with_span(lexer.span(), source)?,
|
||||
Token::Float => parse_literal(token, lexer.slice()).with_span(lexer.span(), source)?,
|
||||
Token::Bool => Value::Bool(lexer.slice().parse().with_span(lexer.span(), source)?),
|
||||
Token::Integer => Value::Int(lexer.slice().parse().with_span(lexer.span(), source)?),
|
||||
Token::Float => Value::Float(lexer.slice().parse().with_span(lexer.span(), source)?),
|
||||
Token::LiteralString => {
|
||||
parse_literal(token, lexer.slice()).with_span(lexer.span(), source)?
|
||||
Value::String(parse_string(lexer.slice()).with_span(lexer.span(), source)?)
|
||||
}
|
||||
Token::Null => Value::Null,
|
||||
Token::Array => Value::Array(parse_array(source, lexer, ArraySyntax::Long)?),
|
||||
Token::SquareOpen => Value::Array(parse_array(source, lexer, ArraySyntax::Short)?),
|
||||
_ => unreachable!(),
|
||||
|
|
@ -59,22 +61,6 @@ pub fn parse_lexer<'source>(
|
|||
Ok(value)
|
||||
}
|
||||
|
||||
fn parse_literal(token: Token, slice: &str) -> Result<Value, ParseError> {
|
||||
let token = token.expect_token(&[
|
||||
Token::Bool,
|
||||
Token::Integer,
|
||||
Token::Float,
|
||||
Token::LiteralString,
|
||||
])?;
|
||||
match token {
|
||||
Token::Bool => Ok(Value::Bool(slice.parse()?)),
|
||||
Token::Integer => Ok(Value::Int(slice.parse()?)),
|
||||
Token::Float => Ok(Value::Float(slice.parse()?)),
|
||||
Token::LiteralString => Ok(Value::String(parse_string(slice)?)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_string(literal: &str) -> Result<String, UnescapeError> {
|
||||
let single_quote = literal.bytes().next().unwrap() == b'\'';
|
||||
let inner = &literal[1..(literal.len()) - 1];
|
||||
|
|
@ -273,9 +259,9 @@ fn test_parse() {
|
|||
Value::Array(hashmap! {
|
||||
Key::String("foo".into()) => Value::Bool(true),
|
||||
Key::String("nested".into()) => Value::Array(hashmap! {
|
||||
Key::String("foo".into()) => Value::Bool(false),
|
||||
Key::String("foo".into()) => Value::Null,
|
||||
}),
|
||||
}),
|
||||
parse(r#"["foo" => true, "nested" => ['foo' => false]]"#).unwrap()
|
||||
parse(r#"["foo" => true, "nested" => ['foo' => null]]"#).unwrap()
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue