blob: 6d3f2eb5ad9bd325ffa5c430596810a0d4039e72 [file] [log] [blame]
use crate::decor::InternalString;
use crate::formatted::decorated;
use crate::parser::errors::CustomError;
use crate::parser::trivia::ws_comment_newline;
use crate::parser::value::value;
use crate::value::{Array, Value};
use combine::parser::char::char;
use combine::parser::range::recognize_with_value;
use combine::stream::RangeStream;
use combine::*;
// ;; Array
// array = array-open array-values 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(v: Vec<Value>, comma: bool, trailing: &str) -> Result<Array, CustomError> {
let mut array = Array {
trailing_comma: comma,
trailing: InternalString::from(trailing),
..Default::default()
};
for val in v {
let err = Err(CustomError::MixedArrayType {
got: format!("{:?}", val.get_type()),
expected: format!("{:?}", array.value_type()),
});
if array.push_formatted(val).is_err() {
return err;
}
}
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: char = '[';
// array-close = ws-newline %x5D ; ]
const ARRAY_CLOSE: char = ']';
// array-sep = ws %x2C ws ; , Comma
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)
})
});
parse!(array_value() -> Value, {
attempt((
ws_comment_newline(),
value(),
ws_comment_newline(),
)).map(|(ws1, v, ws2)| decorated(v, ws1, ws2))
});