1616 *
1717 */
1818
19- use std:: str:: FromStr ;
19+ use std:: { borrow :: Cow , str:: FromStr } ;
2020
2121use nom:: {
2222 branch:: alt,
23- bytes:: complete:: { tag , take_until , take_while1} ,
23+ bytes:: complete:: { is_not , tag , take_while1} ,
2424 character:: complete:: { char, multispace0, multispace1} ,
25- combinator:: map,
26- sequence:: { delimited, separated_pair} ,
27- IResult ,
25+ combinator:: { cut, map, value} ,
26+ error:: { convert_error, VerboseError } ,
27+ sequence:: { delimited, preceded, separated_pair} ,
28+ IResult as NomIResult , Parser ,
2829} ;
2930
3031use super :: rule:: {
@@ -35,7 +36,69 @@ use super::rule::{
3536 CompositeRule ,
3637} ;
3738
38- fn parse_numeric_op ( input : & str ) -> IResult < & str , NumericOperator > {
39+ type IResult < ' a , O > = NomIResult < & ' a str , O , VerboseError < & ' a str > > ;
40+
41+ enum StrFragment < ' a > {
42+ Escaped ( char ) ,
43+ Unescaped ( & ' a str ) ,
44+ }
45+
46+ fn parse_escaped_char ( input : & str ) -> IResult < char > {
47+ preceded (
48+ char ( '\\' ) ,
49+ alt ( (
50+ value ( '"' , char ( '"' ) ) ,
51+ value ( '\\' , char ( '\\' ) ) ,
52+ value ( '/' , char ( '/' ) ) ,
53+ value ( '\n' , char ( 'n' ) ) ,
54+ value ( '\r' , char ( 'r' ) ) ,
55+ value ( '\t' , char ( 't' ) ) ,
56+ value ( '\u{08}' , char ( 'b' ) ) ,
57+ value ( '\u{0C}' , char ( 'f' ) ) ,
58+ ) ) ,
59+ )
60+ . parse ( input)
61+ }
62+
63+ fn parse_str_char ( input : & str ) -> IResult < StrFragment > {
64+ alt ( (
65+ map ( parse_escaped_char, StrFragment :: Escaped ) ,
66+ map ( is_not ( r#""\"# ) , StrFragment :: Unescaped ) ,
67+ ) )
68+ . parse ( input)
69+ }
70+
71+ fn parse_string ( input : & str ) -> IResult < Cow < str > > {
72+ let mut res = Cow :: Borrowed ( "" ) ;
73+ let ( mut input, _) = char ( '"' ) . parse ( input) ?;
74+
75+ loop {
76+ match char ( '"' ) . parse ( input) {
77+ // If it is terminating double quotes then we can return the ok value
78+ Ok ( ( tail, _) ) => return Ok ( ( tail, res) ) ,
79+ // Fail to parsing in recoverable variant can mean it is a valid char that is not double quote
80+ Err ( nom:: Err :: Error ( _) ) => { }
81+ Err ( err) => return Err ( err) ,
82+ } ;
83+
84+ input = match cut ( parse_str_char) ( input) ? {
85+ ( tail, StrFragment :: Escaped ( ch) ) => {
86+ res. to_mut ( ) . push ( ch) ;
87+ tail
88+ }
89+ ( tail, StrFragment :: Unescaped ( s) ) => {
90+ if res. is_empty ( ) {
91+ res = Cow :: Borrowed ( s)
92+ } else {
93+ res. to_mut ( ) . push_str ( s)
94+ }
95+ tail
96+ }
97+ } ;
98+ }
99+ }
100+
101+ fn parse_numeric_op ( input : & str ) -> IResult < NumericOperator > {
39102 alt ( (
40103 map ( tag ( "<=" ) , |_| NumericOperator :: LessThanEquals ) ,
41104 map ( tag ( ">=" ) , |_| NumericOperator :: GreaterThanEquals ) ,
@@ -46,7 +109,7 @@ fn parse_numeric_op(input: &str) -> IResult<&str, NumericOperator> {
46109 ) ) ( input)
47110}
48111
49- fn parse_string_op ( input : & str ) -> IResult < & str , StringOperator > {
112+ fn parse_string_op ( input : & str ) -> IResult < StringOperator > {
50113 alt ( (
51114 map ( tag ( "!=" ) , |_| StringOperator :: NotExact ) ,
52115 map ( tag ( "=%" ) , |_| StringOperator :: Contains ) ,
@@ -56,7 +119,7 @@ fn parse_string_op(input: &str) -> IResult<&str, StringOperator> {
56119 ) ) ( input)
57120}
58121
59- fn parse_numeric_rule ( input : & str ) -> IResult < & str , CompositeRule > {
122+ fn parse_numeric_rule ( input : & str ) -> IResult < CompositeRule > {
60123 let ( remaining, key) = map ( parse_identifier, |s : & str | s. to_string ( ) ) ( input) ?;
61124 let ( remaining, op) = delimited ( multispace0, parse_numeric_op, multispace0) ( remaining) ?;
62125 let ( remaining, value) = map ( take_while1 ( |c : char | c. is_ascii_digit ( ) ) , |x| {
@@ -73,84 +136,92 @@ fn parse_numeric_rule(input: &str) -> IResult<&str, CompositeRule> {
73136 ) )
74137}
75138
76- fn parse_string_rule ( input : & str ) -> IResult < & str , CompositeRule > {
139+ fn parse_string_rule ( input : & str ) -> IResult < CompositeRule > {
77140 let ( remaining, key) = map ( parse_identifier, |s : & str | s. to_string ( ) ) ( input) ?;
78141 let ( remaining, op) = delimited ( multispace0, parse_string_op, multispace0) ( remaining) ?;
79- let ( remaining, value) = map (
80- delimited ( char ( '"' ) , take_until ( "\" " ) , char ( '"' ) ) ,
81- |x : & str | x. to_string ( ) ,
82- ) ( remaining) ?;
142+ let ( remaining, value) = parse_string ( remaining) ?;
83143
84144 Ok ( (
85145 remaining,
86146 CompositeRule :: String ( StringRule {
87147 column : key,
88148 operator : op,
89- value,
149+ value : value . into_owned ( ) ,
90150 ignore_case : None ,
91151 } ) ,
92152 ) )
93153}
94154
95- fn parse_identifier ( input : & str ) -> IResult < & str , & str > {
155+ fn parse_identifier ( input : & str ) -> IResult < & str > {
96156 take_while1 ( |c : char | c. is_alphanumeric ( ) || c == '-' || c == '_' ) ( input)
97157}
98158
99- fn parse_unary_expr ( input : & str ) -> IResult < & str , CompositeRule > {
100- map ( delimited ( tag ( "!(" ) , parse_expression, char ( ')' ) ) , |x| {
101- CompositeRule :: Not ( Box :: new ( x) )
102- } ) ( input)
159+ fn parse_unary_expr ( input : & str ) -> IResult < CompositeRule > {
160+ map (
161+ delimited ( tag ( "!(" ) , cut ( parse_expression) , char ( ')' ) ) ,
162+ |x| CompositeRule :: Not ( Box :: new ( x) ) ,
163+ ) ( input)
103164}
104165
105- fn parse_bracket_expr ( input : & str ) -> IResult < & str , CompositeRule > {
166+ fn parse_bracket_expr ( input : & str ) -> IResult < CompositeRule > {
106167 delimited (
107168 char ( '(' ) ,
108- delimited ( multispace0, parse_expression, multispace0) ,
109- char ( ')' ) ,
169+ delimited ( multispace0, cut ( parse_expression) , multispace0) ,
170+ cut ( char ( ')' ) ) ,
110171 ) ( input)
111172}
112173
113- fn parse_and ( input : & str ) -> IResult < & str , CompositeRule > {
174+ fn parse_and ( input : & str ) -> IResult < CompositeRule > {
114175 let ( remaining, ( lhs, rhs) ) = separated_pair (
115176 parse_atom,
116177 delimited ( multispace1, tag ( "and" ) , multispace1) ,
117- parse_term,
178+ cut ( parse_term) ,
118179 ) ( input) ?;
119180
120181 Ok ( ( remaining, CompositeRule :: And ( vec ! [ lhs, rhs] ) ) )
121182}
122183
123- fn parse_or ( input : & str ) -> IResult < & str , CompositeRule > {
184+ fn parse_or ( input : & str ) -> IResult < CompositeRule > {
124185 let ( remaining, ( lhs, rhs) ) = separated_pair (
125186 parse_term,
126187 delimited ( multispace1, tag ( "or" ) , multispace1) ,
127- parse_expression,
188+ cut ( parse_expression) ,
128189 ) ( input) ?;
129190
130191 Ok ( ( remaining, CompositeRule :: Or ( vec ! [ lhs, rhs] ) ) )
131192}
132193
133- fn parse_expression ( input : & str ) -> IResult < & str , CompositeRule > {
194+ fn parse_expression ( input : & str ) -> IResult < CompositeRule > {
134195 alt ( ( parse_or, parse_term) ) ( input)
135196}
136- fn parse_term ( input : & str ) -> IResult < & str , CompositeRule > {
197+
198+ fn parse_term ( input : & str ) -> IResult < CompositeRule > {
137199 alt ( ( parse_and, parse_atom) ) ( input)
138200}
139- fn parse_atom ( input : & str ) -> IResult < & str , CompositeRule > {
201+
202+ fn parse_atom ( input : & str ) -> IResult < CompositeRule > {
140203 alt ( (
141- alt ( ( parse_numeric_rule , parse_string_rule ) ) ,
204+ alt ( ( parse_string_rule , parse_numeric_rule ) ) ,
142205 parse_unary_expr,
143206 parse_bracket_expr,
144207 ) ) ( input)
145208}
146209
147210impl FromStr for CompositeRule {
148- type Err = Box < dyn std :: error :: Error > ;
211+ type Err = String ;
149212
150213 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
151- parse_expression ( s)
152- . map ( |( _, x) | x)
153- . map_err ( |x| x. to_string ( ) . into ( ) )
214+ let s = s. trim ( ) ;
215+ let ( remaining, parsed) = parse_expression ( s) . map_err ( |err| match err {
216+ nom:: Err :: Incomplete ( _) => "Needed more data" . to_string ( ) ,
217+ nom:: Err :: Error ( err) | nom:: Err :: Failure ( err) => convert_error ( s, err) ,
218+ } ) ?;
219+
220+ if remaining. is_empty ( ) {
221+ Ok ( parsed)
222+ } else {
223+ Err ( format ! ( "Could not parse input \n {}" , remaining) )
224+ }
154225 }
155226}
156227
0 commit comments