json-pop 0.0.2

A small JSON parser from parser/lexer generators.
Documentation
use crate::lex;
use crate::error::CompilationError;
use crate::value;
use crate::parser::ParseError;
use std::result::Result;

grammar<'source>;

extern {
  type Location = usize;
  type Error = CompilationError;
  enum lex::Token<'source> {
    "true"  => lex::Token::True,
    "false" => lex::Token::False,
    "null"  => lex::Token::Null,
    ","	    => lex::Token::Comma,
    ":"	    => lex::Token::Colon,
    "{"	    => lex::Token::LBrace,
    "}"	    => lex::Token::RBrace,
    "["	    => lex::Token::LBrack,
    "]"	    => lex::Token::RBrack,
    string => lex::Token::String(<&'source str>),
    number  => lex::Token::Number(<&'source str>),
    missing_quote => lex::Token::MissingEndQuote(<&'source str>),
  }
}

pub json = value;

value: value::Value<'source> = {
   "true"      =>? Ok(value::Value::<'source>::Bool(true)),
   "false"     =>? Ok(value::Value::<'source>::Bool(false)),
   "null"      =>? Ok(value::Value::<'source>::Null),
   <a: array>  =>? Ok(value::Value::<'source>::Array(a)),
   <o: objects> =>? Ok(value::Value::<'source>::Object(o)),
   <l:@L> <n: number> <r:@R> =>? {
	let result = lexical::parse(n.as_bytes());
	match result {
	   Ok(n) => Ok(value::Value::Number(n)),
	   Err(_e) => Err(ParseError::User{
		error: CompilationError::NumericalError{range:l..r},
	   })
	}
   },
   <l:@L> <s: string> <r:@R> =>? {
	let without_quotes = &s[1..r - (l + 1)];
	Ok(value::Value::<'source>::String(without_quotes))
   },
   <l: @L> missing_quote <r:@R> =>? Err(ParseError::User { error: CompilationError::UnterminatedStringLiteral{range: l..r}}),
};

// No trailing comma.
CommaSep<T>: Vec<T> = {
  <es: CommaSep<T>> "," <e: T> => {let mut es = es; es.push(e); es },
  <e: T> => vec![e],
}

object: (&'source str, value::Value<'source>) = {
  <s:string> ":" <v:value> => (s,v),
}

objects: Vec<(&'source str, value::Value<'source>)> = {
  "{" <es: CommaSep<object>> "}" => es,
  "{" "}" => vec![],
}

array: Vec<value::Value<'source>> = {
  "[" <a: CommaSep<value>> "]" => a,
  "[" "]" => vec![],
}