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![],
}