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 value::{Array, Value};
use decor::InternalString;
use formatted::decorated;
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(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 {
let err = Err(CustomError::MixedArrayType {
got: format!("{:?}", val.get_type()),
expected: format!("{:?}", array.value_type()),
});
if !array.push_value(val, false) {
return err;
}
}
Ok(array)
}
const ARRAY_OPEN: char = '[';
const ARRAY_CLOSE: char = ']';
const ARRAY_SEP: char = ',';
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)
})
});
parse!(array_value() -> Value, {
try((
ws_comment_newline(),
value(),
ws_comment_newline(),
)).map(|(ws1, v, ws2)| decorated(v, ws1, ws2))
});