use combine; use combine::{between, char, letter, spaces, space, many1, parser, sep_by1, Parser, ParseError, ParserExt, combinator}; use combine::primitives::{State, Stream, ParseResult}; #[derive(Debug, PartialEq)] pub struct Term(pub String, pub String); #[derive(Debug, PartialEq)] pub enum BoolQuery { AlwaysTrue, Conjunction(Vec), } pub fn grammar(input: State) -> ParseResult, I> where I: Stream { let make_term = || { let term_field: combinator::Many1 = many1(letter()); let term_value: combinator::Many1 = many1(letter()); (term_field, char(':'), term_value).map(|t| Term(t.0.clone(), t.2.clone())) }; // let term_seqs = (make_term(), space(), parser(grammar::),).map(|t| BoolExpr::AlwaysTrue); sep_by1(make_term(), space()) .parse_state(input) // make_term().or(term_seqs).parse_state(input) //make_term() // // let word = many1(letter()); // //Creates a parser which parses a char and skips any trailing whitespace // let lex_char = |c| char(c).skip(spaces()); // // let comma_list = sep_by(parser(expr::), lex_char(',')); // let array = between(lex_char('['), lex_char(']'), comma_list); // // //We can use tuples to run several parsers in sequence // //The resulting type is a tuple containing each parsers output // let pair = (lex_char('('), // parser(expr::), // lex_char(','), // parser(expr::), // lex_char(')')) // .map(|t| Expr::Pair(Box::new(t.1), Box::new(t.3))); // // word.map(Expr::Id) // .or(array.map(Expr::Array)) // .or(pair) // .skip(spaces()) // .parse_state(input) } pub fn parse_query(query_str: &str) -> Result<(Vec, &str), ParseError<&str>> { parser(grammar).parse(query_str) } #[test] fn test_parse_query() { { let (parsed_query, _) = parse_query("toto:titi toto:tutu").unwrap(); assert_eq!(parsed_query, vec!(query::Term(String::from("toto"), String::from("titi")), query::Term(String::from("toto"), String::from("tutu")))); } }