mod cntr;
mod err;
mod heuristics;
mod list;
mod map;
mod names;
mod prims;
mod wsp;
use super::*;
use heuristics::*;
use list::*;
use names::*;
use nom::{
branch::alt,
bytes::complete::{tag, take_till, take_while, take_while1},
character::complete::{alpha1, char, line_ending},
combinator::{all_consuming, cut, map, map_parser, opt},
error::{self, context, ErrorKind, VerboseErrorKind},
multi::{many0, separated_list0},
sequence::{preceded, separated_pair, terminated},
Err, IResult,
};
use prims::*;
use std::collections::BTreeMap;
use std::str::FromStr;
use wsp::*;
trait CxErr<'a>: error::ParseError<&'a str> + error::ContextError<&'a str> {}
impl<'a> CxErr<'a> for () {}
impl<'a> CxErr<'a> for error::VerboseError<&'a str> {}
#[derive(PartialEq)]
pub struct Error<'a> {
errs: Vec<(usize, VerboseErrorKind)>,
lines: BTreeMap<usize, (usize, &'a str)>,
empty_input: bool,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Trace<'a> {
pub line: usize,
pub col: usize,
pub linestr: &'a str,
pub msg: String,
}
fn kserd_ctor<'a>(ident: Option<Kstr<'a>>, value: Value<'a>) -> Kserd<'a> {
if let Some(ident) = ident {
Kserd::with_id(ident, value).unwrap()
} else {
Kserd::new(value)
}
}
fn kserd_delimited<'a, E: CxErr<'a>>(
force_inline: bool,
) -> impl Fn(&'a str) -> IResult<&'a str, Kserd<'a>, E> {
move |i: &'a str| {
let (i, pat) = pattern_match_delimited(i)?;
match pat {
Nonprim::Tuple => tuple(force_inline)(i),
Nonprim::Cntr => cntr::delimited(force_inline)(i),
Nonprim::Seq => seq_delimited(force_inline)(i),
Nonprim::Map => map::delimited(force_inline)(i),
Nonprim::None => prim(i),
}
}
}
fn kserd_inline<'a, E: CxErr<'a>>(i: &'a str) -> IResult<&'a str, Kserd<'a>, E> {
kserd_delimited(true)(i)
}
fn kserd_concise<'a, E: CxErr<'a>>(i: &'a str) -> IResult<&'a str, Kserd<'a>, E> {
kserd_delimited(false)(i)
}
fn kserd_nested<'a, E: CxErr<'a>>(
indents: usize,
) -> impl Fn(&'a str) -> IResult<&'a str, Kserd<'a>, E> {
move |i: &'a str| {
let (i, verbose) = pattern_match_verbose(i)?;
if verbose {
cntr::verbose(indents)(i)
} else {
ignore_inline_whitespace(kserd_concise)(i)
}
}
}
fn kserd_root<'a, E: CxErr<'a>>(i: &'a str) -> IResult<&'a str, Kserd<'a>, E> {
if i.is_empty() {
context("empty input", |i| {
Err(Err::Error(error::make_error(i, ErrorKind::Eof)))
})(i)
} else {
all_consuming(terminated(kserd_nested(0), multiline_whitespace))(i)
}
}
fn uncut<'a, E: CxErr<'a>, O, F>(f: F) -> impl Fn(&'a str) -> IResult<&'a str, O, E>
where
F: Fn(&'a str) -> IResult<&'a str, O, E>,
{
move |i: &'a str| {
f(i).map_err(|e| match e {
Err::Failure(e) => Err::Error(e),
x => x,
})
}
}
pub fn parse(s: &str) -> Result<Kserd, Error> {
kserd_root::<nom::error::VerboseError<_>>(s)
.map(|x| x.1)
.map_err(|e| match e {
Err::Error(x) | Err::Failure(x) => Error::new(s, x),
Err::Incomplete(_) => {
unreachable!("all parsers use complete versions so no incomplete possible")
}
})
}