use super::values::*;
use super::verbs::*;
extern crate pest;
use pest::error::Error;
use pest::Parser;
#[derive(Parser)]
#[grammar = "fql.pest"]
struct FQLParser;
pub fn parse_expr(expr: &str) -> Result<FQLValue, Error<Rule>> {
let result = FQLParser::parse(Rule::fql, expr)
.map_err(|err| err.renamed_rules(|rule| {
match *rule {
Rule::object => "Object".to_owned(),
Rule::array => "Array".to_owned(),
Rule::string => "String".to_owned(),
Rule::number => "Number".to_owned(),
Rule::boolean => "Boolean".to_owned(),
Rule::null => "null".to_owned(),
Rule::fqlExpr => "Expression".to_owned(),
Rule::op => "Opening delimiter '('".to_owned(),
Rule::cp => "Closing delimiter ')'".to_owned(),
Rule::osb => "Opening delimiter '['".to_owned(),
Rule::csb => "Closing delimiter ']'".to_owned(),
Rule::ocb => "Opening delimiter '{'".to_owned(),
Rule::ccb => "Closing delimiter '}'".to_owned(),
Rule::comma => "','".to_owned(),
Rule::colon => "':'".to_owned(),
_ => format!("{:?}", rule),
}
}));
let fql = result?.next().unwrap();
use pest::iterators::Pair;
fn parse_value(pair: Pair<Rule>) -> FQLValue {
match pair.as_rule() {
Rule::object => FQLValue::Object(parse_object(pair).unwrap()),
Rule::array => FQLValue::Array(parse_array(pair).unwrap()),
Rule::string => FQLValue::String(pair.into_inner().next().unwrap().as_str()),
Rule::number => FQLValue::Number(pair.as_str().parse().unwrap()),
Rule::boolean => FQLValue::Boolean(pair.as_str().parse().unwrap()),
Rule::niladicExpr => FQLValue::NiladicVerb(parse_niladic_verb(pair).unwrap()),
Rule::monadicExpr => FQLValue::MonadicVerb(parse_monadic_verb(pair).unwrap()),
Rule::dyadicExpr => FQLValue::DyadicVerb(parse_dyadic_verb(pair).unwrap()),
Rule::triadicExpr => FQLValue::TriadicVerb(parse_triadic_verb(pair).unwrap()),
Rule::quadraticExpr => FQLValue::QuadraticVerb(parse_quadratic_verb(pair).unwrap()),
Rule::variadicExpr => FQLValue::VariadicVerb(parse_variadic_verb(pair).unwrap()),
Rule::null => FQLValue::Null,
Rule::fqlExpr => parse_value(pair.into_inner().nth(0).unwrap()),
_ => panic!("Parsing Error: unexpected token '{}'", pair.as_str()),
}
}
fn filter_delimiters(pair: &Pair<Rule>) -> bool {
match pair.as_rule() {
Rule::op |
Rule::cp |
Rule::osb |
Rule::csb |
Rule::ocb |
Rule::ccb |
Rule::comma |
Rule::colon => false,
_ => true
}
}
fn parse_array(pair: Pair<Rule>) -> Result<Vec<FQLValue>, Error<Rule>> {
Ok(pair.into_inner().filter(filter_delimiters).map(parse_value).collect())
}
fn parse_object(pair: Pair<Rule>) -> Result<Vec<(&str, FQLValue)>, Error<Rule>> {
Ok(
pair
.into_inner()
.filter(filter_delimiters)
.map(|pair| {
let mut inner_rules = pair.into_inner().filter(filter_delimiters);
let name = inner_rules
.next()
.unwrap()
.into_inner()
.next()
.unwrap()
.as_str();
let value = parse_value(inner_rules.next().unwrap());
(name, value)
})
.collect(),
)
}
fn parse_niladic_verb(pair: Pair<Rule>) -> Result<NiladicVerb, Error<Rule>> {
let mut inner_rules = pair.into_inner().filter(filter_delimiters);
let verb = inner_rules.next().unwrap().as_str();
Ok(NiladicVerb { verb })
}
fn parse_monadic_verb(pair: Pair<Rule>) -> Result<MonadicVerb, Error<Rule>> {
let mut inner_rules = pair.into_inner().filter(filter_delimiters);
let verb = inner_rules.next().unwrap().as_str();
let args: Vec<FQLValue> = inner_rules.map(parse_value).collect();
Ok(MonadicVerb { verb, args })
}
fn parse_dyadic_verb(pair: Pair<Rule>) -> Result<DyadicVerb, Error<Rule>> {
let mut inner_rules = pair.into_inner().filter(filter_delimiters);
let verb = inner_rules.next().unwrap().as_str();
let args: Vec<FQLValue> = inner_rules.map(parse_value).collect();
Ok(DyadicVerb { verb, args })
}
fn parse_triadic_verb(pair: Pair<Rule>) -> Result<TriadicVerb, Error<Rule>> {
let mut inner_rules = pair.into_inner().filter(filter_delimiters);
let verb = inner_rules.next().unwrap().as_str();
let args: Vec<FQLValue> = inner_rules.map(parse_value).collect();
Ok(TriadicVerb { verb, args })
}
fn parse_quadratic_verb(pair: Pair<Rule>) -> Result<QuadraticVerb, Error<Rule>> {
let mut inner_rules = pair.into_inner().filter(filter_delimiters);
let verb = inner_rules.next().unwrap().as_str();
let args: Vec<FQLValue> = inner_rules.map(parse_value).collect();
Ok(QuadraticVerb { verb, args })
}
fn parse_variadic_verb(pair: Pair<Rule>) -> Result<VariadicVerb, Error<Rule>> {
let mut inner_rules = pair.into_inner().filter(filter_delimiters);
let verb = inner_rules.next().unwrap().as_str();
let args: Vec<FQLValue> = inner_rules.map(parse_value).collect();
Ok(VariadicVerb { verb, args })
}
Ok(parse_value(fql))
}