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
|
*.obj
|
||||||
result
|
result
|
||||||
.direnv
|
.direnv
|
||||||
|
*.snap.new
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use super::{Array, Entry, Statement, Value};
|
use super::{Array, Entry, Statement, Value};
|
||||||
use crate::error::StatementInTableError;
|
|
||||||
use crate::{Event, Item, Reader, Result};
|
use crate::{Event, Item, Reader, Result};
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Serialize, Serializer};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
@ -46,25 +45,16 @@ impl Table {
|
||||||
while let Some(event) = reader.event() {
|
while let Some(event) = reader.event() {
|
||||||
match event? {
|
match event? {
|
||||||
Event::Entry {
|
Event::Entry {
|
||||||
key: Item::Statement { .. },
|
key: Item::Statement { content: key, .. },
|
||||||
span,
|
value,
|
||||||
..
|
..
|
||||||
} => {
|
} => insert(&mut map, key.into(), Statement::from(value.content).into()),
|
||||||
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()),
|
|
||||||
|
|
||||||
Event::Entry {
|
Event::Entry {
|
||||||
key: Item::Value { content: key, .. },
|
key: Item::Key { content: key, .. },
|
||||||
value: Item::Value { content: value, .. },
|
value,
|
||||||
..
|
..
|
||||||
} => insert(&mut map, key.into(), Value::from(value).into()),
|
} => insert(&mut map, key.into(), Value::from(value.content).into()),
|
||||||
|
|
||||||
Event::GroupStart { name, .. } => {
|
Event::GroupStart { name, .. } => {
|
||||||
insert(&mut map, name.into(), Table::load(reader)?.into())
|
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)]
|
#[diagnostic(transparent)]
|
||||||
/// No valid token found
|
/// No valid token found
|
||||||
NoValidToken(#[from] NoValidTokenError),
|
NoValidToken(#[from] NoValidTokenError),
|
||||||
#[error(transparent)]
|
|
||||||
#[diagnostic(transparent)]
|
|
||||||
/// An unexpected statement was found inside a table
|
|
||||||
StatementInTable(#[from] StatementInTableError),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ExpectedTokens<'a>(&'a [Token]);
|
struct ExpectedTokens<'a>(&'a [Token]);
|
||||||
|
|
@ -53,12 +49,17 @@ pub struct UnexpectedTokenError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
UnexpectedTokenError {
|
||||||
err_span,
|
err_span,
|
||||||
expected,
|
expected,
|
||||||
found,
|
found,
|
||||||
src
|
src,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +97,11 @@ pub struct NoValidTokenError {
|
||||||
|
|
||||||
impl NoValidTokenError {
|
impl NoValidTokenError {
|
||||||
pub fn new(expected: &'static [Token], err_span: SourceSpan, src: String) -> Self {
|
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 {}
|
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,
|
Item,
|
||||||
/// An enclosed or bare item.
|
/// An enclosed or bare item.
|
||||||
#[regex("\"([^\"\\\\]|\\\\.)*\"")]
|
#[regex("\"([^\"\\\\]|\\\\.)*\"")]
|
||||||
#[display("item")]
|
#[display("quoted item")]
|
||||||
QuotedItem,
|
QuotedItem,
|
||||||
/// An enclosed or bare statement.
|
/// An enclosed or bare statement.
|
||||||
#[regex("\"#([^\"\\\\]|\\\\.)*\"")]
|
|
||||||
#[display("statement")]
|
|
||||||
QuotedStatement,
|
|
||||||
/// An enclosed or bare statement.
|
|
||||||
#[regex("#[^ \"\t\n]+")]
|
#[regex("#[^ \"\t\n]+")]
|
||||||
#[display("statement")]
|
#[display("statement")]
|
||||||
Statement,
|
Statement,
|
||||||
|
/// An enclosed or bare statement.
|
||||||
|
#[regex("\"#([^\"\\\\]|\\\\.)*\"")]
|
||||||
|
#[display("quoted statement")]
|
||||||
|
QuotedStatement,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
|
|
@ -10,25 +10,31 @@ pub enum Item<'a> {
|
||||||
Statement { content: Cow<'a, str>, span: Span },
|
Statement { content: Cow<'a, str>, span: Span },
|
||||||
|
|
||||||
/// A value.
|
/// A value.
|
||||||
Value { content: Cow<'a, str>, span: Span },
|
Key { content: Cow<'a, str>, span: Span },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Item<'a> {
|
impl<'a> Item<'a> {
|
||||||
pub fn span(&self) -> Span {
|
pub fn span(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
Item::Statement { span, .. } => span.clone(),
|
Item::Statement { span, .. } => span.clone(),
|
||||||
Item::Value { span, .. } => span.clone(),
|
Item::Key { span, .. } => span.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_content(self) -> Cow<'a, str> {
|
pub fn into_content(self) -> Cow<'a, str> {
|
||||||
match self {
|
match self {
|
||||||
Item::Statement { content, .. } => content,
|
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.
|
/// Reader event.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum Event<'a> {
|
pub enum Event<'a> {
|
||||||
|
|
@ -41,7 +47,7 @@ pub enum Event<'a> {
|
||||||
/// An entry.
|
/// An entry.
|
||||||
Entry {
|
Entry {
|
||||||
key: Item<'a>,
|
key: Item<'a>,
|
||||||
value: Item<'a>,
|
value: Value<'a>,
|
||||||
span: Span,
|
span: Span,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -98,12 +104,12 @@ impl<'a> Reader<'a> {
|
||||||
}
|
}
|
||||||
Some((Ok(Token::GroupEnd), span)) => return Some(Ok(Event::GroupEnd { span })),
|
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()),
|
content: string(self.lexer.slice()),
|
||||||
span,
|
span,
|
||||||
},
|
},
|
||||||
|
|
||||||
Some((Ok(Token::QuotedItem), span)) => Item::Value {
|
Some((Ok(Token::QuotedItem), span)) => Item::Key {
|
||||||
content: quoted_string(self.lexer.slice()),
|
content: quoted_string(self.lexer.slice()),
|
||||||
span,
|
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()),
|
content: quoted_string(self.lexer.slice()),
|
||||||
span,
|
span,
|
||||||
},
|
},
|
||||||
|
|
||||||
Some((Ok(Token::Item), span)) => Item::Value {
|
Some((Ok(Token::Item), span)) => Value {
|
||||||
content: string(self.lexer.slice()),
|
content: string(self.lexer.slice()),
|
||||||
span,
|
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 }))
|
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;
|
use vdf_reader::Reader;
|
||||||
|
|
||||||
#[test_case("tests/data/concrete.vmt")]
|
#[test_case("tests/data/concrete.vmt")]
|
||||||
|
#[test_case("tests/data/messy.vdf")]
|
||||||
fn test_parse(path: &str) {
|
fn test_parse(path: &str) {
|
||||||
let raw = read_to_string(path).unwrap();
|
let raw = read_to_string(path).unwrap();
|
||||||
let mut reader = Reader::from(raw.as_str());
|
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