Skip to content

Commit

Permalink
Merge #26
Browse files Browse the repository at this point in the history
26: refactor(parser): migrate from nom to combine r=ordian

Closes #16.
  • Loading branch information
bors[bot] committed Aug 13, 2017
2 parents 2055f4a + 0f4a7b3 commit 244fc95
Show file tree
Hide file tree
Showing 22 changed files with 1,046 additions and 1,348 deletions.
8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ keywords = ["toml"]
categories = ["encoding", "parser-implementations", "parsing"]
description = "Yet another format-preserving TOML parser."
authors = ["Andronik Ordian <[email protected]>"]
homepage = "https://github.com/ordian/toml_edit"
repository = "https://github.com/ordian/toml_edit"
documentation = "https://docs.rs/toml_edit"

Expand All @@ -19,9 +18,12 @@ appveyor = { repository = "ordian/toml_edit" }
chrono = "0.4"
intrusive-collections = "0.6"
linked-hash-map = "0.4"
nom_locate = "0.1.0"
typed-arena = "1.3"
nom = { version = "3.2", features = ["verbose-errors"] }
combine = "3.0.0-alpha.1"

# TODO: remove this, once new version is released
[replace]
"combine:3.0.0-alpha.1" = { git = "https://github.com/Marwes/combine" }

[dev-dependencies]
serde_json = "1.0"
Expand Down
3 changes: 3 additions & 0 deletions src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ impl Display for Array {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "{}[", self.decor.prefix)?;
join(f, self.values.iter(), ",")?;
if self.trailing_comma {
write!(f, ",")?;
}
write!(f, "{}", self.trailing)?;
write!(f, "]{}", self.decor.suffix)
}
Expand Down
4 changes: 2 additions & 2 deletions src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,11 @@ impl Drop for DocumentInner {
}

impl FromStr for Document {
type Err = parser::Error;
type Err = parser::TomlError;

/// Parses a document from a &str
fn from_str(s: &str) -> Result<Self, Self::Err> {
parser::Parser::parse(s)
parser::TomlParser::parse(s)
}
}

Expand Down
1 change: 1 addition & 0 deletions src/formatted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub(crate) fn value(mut val: Value, raw: &str) -> Value {
}
_ => {}
};
decorate(&mut val, "", "");
val
}

Expand Down
29 changes: 11 additions & 18 deletions src/key.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::str::FromStr;
use decor::InternalString;
use parser;
use nom;
use combine;
use combine::Parser;


/// Key as part of a Key/Value Pair or a table header.
Expand Down Expand Up @@ -33,27 +34,19 @@ pub struct Key {
}

impl FromStr for Key {
type Err = parser::Error;
type Err = parser::TomlError;

/// Parses a key from a &str
fn from_str(s: &str) -> Result<Self, Self::Err> {
let parsed = parser::key(parser::Span::new(s));
match parsed {
nom::IResult::Done(i, (key, raw)) => if i.fragment.is_empty() {
Ok(Self {
parser::key()
.parse(combine::State::new(s))
.map(|((raw, key), _)| {
Key {
raw: raw.into(),
key: key,
raw: raw.fragment.into(),
})
} else {
Err(Self::Err::new(parser::ErrorKind::InvalidKey, i))
},
nom::IResult::Error(e) => {
let mut err = parser::to_error(&e);
err.kind = parser::ErrorKind::InvalidKey;
Err(err)
}
_ => unreachable!("key should be complete"),
}
}
})
.map_err(|e| Self::Err::new(e, s))
}
}

Expand Down
7 changes: 3 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// #![deny(missing_docs)]
#![deny(warnings)]
// #![deny(warnings)]

//! # `toml_edit`
//!
Expand Down Expand Up @@ -30,8 +30,7 @@
#[macro_use]
extern crate intrusive_collections;
#[macro_use]
extern crate nom;
extern crate nom_locate;
extern crate combine;
extern crate chrono;
extern crate linked_hash_map;
extern crate typed_arena;
Expand All @@ -49,7 +48,7 @@ mod document;

pub use value::{Array, InlineTable, Value};
pub use key::Key;
pub use parser::Error;
pub use parser::TomlError;
pub use table::{Iter, IterMut, Table, TableChild, TableChildMut, TableEntry};
pub use array_of_tables::ArrayOfTables;
pub use document::Document;
112 changes: 48 additions & 64 deletions src/parser/array.rs
Original file line number Diff line number Diff line change
@@ -1,88 +1,72 @@
use nom;
use parser::errors::ErrorKind;
use combine::*;
use combine::range::recognize_with_value;
use combine::char::char;
use combine::primitives::RangeStream;
use parser::errors::CustomError;
use parser::trivia::ws_comment_newline;
use parser::value::value;
use parser::{LenWorkaround, Span};
use ::value::{Value, Array};
use ::decor::InternalString;
use ::formatted::decorated;
use value::{Array, Value};
use decor::InternalString;
use formatted::decorated;

// ;; Array

// array = array-open array-values array-close
named!(parse_array(Span) -> (Vec<Value>, &str),
delimited!(
complete!(tag!(ARRAY_OPEN)),
array_values,
err!(ErrorKind::UnterminatedArray,
complete!(tag!(ARRAY_CLOSE)))
)
);
parse!(array() -> Array, {
between(char(ARRAY_OPEN), char(ARRAY_CLOSE),
array_values().and_then(|(v, c, t)| array_from_vec(v, c, t)))
});

fn array_from_vec(trailing: &str, v: Vec<Value>) -> Option<Array> {
fn array_from_vec(v: Vec<Value>, comma: bool, trailing: &str) -> Result<Array, CustomError> {
let mut array = Array::default();
array.trailing_comma = comma;
array.trailing = InternalString::from(trailing);
for val in v {
if !array.push_value(val, false) {
return None;
let err = Err(CustomError::MixedArrayType {
got: format!("{:?}", val.get_type()),
expected: format!("{:?}", array.value_type()),
});
if !array.push_value(
val,
/* decorate = */
false,
) {
return err;
}
}
Some(array)
}

pub fn array(input: Span) -> nom::IResult<Span, Array> {
let (rest, p) = try_parse!(input, parse_array);

match array_from_vec(p.1, p.0) {
Some(a) => nom::IResult::Done(rest, a),
_ => e!(ErrorKind::MixedArrayType, rest),
}
Ok(array)
}

// note: we're omitting ws and newlines here, because
// they should be part of the formatted values
// array-open = %x5B ws-newline ; [
const ARRAY_OPEN: &str = "[";
const ARRAY_OPEN: char = '[';
// array-close = ws-newline %x5D ; ]
const ARRAY_CLOSE: &str = "]";
const ARRAY_CLOSE: char = ']';
// array-sep = ws %x2C ws ; , Comma
const ARRAY_SEP: &str = ",";
const ARRAY_SEP: char = ',';

// note: this rule is modified
// array-values = [ ( array-value array-sep array-values ) /
// array-value / ws-comment-newline ]
parse!(array_values() -> (Vec<Value>, bool, &'a str), {
(
optional(
recognize_with_value(
sep_end_by1(array_value(), char(ARRAY_SEP))
).map(|(r, v): (&'a str, _)| (v, r.ends_with(',')))
),
ws_comment_newline(),
).map(|(v, t)| {
let (v, c) = v.unwrap_or_default();
(v, c, t)
})
});

named!(array_values(Span) -> (Vec<Value>, &str),
do_parse!(
v: opt!(
do_parse!(
v: separated_nonempty_list_complete!(
tag!(ARRAY_SEP),
array_value
) >>
t: opt!(trailing) >>
(v, t.map(|s| s.fragment).unwrap_or(""))
)
) >>
w: ws_comment_newline >>
(v.unwrap_or_else(|| (Vec::new(), w.fragment)))
)
);

named!(array_value(Span) -> Value,
do_parse!(
ws1: ws_comment_newline >>
v: value >>
ws2: ws_comment_newline >>
(decorated(v, ws1.fragment, ws2.fragment))
)
);

named!(trailing(Span) -> Span,
recognize!(
tuple!(
complete!(tag!(ARRAY_SEP)),
ws_comment_newline
)
)
);
parse!(array_value() -> Value, {
try((
ws_comment_newline(),
value(),
ws_comment_newline(),
)).map(|(ws1, v, ws2)| decorated(v, ws1, ws2))
});
Loading

0 comments on commit 244fc95

Please sign in to comment.