1
Fork 0

fix(parser): Fix incorrect parsing of unquoted strings

Closes #4.
This commit is contained in:
Lucas Schwiderski 2023-03-01 19:30:17 +01:00
parent a6ef5a914e
commit 1ca19b4dda
Signed by: lucas
GPG key ID: AA12679AAA6DF4D8
3 changed files with 19 additions and 13 deletions

View file

@ -6,6 +6,10 @@
== [Unreleased] == [Unreleased]
== Fixed
- fix incorrect parsing of unquoted strings
== [v0.2.3] - 2023-02-24 == [v0.2.3] - 2023-02-24
=== Fixed === Fixed

View file

@ -1,10 +1,10 @@
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::{tag, take_until}; use nom::bytes::complete::{tag, take_until};
use nom::character::complete::{alpha1, alphanumeric1, char, digit1, not_line_ending, one_of}; use nom::character::complete::{char, digit1, none_of, not_line_ending, one_of};
use nom::combinator::{cut, eof, map, map_res, opt, recognize, value}; use nom::combinator::{cut, eof, map, map_res, opt, recognize, value};
use nom::multi::{many0_count, many1_count}; use nom::multi::many1_count;
use nom::number::complete::double; use nom::number::complete::double;
use nom::sequence::{delimited, pair, preceded, terminated, tuple}; use nom::sequence::{delimited, preceded, terminated, tuple};
use nom::{IResult, Slice}; use nom::{IResult, Slice};
use nom_locate::LocatedSpan; use nom_locate::LocatedSpan;
@ -57,11 +57,9 @@ fn float(input: Span) -> IResult<Span, f64> {
} }
fn identifier(input: Span) -> IResult<Span, &str> { fn identifier(input: Span) -> IResult<Span, &str> {
let leading = alt((alpha1, tag("_"))); map(recognize(many1_count(none_of("\" \t\n=:"))), |val: Span| {
let trailing = many0_count(alt((alphanumeric1, tag("_")))); *val.fragment()
let ident = pair(leading, trailing); })(input)
map(recognize(ident), |val: Span| *val.fragment())(input)
} }
fn string_content(input: Span) -> IResult<Span, &str> { fn string_content(input: Span) -> IResult<Span, &str> {
@ -295,10 +293,14 @@ mod test {
assert_ok!("foo_bar", identifier, "", "foo_bar"); assert_ok!("foo_bar", identifier, "", "foo_bar");
assert_ok!("_foo", identifier, "", "_foo"); assert_ok!("_foo", identifier, "", "_foo");
assert_ok!("foo bar", identifier, " bar", "foo"); assert_ok!("foo bar", identifier, " bar", "foo");
assert_ok!("123", identifier, "", "123");
assert_ok!("1foo", identifier, "", "1foo");
assert_ok!("foo-bar", identifier, "", "foo-bar");
assert_ok!("foo/bar", identifier, "", "foo/bar");
assert_ok!("foo\"", identifier, "\"", "foo");
assert_err!("123", identifier, ErrorKind::Tag); assert_err!("\"foo", identifier, ErrorKind::Many1Count);
assert_err!("1foo", identifier, ErrorKind::Tag); assert_err!("\"foo\"", identifier, ErrorKind::Many1Count);
assert_err!("\"foo\"", identifier, ErrorKind::Tag);
} }
#[test] #[test]

View file

@ -122,10 +122,10 @@ impl<'a> serde::ser::Serializer for &'a mut Serializer {
fn serialize_str(self, v: &str) -> Result<Self::Ok> { fn serialize_str(self, v: &str) -> Result<Self::Ok> {
self.ensure_top_level_struct()?; self.ensure_top_level_struct()?;
let needs_escapes = let needs_quotes =
v.is_empty() || v.contains([' ', '\n', '\r', '\t', '=', '\'', '"', '\\', '/']); v.is_empty() || v.contains([' ', '\n', '\r', '\t', '=', '\'', '"', '\\', '/']);
if needs_escapes { if needs_quotes {
self.output += "\""; self.output += "\"";
for c in v.chars() { for c in v.chars() {