<s> import re <EOL> import json <EOL> import collections <EOL> from . import atoms <EOL> from . import rules <EOL> from . import iprange <EOL> from . import _domainname <EOL> from . parsing import parser_singleton , transform , seq , txt , epsilon , forward_ref , union , maybe , step , step_default <EOL> class Formatter ( object ) : <EOL> def __init__ ( self ) : <EOL> self . _types = { } <EOL> def add ( self , type_ , func ) : <EOL> self . _types [ type_ ] = func <EOL> def handler ( self , type_ ) : <EOL> def _formatter ( func ) : <EOL> self . add ( type_ , func ) <EOL> return func <EOL> return _formatter <EOL> def _format_gen ( self , obj ) : <EOL> type_ = type ( obj ) <EOL> func = self . _types . get ( type_ ) <EOL> if func is None : <EOL> raise TypeError ( "<STR_LIT>" + repr ( type_ ) ) <EOL> return func ( self . _format_gen , obj ) <EOL> def _format ( self , obj ) : <EOL> stack = [ self . _format_gen ( obj ) ] <EOL> while stack : <EOL> try : <EOL> value = stack [ - <NUM_LIT:1> ] . next ( ) <EOL> except StopIteration : <EOL> stack . pop ( ) <EOL> continue <EOL> if not isinstance ( value , basestring ) : <EOL> stack . append ( iter ( value ) ) <EOL> continue <EOL> yield value <EOL> def format ( self , obj ) : <EOL> return "<STR_LIT>" . join ( self . _format ( obj ) ) <EOL> formatter = Formatter ( ) <EOL> unquoted_rex = re . compile ( r"<STR_LIT>" ) <EOL> quoted_rex = re . compile ( r'<STR_LIT>' ) <EOL> @ parser_singleton <EOL> def string_parser ( ( string , start , end ) ) : <EOL> if not start < end : <EOL> yield None , None <EOL> if string [ start ] == '<STR_LIT:">' : <EOL> match = quoted_rex . match ( string , start , end ) <EOL> if not match : <EOL> yield None , None <EOL> value = json . loads ( match . group ( <NUM_LIT:1> ) ) <EOL> start = match . end ( ) <EOL> else : <EOL> match = unquoted_rex . match ( string , start , end ) <EOL> if not match : <EOL> yield None , None <EOL> value = match . group ( <NUM_LIT:1> ) <EOL> start = match . end ( ) <EOL> yield None , ( atoms . String ( value ) , ( string , start , end ) ) <EOL> @ formatter . handler ( atoms . RegExp ) <EOL> def format_regexp ( format , regexp ) : <EOL> escape_slash_rex = re . compile ( r"<STR_LIT>" , re . U ) <EOL> def escape_slash ( match ) : <EOL> return match . group ( <NUM_LIT:1> ) + match . group ( <NUM_LIT:2> ) . replace ( "<STR_LIT:/>" , "<STR_LIT>" ) <EOL> pattern = regexp . pattern <EOL> pattern = escape_slash_rex . sub ( escape_slash , pattern ) <EOL> result = "<STR_LIT:/>" + pattern + "<STR_LIT:/>" <EOL> if regexp . ignore_case : <EOL> result += "<STR_LIT:i>" <EOL> yield result <EOL> @ formatter . handler ( atoms . String ) <EOL> def format_string ( format , string ) : <EOL> value = string . value <EOL> match = unquoted_rex . match ( value ) <EOL> if match and match . end ( ) == len ( value ) : <EOL> yield value <EOL> else : <EOL> yield json . dumps ( value ) <EOL> ip_parser = transform ( atoms . IP , iprange . IPRange . parser ) <EOL> @ formatter . handler ( atoms . IP ) <EOL> def format_ip ( format , ip ) : <EOL> yield unicode ( ip . range ) <EOL> domainname_parser = transform ( atoms . DomainName , _domainname . pattern_parser ) <EOL> @ formatter . handler ( atoms . DomainName ) <EOL> def format_domainname ( format , name ) : <EOL> yield unicode ( name . pattern ) <EOL> star_parser = seq ( txt ( "<STR_LIT:*>" ) , epsilon ( None ) , pick = <NUM_LIT:1> ) <EOL> @ parser_singleton <EOL> def regexp_parser ( data , rex = re . compile ( r'<STR_LIT>' ) ) : <EOL> string , start , end = data <EOL> if not start < end : <EOL> yield None , None <EOL> if string [ start ] != "<STR_LIT:/>" : <EOL> yield None , None <EOL> match = rex . match ( string , start , end ) <EOL> if not match : <EOL> yield None , None <EOL> ignore_case = match . group ( <NUM_LIT:2> ) is not None <EOL> regexp = atoms . RegExp ( match . group ( <NUM_LIT:1> ) , ignore_case = ignore_case ) <EOL> yield None , ( regexp , ( string , match . end ( ) , end ) ) <EOL> @ formatter . handler ( rules . Anything ) <EOL> def format_anything ( format , anything ) : <EOL> yield "<STR_LIT:*>" <EOL> @ formatter . handler ( rules . Fuzzy ) <EOL> def format_fuzzy ( format , fuzzy ) : <EOL> yield format ( fuzzy . atom ) <EOL> @ formatter . handler ( rules . NonMatch ) <EOL> def format_non_match ( format , obj ) : <EOL> yield format ( obj . key ) if obj . key is not None else "<STR_LIT:*>" <EOL> if isinstance ( obj . value , atoms . IP ) : <EOL> yield "<STR_LIT>" <EOL> else : <EOL> yield "<STR_LIT>" <EOL> yield format ( obj . value ) if obj . value is not None else "<STR_LIT:*>" <EOL> @ formatter . handler ( rules . Match ) <EOL> def format_match ( format , obj ) : <EOL> yield format ( obj . key ) if obj . key is not None else "<STR_LIT:*>" <EOL> if isinstance ( obj . value , atoms . IP ) : <EOL> yield "<STR_LIT>" <EOL> else : <EOL> yield "<STR_LIT:=>" <EOL> yield format ( obj . value ) if obj . value is not None else "<STR_LIT:*>" <EOL> @ formatter . handler ( rules . And ) <EOL> def format_and ( format , rule ) : <EOL> for index , subrule in enumerate ( rule . subrules ) : <EOL> if index != <NUM_LIT:0> : <EOL> yield "<STR_LIT>" <EOL> if isinstance ( subrule , ( rules . No , rules . Match , rules . NonMatch , rules . Fuzzy , rules . Anything ) ) : <EOL> yield format ( subrule ) <EOL> else : <EOL> yield "<STR_LIT:(>" <EOL> yield format ( subrule ) <EOL> yield "<STR_LIT:)>" <EOL> @ formatter . handler ( rules . Or ) <EOL> def format_or ( format , rule ) : <EOL> for index , subrule in enumerate ( rule . subrules ) : <EOL> if index != <NUM_LIT:0> : <EOL> yield "<STR_LIT>" <EOL> if isinstance ( subrule , ( rules . No , rules . Match , rules . NonMatch , rules . Fuzzy , rules . Anything ) ) : <EOL> yield format ( subrule ) <EOL> else : <EOL> yield "<STR_LIT:(>" <EOL> yield format ( subrule ) <EOL> yield "<STR_LIT:)>" <EOL> @ formatter . handler ( rules . No ) <EOL> def format_no ( format , rule ) : <EOL> yield "<STR_LIT>" <EOL> if not isinstance ( rule . subrule , ( rules . No , rules . Match , rules . NonMatch , rules . Fuzzy , rules . Anything ) ) : <EOL> yield "<STR_LIT:(>" <EOL> yield format ( rule . subrule ) <EOL> yield "<STR_LIT:)>" <EOL> else : <EOL> yield format ( rule . subrule ) <EOL> def _create_parser ( ) : <EOL> expr = forward_ref ( ) <EOL> parens_expr = seq ( txt ( "<STR_LIT:(>" ) , expr , txt ( "<STR_LIT:)>" ) , pick = <NUM_LIT:1> ) <EOL> def flatten ( * objs ) : <EOL> objs = collections . deque ( objs ) <EOL> while objs : <EOL> obj = objs . popleft ( ) <EOL> try : <EOL> obj = iter ( obj ) <EOL> except TypeError : <EOL> yield obj <EOL> else : <EOL> objs . extendleft ( obj ) <EOL> @ parser_singleton <EOL> def ws ( ( string , start , end ) , chars = frozenset ( "<STR_LIT>" ) ) : <EOL> if not start < end or string [ start ] not in chars : <EOL> yield None , None <EOL> start += <NUM_LIT:1> <EOL> while start < end and string [ start ] in chars : <EOL> start += <NUM_LIT:1> <EOL> yield None , ( None , ( string , start , end ) ) <EOL> match_tail = union ( <EOL> seq ( maybe ( ws ) , txt ( "<STR_LIT:=>" ) , maybe ( txt ( "<STR_LIT:=>" ) ) , maybe ( ws ) , union ( star_parser , regexp_parser , string_parser ) , pick = - <NUM_LIT:1> ) , <EOL> seq ( ws , txt ( "<STR_LIT>" , ignore_case = True ) , ws , union ( ip_parser , domainname_parser ) , pick = - <NUM_LIT:1> ) , <EOL> ) <EOL> non_match_tail = union ( <EOL> seq ( maybe ( ws ) , txt ( "<STR_LIT>" ) , maybe ( ws ) , union ( star_parser , regexp_parser , string_parser ) , pick = - <NUM_LIT:1> ) , <EOL> seq ( ws , txt ( "<STR_LIT>" , ignore_case = True ) , ws , txt ( "<STR_LIT>" , ignore_case = True ) , ws , union ( ip_parser , domainname_parser ) , pick = - <NUM_LIT:1> ) , <EOL> ) <EOL> basic = union ( <EOL> step ( <EOL> star_parser , <EOL> ( match_tail , rules . Match ) , <EOL> ( non_match_tail , rules . NonMatch ) , <EOL> step_default ( lambda x : rules . Anything ( ) ) <EOL> ) , <EOL> transform ( <EOL> rules . Fuzzy , <EOL> union ( regexp_parser , ip_parser , domainname_parser ) <EOL> ) , <EOL> step ( <EOL> string_parser , <EOL> ( match_tail , rules . Match ) , <EOL> ( non_match_tail , rules . NonMatch ) , <EOL> step_default ( rules . Fuzzy ) <EOL> ) <EOL> ) <EOL> no_parser = forward_ref ( ) <EOL> no_parser . set ( transform ( <EOL> rules . No , <EOL> seq ( <EOL> txt ( "<STR_LIT>" , ignore_case = True ) , <EOL> union ( <EOL> seq ( maybe ( ws ) , parens_expr , pick = <NUM_LIT:1> ) , <EOL> seq ( ws , union ( no_parser , basic ) , pick = <NUM_LIT:1> ) <EOL> ) , <EOL> pick = <NUM_LIT:1> <EOL> ) <EOL> ) ) <EOL> and_tail = forward_ref ( ) <EOL> or_tail = forward_ref ( ) <EOL> def binary_rule_tail ( name ) : <EOL> result = forward_ref ( ) <EOL> result . set ( <EOL> seq ( <EOL> txt ( name , ignore_case = True ) , <EOL> union ( <EOL> step ( <EOL> seq ( maybe ( ws ) , parens_expr , pick = <NUM_LIT:1> ) , <EOL> ( seq ( maybe ( ws ) , result , pick = <NUM_LIT:1> ) , lambda x , y : ( x , y ) ) , <EOL> ( seq ( maybe ( ws ) , and_tail , pick = <NUM_LIT:1> ) , lambda x , y : rules . And ( * flatten ( x , y ) ) ) , <EOL> ( seq ( maybe ( ws ) , or_tail , pick = <NUM_LIT:1> ) , lambda x , y : rules . Or ( * flatten ( x , y ) ) ) , <EOL> step_default ( ) <EOL> ) , <EOL> step ( <EOL> seq ( ws , union ( no_parser , basic ) , pick = <NUM_LIT:1> ) , <EOL> ( seq ( ws , result , pick = <NUM_LIT:1> ) , lambda x , y : ( x , y ) ) , <EOL> ( seq ( ws , and_tail , pick = <NUM_LIT:1> ) , lambda x , y : rules . And ( * flatten ( x , y ) ) ) , <EOL> ( seq ( ws , or_tail , pick = <NUM_LIT:1> ) , lambda x , y : rules . Or ( * flatten ( x , y ) ) ) , <EOL> step_default ( ) <EOL> ) <EOL> ) , <EOL> pick = <NUM_LIT:1> <EOL> ) <EOL> ) <EOL> return result <EOL> and_tail . set ( binary_rule_tail ( "<STR_LIT>" ) ) <EOL> or_tail . set ( binary_rule_tail ( "<STR_LIT>" ) ) <EOL> expr . set ( <EOL> seq ( <EOL> maybe ( ws ) , <EOL> union ( <EOL> step ( <EOL> parens_expr , <EOL> ( seq ( maybe ( ws ) , and_tail , pick = <NUM_LIT:1> ) , lambda x , y : rules . And ( * flatten ( x , y ) ) ) , <EOL> ( seq ( maybe ( ws ) , or_tail , pick = <NUM_LIT:1> ) , lambda x , y : rules . Or ( * flatten ( x , y ) ) ) , <EOL> step_default ( ) <EOL> ) , <EOL> step ( <EOL> union ( no_parser , basic ) , <EOL> ( seq ( ws , and_tail , pick = <NUM_LIT:1> ) , lambda x , y : rules . And ( * flatten ( x , y ) ) ) , <EOL> ( seq ( ws , or_tail , pick = <NUM_LIT:1> ) , lambda x , y : rules . Or ( * flatten ( x , y ) ) ) , <EOL> step_default ( ) <EOL> ) <EOL> ) , <EOL> maybe ( ws ) , <EOL> pick = <NUM_LIT:1> <EOL> ) <EOL> ) <EOL> return expr <EOL> expr = _create_parser ( ) <EOL> def parse ( string ) : <EOL> match = expr . parse ( string ) <EOL> if not match or match [ <NUM_LIT:1> ] != "<STR_LIT>" : <EOL> raise ValueError ( "<STR_LIT>" + repr ( string ) ) <EOL> return match [ <NUM_LIT:0> ] <EOL> def rule ( obj ) : <EOL> if isinstance ( obj , basestring ) : <EOL> return parse ( obj ) <EOL> return obj <EOL> def format ( rule ) : <EOL> return formatter . format ( rule ) </s>
