Improve graph traversal expression parsing code

This commit is contained in:
Tobie Morgan Hitchcock 2022-06-08 19:50:29 +01:00
parent 1333ecf0df
commit 8ce5d01727

View file

@ -1,10 +1,10 @@
use crate::sql::comment::mightbespace; use crate::sql::comment::mightbespace;
use crate::sql::comment::shouldbespace; use crate::sql::comment::shouldbespace;
use crate::sql::cond::{cond, Cond};
use crate::sql::dir::{dir, Dir}; use crate::sql::dir::{dir, Dir};
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::idiom::{idiom, Idiom}; use crate::sql::idiom::{idiom, Idiom};
use crate::sql::table::{table, tables, Tables}; use crate::sql::table::{table, tables, Tables};
use crate::sql::value::{value, Value};
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag_no_case; use nom::bytes::complete::tag_no_case;
use nom::character::complete::char; use nom::character::complete::char;
@ -17,7 +17,7 @@ use std::fmt;
pub struct Graph { pub struct Graph {
pub dir: Dir, pub dir: Dir,
pub what: Tables, pub what: Tables,
pub cond: Option<Value>, pub cond: Option<Cond>,
pub alias: Option<Idiom>, pub alias: Option<Idiom>,
} }
@ -36,7 +36,7 @@ impl fmt::Display for Graph {
_ => write!(f, "{}", self.what), _ => write!(f, "{}", self.what),
}?; }?;
if let Some(ref v) = self.cond { if let Some(ref v) = self.cond {
write!(f, " WHERE {}", v)? write!(f, " {}", v)?
} }
if let Some(ref v) = self.alias { if let Some(ref v) = self.alias {
write!(f, " AS {}", v)? write!(f, " AS {}", v)?
@ -47,17 +47,12 @@ impl fmt::Display for Graph {
} }
pub fn graph(i: &str) -> IResult<&str, Graph> { pub fn graph(i: &str) -> IResult<&str, Graph> {
alt((graph_in, graph_out, graph_both))(i) let (i, dir) = dir(i)?;
}
fn graph_in(i: &str) -> IResult<&str, Graph> {
let (i, _) = char('<')(i)?;
let (i, _) = char('-')(i)?;
let (i, (what, cond, alias)) = alt((simple, custom))(i)?; let (i, (what, cond, alias)) = alt((simple, custom))(i)?;
Ok(( Ok((
i, i,
Graph { Graph {
dir: Dir::In, dir,
what, what,
cond, cond,
alias, alias,
@ -65,81 +60,39 @@ fn graph_in(i: &str) -> IResult<&str, Graph> {
)) ))
} }
fn graph_out(i: &str) -> IResult<&str, Graph> { fn simple(i: &str) -> IResult<&str, (Tables, Option<Cond>, Option<Idiom>)> {
let (i, _) = char('-')(i)?; let (i, w) = alt((any, one))(i)?;
let (i, _) = char('>')(i)?;
let (i, (what, cond, alias)) = alt((simple, custom))(i)?;
Ok((
i,
Graph {
dir: Dir::Out,
what,
cond,
alias,
},
))
}
fn graph_both(i: &str) -> IResult<&str, Graph> {
let (i, _) = char('<')(i)?;
let (i, _) = char('-')(i)?;
let (i, _) = char('>')(i)?;
let (i, (what, cond, alias)) = alt((simple, custom))(i)?;
Ok((
i,
Graph {
dir: Dir::Both,
what,
cond,
alias,
},
))
}
fn simple(i: &str) -> IResult<&str, (Tables, Option<Value>, Option<Idiom>)> {
let (i, w) = alt((any, single))(i)?;
Ok((i, (w, None, None))) Ok((i, (w, None, None)))
} }
fn custom(i: &str) -> IResult<&str, (Tables, Option<Value>, Option<Idiom>)> { fn custom(i: &str) -> IResult<&str, (Tables, Option<Cond>, Option<Idiom>)> {
let (i, _) = char('(')(i)?; let (i, _) = char('(')(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, w) = alt((any, multi))(i)?; let (i, w) = alt((any, tables))(i)?;
let (i, c) = opt(cond)(i)?; let (i, c) = opt(|i| {
let (i, a) = opt(alias)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char(')')(i)?;
Ok((i, (w, c, a)))
}
fn single(i: &str) -> IResult<&str, Tables> {
let (i, v) = table(i)?;
Ok((i, Tables::from(v)))
}
fn multi(i: &str) -> IResult<&str, Tables> {
let (i, v) = tables(i)?;
Ok((i, Tables::from(v)))
}
fn any(i: &str) -> IResult<&str, Tables> {
map(char('?'), |_| Tables::default())(i)
}
fn cond(i: &str) -> IResult<&str, Value> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("WHERE")(i)?; let (i, v) = cond(i)?;
let (i, _) = shouldbespace(i)?;
let (i, v) = value(i)?;
Ok((i, v)) Ok((i, v))
} })(i)?;
let (i, a) = opt(|i| {
fn alias(i: &str) -> IResult<&str, Idiom> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("AS")(i)?; let (i, _) = tag_no_case("AS")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, v) = idiom(i)?; let (i, v) = idiom(i)?;
Ok((i, v)) Ok((i, v))
})(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char(')')(i)?;
Ok((i, (w, c, a)))
}
fn one(i: &str) -> IResult<&str, Tables> {
let (i, v) = table(i)?;
Ok((i, Tables::from(v)))
}
fn any(i: &str) -> IResult<&str, Tables> {
map(char('?'), |_| Tables::default())(i)
} }
#[cfg(test)] #[cfg(test)]