statements

This commit is contained in:
Robin Appelman 2023-12-15 16:22:51 +01:00
commit 12d3e35496
8 changed files with 69 additions and 53 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ target
*.obj
result
.direnv
*.snap.new

View file

@ -1,5 +1,4 @@
use super::{Array, Entry, Statement, Value};
use crate::error::StatementInTableError;
use crate::{Event, Item, Reader, Result};
use serde::{Serialize, Serializer};
use std::collections::HashMap;
@ -46,25 +45,16 @@ impl Table {
while let Some(event) = reader.event() {
match event? {
Event::Entry {
key: Item::Statement { .. },
span,
key: Item::Statement { content: key, .. },
value,
..
} => {
return Err(
StatementInTableError::new(span.into(), reader.content.into()).into(),
)
}
Event::Entry {
key: Item::Value { content: key, .. },
value: Item::Statement { content: value, .. },
..
} => insert(&mut map, key.into(), Statement::from(value).into()),
} => insert(&mut map, key.into(), Statement::from(value.content).into()),
Event::Entry {
key: Item::Value { content: key, .. },
value: Item::Value { content: value, .. },
key: Item::Key { content: key, .. },
value,
..
} => insert(&mut map, key.into(), Value::from(value).into()),
} => insert(&mut map, key.into(), Value::from(value.content).into()),
Event::GroupStart { name, .. } => {
insert(&mut map, name.into(), Table::load(reader)?.into())

View file

@ -15,10 +15,6 @@ pub enum VdfError {
#[diagnostic(transparent)]
/// No valid token found
NoValidToken(#[from] NoValidTokenError),
#[error(transparent)]
#[diagnostic(transparent)]
/// An unexpected statement was found inside a table
StatementInTable(#[from] StatementInTableError),
}
struct ExpectedTokens<'a>(&'a [Token]);
@ -53,12 +49,17 @@ pub struct UnexpectedTokenError {
}
impl UnexpectedTokenError {
pub fn new(expected: &'static [Token], found: Option<Token>, err_span: SourceSpan, src: String) -> Self {
pub fn new(
expected: &'static [Token],
found: Option<Token>,
err_span: SourceSpan,
src: String,
) -> Self {
UnexpectedTokenError {
err_span,
expected,
found,
src
src,
}
}
}
@ -96,7 +97,11 @@ pub struct NoValidTokenError {
impl NoValidTokenError {
pub fn new(expected: &'static [Token], err_span: SourceSpan, src: String) -> Self {
NoValidTokenError { err_span, expected ,src }
NoValidTokenError {
err_span,
expected,
src,
}
}
}
@ -111,19 +116,3 @@ impl Display for NoValidTokenError {
}
impl Error for NoValidTokenError {}
/// An unexpected statement was found inside a table
#[derive(Debug, Clone, Diagnostic, Error)]
#[diagnostic(code(php_literal_parser::unexpected_token))]
#[error("An unexpected statement was found inside a table")]
pub struct StatementInTableError {
#[label("Unexpected statement")]
err_span: SourceSpan,
#[source_code]
src: String,
}
impl StatementInTableError {
pub fn new(err_span: SourceSpan, src: String) -> Self {
StatementInTableError { err_span, src }
}
}

View file

@ -21,16 +21,16 @@ pub enum Token {
Item,
/// An enclosed or bare item.
#[regex("\"([^\"\\\\]|\\\\.)*\"")]
#[display("item")]
#[display("quoted item")]
QuotedItem,
/// An enclosed or bare statement.
#[regex("\"#([^\"\\\\]|\\\\.)*\"")]
#[display("statement")]
QuotedStatement,
/// An enclosed or bare statement.
#[regex("#[^ \"\t\n]+")]
#[display("statement")]
Statement,
/// An enclosed or bare statement.
#[regex("\"#([^\"\\\\]|\\\\.)*\"")]
#[display("quoted statement")]
QuotedStatement,
}
#[cfg(test)]

View file

@ -10,25 +10,31 @@ pub enum Item<'a> {
Statement { content: Cow<'a, str>, span: Span },
/// A value.
Value { content: Cow<'a, str>, span: Span },
Key { content: Cow<'a, str>, span: Span },
}
impl<'a> Item<'a> {
pub fn span(&self) -> Span {
match self {
Item::Statement { span, .. } => span.clone(),
Item::Value { span, .. } => span.clone(),
Item::Key { span, .. } => span.clone(),
}
}
pub fn into_content(self) -> Cow<'a, str> {
match self {
Item::Statement { content, .. } => content,
Item::Value { content, .. } => content,
Item::Key { content, .. } => content,
}
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Value<'a> {
pub content: Cow<'a, str>,
pub span: Span,
}
/// Reader event.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Event<'a> {
@ -41,7 +47,7 @@ pub enum Event<'a> {
/// An entry.
Entry {
key: Item<'a>,
value: Item<'a>,
value: Value<'a>,
span: Span,
},
}
@ -98,12 +104,12 @@ impl<'a> Reader<'a> {
}
Some((Ok(Token::GroupEnd), span)) => return Some(Ok(Event::GroupEnd { span })),
Some((Ok(Token::Item), span)) => Item::Value {
Some((Ok(Token::Item), span)) => Item::Key {
content: string(self.lexer.slice()),
span,
},
Some((Ok(Token::QuotedItem), span)) => Item::Value {
Some((Ok(Token::QuotedItem), span)) => Item::Key {
content: quoted_string(self.lexer.slice()),
span,
},
@ -158,12 +164,12 @@ impl<'a> Reader<'a> {
}))
}
Some((Ok(Token::QuotedItem), span)) => Item::Value {
Some((Ok(Token::QuotedItem), span)) => Value {
content: quoted_string(self.lexer.slice()),
span,
},
Some((Ok(Token::Item), span)) => Item::Value {
Some((Ok(Token::Item), span)) => Value {
content: string(self.lexer.slice()),
span,
},
@ -179,7 +185,7 @@ impl<'a> Reader<'a> {
}
};
let span = key.span().start..value.span().end;
let span = key.span().start..value.span.end;
Some(Ok(Event::Entry { key, value, span }))
}
}

12
tests/data/messy.vdf Normal file
View file

@ -0,0 +1,12 @@
"#base" "panelBase.res"
"Resource/specificPanel.res"
{
// Specify panel-specific controls here
empty ""
"empty quoted" "\"\""
array 1
array 2
array "3"
windows_path "C:\test\no newline"
}

View file

@ -4,6 +4,7 @@ use vdf_reader::entry::Table;
use vdf_reader::Reader;
#[test_case("tests/data/concrete.vmt")]
#[test_case("tests/data/messy.vdf")]
fn test_parse(path: &str) {
let raw = read_to_string(path).unwrap();
let mut reader = Reader::from(raw.as_str());

View file

@ -0,0 +1,17 @@
---
source: tests/parse.rs
expression: parsed
---
Table({
"#base": Statement(Statement("panelBase.res")),
"Resource/specificPanel.res": Table(Table({
"array": Array(Array([
Value(Value("1")),
Value(Value("2")),
Value(Value("3")),
])),
"empty": Value(Value("")),
"empty quoted": Value(Value("\"\"")),
"windows_path": Value(Value("C:\\test\\no newline")),
})),
})