@@ -11,7 +11,9 @@ use pest::pratt_parser::Assoc as AssocNew;
1111use pest:: pratt_parser:: { Op , PrattParser } ;
1212use pest:: Parser ;
1313use regex:: Regex ;
14+ use std:: collections:: HashMap ;
1415use std:: net:: { IpAddr , Ipv4Addr , Ipv6Addr } ;
16+ use std:: rc:: Rc ;
1517
1618type ParseResult < T > = Result < T , ParseError < Rule > > ;
1719/// cbindgen:ignore
@@ -59,12 +61,16 @@ impl ATCParser {
5961 }
6062 }
6163 // matcher = { SOI ~ expression ~ EOI }
62- fn parse_matcher ( & mut self , source : & str ) -> ParseResult < Expression > {
64+ fn parse_matcher (
65+ & mut self ,
66+ source : & str ,
67+ regex_cache : & mut HashMap < String , Rc < Regex > > ,
68+ ) -> ParseResult < Expression > {
6369 let pairs = ATCParser :: parse ( Rule :: matcher, source) ?;
6470 let expr_pair = pairs. peek ( ) . unwrap ( ) . into_inner ( ) . peek ( ) . unwrap ( ) ;
6571 let rule = expr_pair. as_rule ( ) ;
6672 match rule {
67- Rule :: expression => parse_expression ( expr_pair, & self . pratt_parser ) ,
73+ Rule :: expression => parse_expression ( expr_pair, & self . pratt_parser , regex_cache ) ,
6874 _ => unreachable ! ( ) ,
6975 }
7076 }
@@ -185,7 +191,10 @@ fn parse_int_literal(pair: Pair<Rule>) -> ParseResult<i64> {
185191}
186192
187193// predicate = { lhs ~ binary_operator ~ rhs }
188- fn parse_predicate ( pair : Pair < Rule > ) -> ParseResult < Predicate > {
194+ fn parse_predicate (
195+ pair : Pair < Rule > ,
196+ regex_cache : & mut HashMap < String , Rc < Regex > > ,
197+ ) -> ParseResult < Predicate > {
189198 let mut pairs = pair. into_inner ( ) ;
190199 let lhs = parse_lhs ( pairs. next ( ) . unwrap ( ) ) ?;
191200 let op = parse_binary_operator ( pairs. next ( ) . unwrap ( ) ) ;
@@ -195,16 +204,26 @@ fn parse_predicate(pair: Pair<Rule>) -> ParseResult<Predicate> {
195204 lhs,
196205 rhs : if op == BinaryOperator :: Regex {
197206 if let Value :: String ( s) = rhs {
198- let r = Regex :: new ( & s) . map_err ( |e| {
199- ParseError :: new_from_span (
200- ErrorVariant :: CustomError {
201- message : e. to_string ( ) ,
202- } ,
203- rhs_pair. as_span ( ) ,
204- )
205- } ) ?;
207+ let regex_rc = match regex_cache. get ( & s) {
208+ Some ( stored_regex_rc) => stored_regex_rc. clone ( ) ,
209+ _ => {
210+ let r = Regex :: new ( & s) . map_err ( |e| {
211+ ParseError :: new_from_span (
212+ ErrorVariant :: CustomError {
213+ message : e. to_string ( ) ,
214+ } ,
215+ rhs_pair. as_span ( ) ,
216+ )
217+ } ) ?;
218+
219+ let rc = Rc :: new ( r) ;
206220
207- Value :: Regex ( r)
221+ regex_cache. insert ( s, rc. clone ( ) ) ;
222+ rc
223+ }
224+ } ;
225+
226+ Value :: Regex ( regex_rc)
208227 } else {
209228 return Err ( ParseError :: new_from_span (
210229 ErrorVariant :: CustomError {
@@ -267,37 +286,51 @@ fn parse_binary_operator(pair: Pair<Rule>) -> BinaryOperator {
267286fn parse_parenthesised_expression (
268287 pair : Pair < Rule > ,
269288 pratt : & PrattParser < Rule > ,
289+ regex_cache : & mut HashMap < String , Rc < Regex > > ,
270290) -> ParseResult < Expression > {
271291 let mut pairs = pair. into_inner ( ) ;
272292 let pair = pairs. next ( ) . unwrap ( ) ;
273293 let rule = pair. as_rule ( ) ;
274294 match rule {
275- Rule :: expression => parse_expression ( pair, pratt) ,
295+ Rule :: expression => parse_expression ( pair, pratt, regex_cache ) ,
276296 Rule :: not_op => Ok ( Expression :: Logical ( Box :: new ( LogicalExpression :: Not (
277- parse_expression ( pairs. next ( ) . unwrap ( ) , pratt) ?,
297+ parse_expression ( pairs. next ( ) . unwrap ( ) , pratt, regex_cache ) ?,
278298 ) ) ) ) ,
279299 _ => unreachable ! ( ) ,
280300 }
281301}
282302
283303// term = { predicate | parenthesised_expression }
284- fn parse_term ( pair : Pair < Rule > , pratt : & PrattParser < Rule > ) -> ParseResult < Expression > {
304+ fn parse_term (
305+ pair : Pair < Rule > ,
306+ pratt : & PrattParser < Rule > ,
307+ regex_cache : & mut HashMap < String , Rc < Regex > > ,
308+ ) -> ParseResult < Expression > {
285309 let pairs = pair. into_inner ( ) ;
286310 let inner_rule = pairs. peek ( ) . unwrap ( ) ;
287311 let rule = inner_rule. as_rule ( ) ;
288312 match rule {
289- Rule :: predicate => Ok ( Expression :: Predicate ( parse_predicate ( inner_rule) ?) ) ,
290- Rule :: parenthesised_expression => parse_parenthesised_expression ( inner_rule, pratt) ,
313+ Rule :: predicate => Ok ( Expression :: Predicate ( parse_predicate (
314+ inner_rule,
315+ regex_cache,
316+ ) ?) ) ,
317+ Rule :: parenthesised_expression => {
318+ parse_parenthesised_expression ( inner_rule, pratt, regex_cache)
319+ }
291320 _ => unreachable ! ( ) ,
292321 }
293322}
294323
295324// expression = { term ~ ( logical_operator ~ term )* }
296- fn parse_expression ( pair : Pair < Rule > , pratt : & PrattParser < Rule > ) -> ParseResult < Expression > {
325+ fn parse_expression (
326+ pair : Pair < Rule > ,
327+ pratt : & PrattParser < Rule > ,
328+ regex_cache : & mut HashMap < String , Rc < Regex > > ,
329+ ) -> ParseResult < Expression > {
297330 let pairs = pair. into_inner ( ) ;
298331 pratt
299332 . map_primary ( |operand| match operand. as_rule ( ) {
300- Rule :: term => parse_term ( operand, pratt) ,
333+ Rule :: term => parse_term ( operand, pratt, regex_cache ) ,
301334 _ => unreachable ! ( ) ,
302335 } )
303336 . map_infix ( |lhs, op, rhs| {
@@ -310,8 +343,11 @@ fn parse_expression(pair: Pair<Rule>, pratt: &PrattParser<Rule>) -> ParseResult<
310343 . parse ( pairs)
311344}
312345
313- pub fn parse ( source : & str ) -> ParseResult < Expression > {
314- ATCParser :: new ( ) . parse_matcher ( source)
346+ pub fn parse (
347+ source : & str ,
348+ regex_cache : & mut HashMap < String , Rc < Regex > > ,
349+ ) -> ParseResult < Expression > {
350+ ATCParser :: new ( ) . parse_matcher ( source, regex_cache)
315351}
316352
317353#[ cfg( test) ]
@@ -320,16 +356,19 @@ mod tests {
320356
321357 #[ test]
322358 fn test_bad_syntax ( ) {
359+ let mut regex_cache = HashMap :: new ( ) ;
323360 assert_eq ! (
324- parse( "! a == 1" ) . unwrap_err( ) . to_string( ) ,
361+ parse( "! a == 1" , & mut regex_cache ) . unwrap_err( ) . to_string( ) ,
325362 " --> 1:1\n |\n 1 | ! a == 1\n | ^---\n |\n = expected term"
326363 ) ;
327364 assert_eq ! (
328- parse( "a == 1 || ! b == 2" ) . unwrap_err( ) . to_string( ) ,
365+ parse( "a == 1 || ! b == 2" , & mut regex_cache)
366+ . unwrap_err( )
367+ . to_string( ) ,
329368 " --> 1:11\n |\n 1 | a == 1 || ! b == 2\n | ^---\n |\n = expected term"
330369 ) ;
331370 assert_eq ! (
332- parse( "(a == 1 || b == 2) && ! c == 3" )
371+ parse( "(a == 1 || b == 2) && ! c == 3" , & mut regex_cache )
333372 . unwrap_err( )
334373 . to_string( ) ,
335374 " --> 1:23\n |\n 1 | (a == 1 || b == 2) && ! c == 3\n | ^---\n |\n = expected term"
0 commit comments