mirror of
https://codeberg.org/icewind/vdf-reader.git
synced 2026-06-03 18:14:07 +02:00
statements
This commit is contained in:
parent
8e3f20a298
commit
12d3e35496
8 changed files with 69 additions and 53 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -3,3 +3,4 @@ target
|
|||
*.obj
|
||||
result
|
||||
.direnv
|
||||
*.snap.new
|
||||
|
|
@ -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())
|
||||
|
|
|
|||
35
src/error.rs
35
src/error.rs
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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
12
tests/data/messy.vdf
Normal 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"
|
||||
}
|
||||
|
|
@ -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());
|
||||
|
|
|
|||
17
tests/snapshots/parse__parse-2.snap
Normal file
17
tests/snapshots/parse__parse-2.snap
Normal 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")),
|
||||
})),
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue