-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwhere_clause.rs
125 lines (111 loc) · 3.38 KB
/
where_clause.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::{get_clause::node_path, set_clause::value_variant};
use nom::{
bytes::complete::{tag, tag_no_case, take_till},
character::complete::multispace1,
combinator::opt,
multi::separated_list1,
IResult, Parser,
};
use xml_mut_data::{
NodePath, PathVariant, Predicate, PredicateEquals, PredicateExists, ValuePath, ValueSelector,
WhereClause,
};
pub fn value_source(s: &str) -> IResult<&str, ValueSelector> {
let (s, _) = tag("[")(s)?;
let (s, at) = opt(tag("@")).parse(s)?;
let (s, name) = take_till(|c: char| c == ']')(s)?;
let (s, _) = tag("]")(s)?;
Ok(if at.is_some() {
(s, ValueSelector::Attribute(name))
} else {
match name {
"text" => (s, ValueSelector::Text),
"tail" => (s, ValueSelector::Tail),
"name" => (s, ValueSelector::Name),
_ => {
return Err(nom::Err::Error(nom::error::Error {
code: nom::error::ErrorKind::Tag,
input: name,
}))
}
}
})
}
pub fn value_path(s: &str) -> IResult<&str, ValuePath> {
let (s, node_path) = opt(node_path).parse(s)?;
let (s, source) = value_source(s)?;
Ok(if let Some(node_path) = node_path {
(
s,
ValuePath {
node_path,
selector: source,
},
)
} else {
(
s,
ValuePath {
node_path: NodePath { path: vec![] },
selector: source,
},
)
})
}
// TODO: non desttructive parse of node path or value selector
pub fn path_variant(s: &str) -> IResult<&str, PathVariant> {
let (s, value) = opt(value_path).parse(s)?;
if let Some(value) = value {
Ok((s, PathVariant::Value(value)))
} else {
let (s, path) = node_path(s)?;
Ok((s, PathVariant::Node(path)))
}
}
pub fn predicate_node_exists(s: &str) -> IResult<&str, PredicateExists> {
let (s, exists_word) = tag_no_case("exists")(s)?;
let (s, _) = multispace1(s)?;
let (s, path) = path_variant(s)?;
Ok((s, PredicateExists { exists_word, path }))
}
pub fn predicate_equals(s: &str) -> IResult<&str, PredicateEquals> {
let (s, left_side) = value_path(s)?;
let (s, _) = multispace1(s)?;
let (s, _) = tag("==")(s)?;
let (s, _) = multispace1(s)?;
let (s, right_side) = value_variant(s)?;
Ok((
s,
PredicateEquals {
left_side,
right_side,
},
))
}
pub fn predicate(s: &str) -> IResult<&str, Predicate> {
let (s, maybe_p_node_exists) = opt(predicate_node_exists).parse(s)?;
Ok(if let Some(p_node_exists) = maybe_p_node_exists {
(s, Predicate::Exists(p_node_exists))
} else {
let (s, p_equals) = predicate_equals(s)?;
(s, Predicate::Equals(p_equals))
})
}
fn and_surounded_mulispace1(s: &str) -> IResult<&str, &str> {
let (s, _) = multispace1(s)?;
let (s, and_word) = tag_no_case("and")(s)?;
let (s, _) = multispace1(s)?;
Ok((s, and_word))
}
pub fn where_clause(s: &str) -> IResult<&str, WhereClause> {
let (s, where_word) = tag_no_case("where")(s)?;
let (s, _) = multispace1(s)?;
let (s, predicates) = separated_list1(and_surounded_mulispace1, predicate).parse(s)?;
Ok((
s,
WhereClause {
where_word,
predicates,
},
))
}