<s> """<STR_LIT>""" <EOL> from jinja2 import nodes <EOL> from jinja2 . exceptions import TemplateSyntaxError , TemplateAssertionError <EOL> from jinja2 . utils import next <EOL> from jinja2 . lexer import describe_token , describe_token_expr <EOL> _statement_keywords = frozenset ( [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' ] ) <EOL> _compare_operators = frozenset ( [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> class Parser ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , environment , source , name = None , filename = None , <EOL> state = None ) : <EOL> self . environment = environment <EOL> self . stream = environment . _tokenize ( source , name , filename , state ) <EOL> self . name = name <EOL> self . filename = filename <EOL> self . closed = False <EOL> self . extensions = { } <EOL> for extension in environment . iter_extensions ( ) : <EOL> for tag in extension . tags : <EOL> self . extensions [ tag ] = extension . parse <EOL> self . _last_identifier = <NUM_LIT:0> <EOL> self . _tag_stack = [ ] <EOL> self . _end_token_stack = [ ] <EOL> def fail ( self , msg , lineno = None , exc = TemplateSyntaxError ) : <EOL> """<STR_LIT>""" <EOL> if lineno is None : <EOL> lineno = self . stream . current . lineno <EOL> raise exc ( msg , lineno , self . name , self . filename ) <EOL> def _fail_ut_eof ( self , name , end_token_stack , lineno ) : <EOL> expected = [ ] <EOL> for exprs in end_token_stack : <EOL> expected . extend ( map ( describe_token_expr , exprs ) ) <EOL> if end_token_stack : <EOL> currently_looking = '<STR_LIT>' . join ( <EOL> "<STR_LIT>" % describe_token_expr ( expr ) <EOL> for expr in end_token_stack [ - <NUM_LIT:1> ] ) <EOL> else : <EOL> currently_looking = None <EOL> if name is None : <EOL> message = [ '<STR_LIT>' ] <EOL> else : <EOL> message = [ '<STR_LIT>' % name ] <EOL> if currently_looking : <EOL> if name is not None and name in expected : <EOL> message . append ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' % currently_looking ) <EOL> else : <EOL> message . append ( '<STR_LIT>' <EOL> '<STR_LIT>' % currently_looking ) <EOL> if self . _tag_stack : <EOL> message . append ( '<STR_LIT>' <EOL> '<STR_LIT>' % self . _tag_stack [ - <NUM_LIT:1> ] ) <EOL> self . fail ( '<STR_LIT:U+0020>' . join ( message ) , lineno ) <EOL> def fail_unknown_tag ( self , name , lineno = None ) : <EOL> """<STR_LIT>""" <EOL> return self . _fail_ut_eof ( name , self . _end_token_stack , lineno ) <EOL> def fail_eof ( self , end_tokens = None , lineno = None ) : <EOL> """<STR_LIT>""" <EOL> stack = list ( self . _end_token_stack ) <EOL> if end_tokens is not None : <EOL> stack . append ( end_tokens ) <EOL> return self . _fail_ut_eof ( None , stack , lineno ) <EOL> def is_tuple_end ( self , extra_end_rules = None ) : <EOL> """<STR_LIT>""" <EOL> if self . stream . current . type in ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) : <EOL> return True <EOL> elif extra_end_rules is not None : <EOL> return self . stream . current . test_any ( extra_end_rules ) <EOL> return False <EOL> def free_identifier ( self , lineno = None ) : <EOL> """<STR_LIT>""" <EOL> self . _last_identifier += <NUM_LIT:1> <EOL> rv = object . __new__ ( nodes . InternalName ) <EOL> nodes . Node . __init__ ( rv , '<STR_LIT>' % self . _last_identifier , lineno = lineno ) <EOL> return rv <EOL> def parse_statement ( self ) : <EOL> """<STR_LIT>""" <EOL> token = self . stream . current <EOL> if token . type != '<STR_LIT:name>' : <EOL> self . fail ( '<STR_LIT>' , token . lineno ) <EOL> self . _tag_stack . append ( token . value ) <EOL> pop_tag = True <EOL> try : <EOL> if token . value in _statement_keywords : <EOL> return getattr ( self , '<STR_LIT>' + self . stream . current . value ) ( ) <EOL> if token . value == '<STR_LIT>' : <EOL> return self . parse_call_block ( ) <EOL> if token . value == '<STR_LIT>' : <EOL> return self . parse_filter_block ( ) <EOL> ext = self . extensions . get ( token . value ) <EOL> if ext is not None : <EOL> return ext ( self ) <EOL> self . _tag_stack . pop ( ) <EOL> pop_tag = False <EOL> self . fail_unknown_tag ( token . value , token . lineno ) <EOL> finally : <EOL> if pop_tag : <EOL> self . _tag_stack . pop ( ) <EOL> def parse_statements ( self , end_tokens , drop_needle = False ) : <EOL> """<STR_LIT>""" <EOL> self . stream . skip_if ( '<STR_LIT>' ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> result = self . subparse ( end_tokens ) <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> self . fail_eof ( end_tokens ) <EOL> if drop_needle : <EOL> next ( self . stream ) <EOL> return result <EOL> def parse_set ( self ) : <EOL> """<STR_LIT>""" <EOL> lineno = next ( self . stream ) . lineno <EOL> target = self . parse_assign_target ( ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> expr = self . parse_tuple ( ) <EOL> return nodes . Assign ( target , expr , lineno = lineno ) <EOL> def parse_for ( self ) : <EOL> """<STR_LIT>""" <EOL> lineno = self . stream . expect ( '<STR_LIT>' ) . lineno <EOL> target = self . parse_assign_target ( extra_end_rules = ( '<STR_LIT>' , ) ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> iter = self . parse_tuple ( with_condexpr = False , <EOL> extra_end_rules = ( '<STR_LIT>' , ) ) <EOL> test = None <EOL> if self . stream . skip_if ( '<STR_LIT>' ) : <EOL> test = self . parse_expression ( ) <EOL> recursive = self . stream . skip_if ( '<STR_LIT>' ) <EOL> body = self . parse_statements ( ( '<STR_LIT>' , '<STR_LIT>' ) ) <EOL> if next ( self . stream ) . value == '<STR_LIT>' : <EOL> else_ = [ ] <EOL> else : <EOL> else_ = self . parse_statements ( ( '<STR_LIT>' , ) , drop_needle = True ) <EOL> return nodes . For ( target , iter , body , else_ , test , <EOL> recursive , lineno = lineno ) <EOL> def parse_if ( self ) : <EOL> """<STR_LIT>""" <EOL> node = result = nodes . If ( lineno = self . stream . expect ( '<STR_LIT>' ) . lineno ) <EOL> while <NUM_LIT:1> : <EOL> node . test = self . parse_tuple ( with_condexpr = False ) <EOL> node . body = self . parse_statements ( ( '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' ) ) <EOL> token = next ( self . stream ) <EOL> if token . test ( '<STR_LIT>' ) : <EOL> new_node = nodes . If ( lineno = self . stream . current . lineno ) <EOL> node . else_ = [ new_node ] <EOL> node = new_node <EOL> continue <EOL> elif token . test ( '<STR_LIT>' ) : <EOL> node . else_ = self . parse_statements ( ( '<STR_LIT>' , ) , <EOL> drop_needle = True ) <EOL> else : <EOL> node . else_ = [ ] <EOL> break <EOL> return result <EOL> def parse_block ( self ) : <EOL> node = nodes . Block ( lineno = next ( self . stream ) . lineno ) <EOL> node . name = self . stream . expect ( '<STR_LIT:name>' ) . value <EOL> node . scoped = self . stream . skip_if ( '<STR_LIT>' ) <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> self . fail ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> node . body = self . parse_statements ( ( '<STR_LIT>' , ) , drop_needle = True ) <EOL> self . stream . skip_if ( '<STR_LIT>' + node . name ) <EOL> return node <EOL> def parse_extends ( self ) : <EOL> node = nodes . Extends ( lineno = next ( self . stream ) . lineno ) <EOL> node . template = self . parse_expression ( ) <EOL> return node <EOL> def parse_import_context ( self , node , default ) : <EOL> if self . stream . current . test_any ( '<STR_LIT>' , '<STR_LIT>' ) and self . stream . look ( ) . test ( '<STR_LIT>' ) : <EOL> node . with_context = next ( self . stream ) . value == '<STR_LIT>' <EOL> self . stream . skip ( ) <EOL> else : <EOL> node . with_context = default <EOL> return node <EOL> def parse_include ( self ) : <EOL> node = nodes . Include ( lineno = next ( self . stream ) . lineno ) <EOL> node . template = self . parse_expression ( ) <EOL> if self . stream . current . test ( '<STR_LIT>' ) and self . stream . look ( ) . test ( '<STR_LIT>' ) : <EOL> node . ignore_missing = True <EOL> self . stream . skip ( <NUM_LIT:2> ) <EOL> else : <EOL> node . ignore_missing = False <EOL> return self . parse_import_context ( node , True ) <EOL> def parse_import ( self ) : <EOL> node = nodes . Import ( lineno = next ( self . stream ) . lineno ) <EOL> node . template = self . parse_expression ( ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> node . target = self . parse_assign_target ( name_only = True ) . name <EOL> return self . parse_import_context ( node , False ) <EOL> def parse_from ( self ) : <EOL> node = nodes . FromImport ( lineno = next ( self . stream ) . lineno ) <EOL> node . template = self . parse_expression ( ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> node . names = [ ] <EOL> def parse_context ( ) : <EOL> if self . stream . current . value in ( '<STR_LIT>' , '<STR_LIT>' ) and self . stream . look ( ) . test ( '<STR_LIT>' ) : <EOL> node . with_context = next ( self . stream ) . value == '<STR_LIT>' <EOL> self . stream . skip ( ) <EOL> return True <EOL> return False <EOL> while <NUM_LIT:1> : <EOL> if node . names : <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> if self . stream . current . type == '<STR_LIT:name>' : <EOL> if parse_context ( ) : <EOL> break <EOL> target = self . parse_assign_target ( name_only = True ) <EOL> if target . name . startswith ( '<STR_LIT:_>' ) : <EOL> self . fail ( '<STR_LIT>' <EOL> '<STR_LIT>' , target . lineno , <EOL> exc = TemplateAssertionError ) <EOL> if self . stream . skip_if ( '<STR_LIT>' ) : <EOL> alias = self . parse_assign_target ( name_only = True ) <EOL> node . names . append ( ( target . name , alias . name ) ) <EOL> else : <EOL> node . names . append ( target . name ) <EOL> if parse_context ( ) or self . stream . current . type != '<STR_LIT>' : <EOL> break <EOL> else : <EOL> break <EOL> if not hasattr ( node , '<STR_LIT>' ) : <EOL> node . with_context = False <EOL> self . stream . skip_if ( '<STR_LIT>' ) <EOL> return node <EOL> def parse_signature ( self , node ) : <EOL> node . args = args = [ ] <EOL> node . defaults = defaults = [ ] <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> while self . stream . current . type != '<STR_LIT>' : <EOL> if args : <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> arg = self . parse_assign_target ( name_only = True ) <EOL> arg . set_ctx ( '<STR_LIT>' ) <EOL> if self . stream . skip_if ( '<STR_LIT>' ) : <EOL> defaults . append ( self . parse_expression ( ) ) <EOL> args . append ( arg ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> def parse_call_block ( self ) : <EOL> node = nodes . CallBlock ( lineno = next ( self . stream ) . lineno ) <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> self . parse_signature ( node ) <EOL> else : <EOL> node . args = [ ] <EOL> node . defaults = [ ] <EOL> node . call = self . parse_expression ( ) <EOL> if not isinstance ( node . call , nodes . Call ) : <EOL> self . fail ( '<STR_LIT>' , node . lineno ) <EOL> node . body = self . parse_statements ( ( '<STR_LIT>' , ) , drop_needle = True ) <EOL> return node <EOL> def parse_filter_block ( self ) : <EOL> node = nodes . FilterBlock ( lineno = next ( self . stream ) . lineno ) <EOL> node . filter = self . parse_filter ( None , start_inline = True ) <EOL> node . body = self . parse_statements ( ( '<STR_LIT>' , ) , <EOL> drop_needle = True ) <EOL> return node <EOL> def parse_macro ( self ) : <EOL> node = nodes . Macro ( lineno = next ( self . stream ) . lineno ) <EOL> node . name = self . parse_assign_target ( name_only = True ) . name <EOL> self . parse_signature ( node ) <EOL> node . body = self . parse_statements ( ( '<STR_LIT>' , ) , <EOL> drop_needle = True ) <EOL> return node <EOL> def parse_print ( self ) : <EOL> node = nodes . Output ( lineno = next ( self . stream ) . lineno ) <EOL> node . nodes = [ ] <EOL> while self . stream . current . type != '<STR_LIT>' : <EOL> if node . nodes : <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> node . nodes . append ( self . parse_expression ( ) ) <EOL> return node <EOL> def parse_assign_target ( self , with_tuple = True , name_only = False , <EOL> extra_end_rules = None ) : <EOL> """<STR_LIT>""" <EOL> if name_only : <EOL> token = self . stream . expect ( '<STR_LIT:name>' ) <EOL> target = nodes . Name ( token . value , '<STR_LIT:store>' , lineno = token . lineno ) <EOL> else : <EOL> if with_tuple : <EOL> target = self . parse_tuple ( simplified = True , <EOL> extra_end_rules = extra_end_rules ) <EOL> else : <EOL> target = self . parse_primary ( ) <EOL> target . set_ctx ( '<STR_LIT:store>' ) <EOL> if not target . can_assign ( ) : <EOL> self . fail ( '<STR_LIT>' % target . __class__ . <EOL> __name__ . lower ( ) , target . lineno ) <EOL> return target <EOL> def parse_expression ( self , with_condexpr = True ) : <EOL> """<STR_LIT>""" <EOL> if with_condexpr : <EOL> return self . parse_condexpr ( ) <EOL> return self . parse_or ( ) <EOL> def parse_condexpr ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> expr1 = self . parse_or ( ) <EOL> while self . stream . skip_if ( '<STR_LIT>' ) : <EOL> expr2 = self . parse_or ( ) <EOL> if self . stream . skip_if ( '<STR_LIT>' ) : <EOL> expr3 = self . parse_condexpr ( ) <EOL> else : <EOL> expr3 = None <EOL> expr1 = nodes . CondExpr ( expr2 , expr1 , expr3 , lineno = lineno ) <EOL> lineno = self . stream . current . lineno <EOL> return expr1 <EOL> def parse_or ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> left = self . parse_and ( ) <EOL> while self . stream . skip_if ( '<STR_LIT>' ) : <EOL> right = self . parse_and ( ) <EOL> left = nodes . Or ( left , right , lineno = lineno ) <EOL> lineno = self . stream . current . lineno <EOL> return left <EOL> def parse_and ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> left = self . parse_not ( ) <EOL> while self . stream . skip_if ( '<STR_LIT>' ) : <EOL> right = self . parse_not ( ) <EOL> left = nodes . And ( left , right , lineno = lineno ) <EOL> lineno = self . stream . current . lineno <EOL> return left <EOL> def parse_not ( self ) : <EOL> if self . stream . current . test ( '<STR_LIT>' ) : <EOL> lineno = next ( self . stream ) . lineno <EOL> return nodes . Not ( self . parse_not ( ) , lineno = lineno ) <EOL> return self . parse_compare ( ) <EOL> def parse_compare ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> expr = self . parse_add ( ) <EOL> ops = [ ] <EOL> while <NUM_LIT:1> : <EOL> token_type = self . stream . current . type <EOL> if token_type in _compare_operators : <EOL> next ( self . stream ) <EOL> ops . append ( nodes . Operand ( token_type , self . parse_add ( ) ) ) <EOL> elif self . stream . skip_if ( '<STR_LIT>' ) : <EOL> ops . append ( nodes . Operand ( '<STR_LIT>' , self . parse_add ( ) ) ) <EOL> elif self . stream . current . test ( '<STR_LIT>' ) and self . stream . look ( ) . test ( '<STR_LIT>' ) : <EOL> self . stream . skip ( <NUM_LIT:2> ) <EOL> ops . append ( nodes . Operand ( '<STR_LIT>' , self . parse_add ( ) ) ) <EOL> else : <EOL> break <EOL> lineno = self . stream . current . lineno <EOL> if not ops : <EOL> return expr <EOL> return nodes . Compare ( expr , ops , lineno = lineno ) <EOL> def parse_add ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> left = self . parse_sub ( ) <EOL> while self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> right = self . parse_sub ( ) <EOL> left = nodes . Add ( left , right , lineno = lineno ) <EOL> lineno = self . stream . current . lineno <EOL> return left <EOL> def parse_sub ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> left = self . parse_concat ( ) <EOL> while self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> right = self . parse_concat ( ) <EOL> left = nodes . Sub ( left , right , lineno = lineno ) <EOL> lineno = self . stream . current . lineno <EOL> return left <EOL> def parse_concat ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> args = [ self . parse_mul ( ) ] <EOL> while self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> args . append ( self . parse_mul ( ) ) <EOL> if len ( args ) == <NUM_LIT:1> : <EOL> return args [ <NUM_LIT:0> ] <EOL> return nodes . Concat ( args , lineno = lineno ) <EOL> def parse_mul ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> left = self . parse_div ( ) <EOL> while self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> right = self . parse_div ( ) <EOL> left = nodes . Mul ( left , right , lineno = lineno ) <EOL> lineno = self . stream . current . lineno <EOL> return left <EOL> def parse_div ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> left = self . parse_floordiv ( ) <EOL> while self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> right = self . parse_floordiv ( ) <EOL> left = nodes . Div ( left , right , lineno = lineno ) <EOL> lineno = self . stream . current . lineno <EOL> return left <EOL> def parse_floordiv ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> left = self . parse_mod ( ) <EOL> while self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> right = self . parse_mod ( ) <EOL> left = nodes . FloorDiv ( left , right , lineno = lineno ) <EOL> lineno = self . stream . current . lineno <EOL> return left <EOL> def parse_mod ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> left = self . parse_pow ( ) <EOL> while self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> right = self . parse_pow ( ) <EOL> left = nodes . Mod ( left , right , lineno = lineno ) <EOL> lineno = self . stream . current . lineno <EOL> return left <EOL> def parse_pow ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> left = self . parse_unary ( ) <EOL> while self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> right = self . parse_unary ( ) <EOL> left = nodes . Pow ( left , right , lineno = lineno ) <EOL> lineno = self . stream . current . lineno <EOL> return left <EOL> def parse_unary ( self , with_filter = True ) : <EOL> token_type = self . stream . current . type <EOL> lineno = self . stream . current . lineno <EOL> if token_type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> node = nodes . Neg ( self . parse_unary ( False ) , lineno = lineno ) <EOL> elif token_type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> node = nodes . Pos ( self . parse_unary ( False ) , lineno = lineno ) <EOL> else : <EOL> node = self . parse_primary ( ) <EOL> node = self . parse_postfix ( node ) <EOL> if with_filter : <EOL> node = self . parse_filter_expr ( node ) <EOL> return node <EOL> def parse_primary ( self ) : <EOL> token = self . stream . current <EOL> if token . type == '<STR_LIT:name>' : <EOL> if token . value in ( '<STR_LIT:true>' , '<STR_LIT:false>' , '<STR_LIT:True>' , '<STR_LIT:False>' ) : <EOL> node = nodes . Const ( token . value in ( '<STR_LIT:true>' , '<STR_LIT:True>' ) , <EOL> lineno = token . lineno ) <EOL> elif token . value in ( '<STR_LIT:none>' , '<STR_LIT:None>' ) : <EOL> node = nodes . Const ( None , lineno = token . lineno ) <EOL> else : <EOL> node = nodes . Name ( token . value , '<STR_LIT>' , lineno = token . lineno ) <EOL> next ( self . stream ) <EOL> elif token . type == '<STR_LIT:string>' : <EOL> next ( self . stream ) <EOL> buf = [ token . value ] <EOL> lineno = token . lineno <EOL> while self . stream . current . type == '<STR_LIT:string>' : <EOL> buf . append ( self . stream . current . value ) <EOL> next ( self . stream ) <EOL> node = nodes . Const ( '<STR_LIT>' . join ( buf ) , lineno = lineno ) <EOL> elif token . type in ( '<STR_LIT>' , '<STR_LIT:float>' ) : <EOL> next ( self . stream ) <EOL> node = nodes . Const ( token . value , lineno = token . lineno ) <EOL> elif token . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> node = self . parse_tuple ( explicit_parentheses = True ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> elif token . type == '<STR_LIT>' : <EOL> node = self . parse_list ( ) <EOL> elif token . type == '<STR_LIT>' : <EOL> node = self . parse_dict ( ) <EOL> else : <EOL> self . fail ( "<STR_LIT>" % describe_token ( token ) , token . lineno ) <EOL> return node <EOL> def parse_tuple ( self , simplified = False , with_condexpr = True , <EOL> extra_end_rules = None , explicit_parentheses = False ) : <EOL> """<STR_LIT>""" <EOL> lineno = self . stream . current . lineno <EOL> if simplified : <EOL> parse = self . parse_primary <EOL> elif with_condexpr : <EOL> parse = self . parse_expression <EOL> else : <EOL> parse = lambda : self . parse_expression ( with_condexpr = False ) <EOL> args = [ ] <EOL> is_tuple = False <EOL> while <NUM_LIT:1> : <EOL> if args : <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> if self . is_tuple_end ( extra_end_rules ) : <EOL> break <EOL> args . append ( parse ( ) ) <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> is_tuple = True <EOL> else : <EOL> break <EOL> lineno = self . stream . current . lineno <EOL> if not is_tuple : <EOL> if args : <EOL> return args [ <NUM_LIT:0> ] <EOL> if not explicit_parentheses : <EOL> self . fail ( '<STR_LIT>' % <EOL> describe_token ( self . stream . current ) ) <EOL> return nodes . Tuple ( args , '<STR_LIT>' , lineno = lineno ) <EOL> def parse_list ( self ) : <EOL> token = self . stream . expect ( '<STR_LIT>' ) <EOL> items = [ ] <EOL> while self . stream . current . type != '<STR_LIT>' : <EOL> if items : <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> break <EOL> items . append ( self . parse_expression ( ) ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> return nodes . List ( items , lineno = token . lineno ) <EOL> def parse_dict ( self ) : <EOL> token = self . stream . expect ( '<STR_LIT>' ) <EOL> items = [ ] <EOL> while self . stream . current . type != '<STR_LIT>' : <EOL> if items : <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> break <EOL> key = self . parse_expression ( ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> value = self . parse_expression ( ) <EOL> items . append ( nodes . Pair ( key , value , lineno = key . lineno ) ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> return nodes . Dict ( items , lineno = token . lineno ) <EOL> def parse_postfix ( self , node ) : <EOL> while <NUM_LIT:1> : <EOL> token_type = self . stream . current . type <EOL> if token_type == '<STR_LIT>' or token_type == '<STR_LIT>' : <EOL> node = self . parse_subscript ( node ) <EOL> elif token_type == '<STR_LIT>' : <EOL> node = self . parse_call ( node ) <EOL> else : <EOL> break <EOL> return node <EOL> def parse_filter_expr ( self , node ) : <EOL> while <NUM_LIT:1> : <EOL> token_type = self . stream . current . type <EOL> if token_type == '<STR_LIT>' : <EOL> node = self . parse_filter ( node ) <EOL> elif token_type == '<STR_LIT:name>' and self . stream . current . value == '<STR_LIT>' : <EOL> node = self . parse_test ( node ) <EOL> elif token_type == '<STR_LIT>' : <EOL> node = self . parse_call ( node ) <EOL> else : <EOL> break <EOL> return node <EOL> def parse_subscript ( self , node ) : <EOL> token = next ( self . stream ) <EOL> if token . type == '<STR_LIT>' : <EOL> attr_token = self . stream . current <EOL> next ( self . stream ) <EOL> if attr_token . type == '<STR_LIT:name>' : <EOL> return nodes . Getattr ( node , attr_token . value , '<STR_LIT>' , <EOL> lineno = token . lineno ) <EOL> elif attr_token . type != '<STR_LIT>' : <EOL> self . fail ( '<STR_LIT>' , attr_token . lineno ) <EOL> arg = nodes . Const ( attr_token . value , lineno = attr_token . lineno ) <EOL> return nodes . Getitem ( node , arg , '<STR_LIT>' , lineno = token . lineno ) <EOL> if token . type == '<STR_LIT>' : <EOL> priority_on_attribute = False <EOL> args = [ ] <EOL> while self . stream . current . type != '<STR_LIT>' : <EOL> if args : <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> args . append ( self . parse_subscribed ( ) ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> if len ( args ) == <NUM_LIT:1> : <EOL> arg = args [ <NUM_LIT:0> ] <EOL> else : <EOL> arg = nodes . Tuple ( args , '<STR_LIT>' , lineno = token . lineno ) <EOL> return nodes . Getitem ( node , arg , '<STR_LIT>' , lineno = token . lineno ) <EOL> self . fail ( '<STR_LIT>' , self . lineno ) <EOL> def parse_subscribed ( self ) : <EOL> lineno = self . stream . current . lineno <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> args = [ None ] <EOL> else : <EOL> node = self . parse_expression ( ) <EOL> if self . stream . current . type != '<STR_LIT>' : <EOL> return node <EOL> next ( self . stream ) <EOL> args = [ node ] <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> args . append ( None ) <EOL> elif self . stream . current . type not in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> args . append ( self . parse_expression ( ) ) <EOL> else : <EOL> args . append ( None ) <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> if self . stream . current . type not in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> args . append ( self . parse_expression ( ) ) <EOL> else : <EOL> args . append ( None ) <EOL> else : <EOL> args . append ( None ) <EOL> return nodes . Slice ( lineno = lineno , * args ) <EOL> def parse_call ( self , node ) : <EOL> token = self . stream . expect ( '<STR_LIT>' ) <EOL> args = [ ] <EOL> kwargs = [ ] <EOL> dyn_args = dyn_kwargs = None <EOL> require_comma = False <EOL> def ensure ( expr ) : <EOL> if not expr : <EOL> self . fail ( '<STR_LIT>' , <EOL> token . lineno ) <EOL> while self . stream . current . type != '<STR_LIT>' : <EOL> if require_comma : <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> break <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> ensure ( dyn_args is None and dyn_kwargs is None ) <EOL> next ( self . stream ) <EOL> dyn_args = self . parse_expression ( ) <EOL> elif self . stream . current . type == '<STR_LIT>' : <EOL> ensure ( dyn_kwargs is None ) <EOL> next ( self . stream ) <EOL> dyn_kwargs = self . parse_expression ( ) <EOL> else : <EOL> ensure ( dyn_args is None and dyn_kwargs is None ) <EOL> if self . stream . current . type == '<STR_LIT:name>' and self . stream . look ( ) . type == '<STR_LIT>' : <EOL> key = self . stream . current . value <EOL> self . stream . skip ( <NUM_LIT:2> ) <EOL> value = self . parse_expression ( ) <EOL> kwargs . append ( nodes . Keyword ( key , value , <EOL> lineno = value . lineno ) ) <EOL> else : <EOL> ensure ( not kwargs ) <EOL> args . append ( self . parse_expression ( ) ) <EOL> require_comma = True <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> if node is None : <EOL> return args , kwargs , dyn_args , dyn_kwargs <EOL> return nodes . Call ( node , args , kwargs , dyn_args , dyn_kwargs , <EOL> lineno = token . lineno ) <EOL> def parse_filter ( self , node , start_inline = False ) : <EOL> while self . stream . current . type == '<STR_LIT>' or start_inline : <EOL> if not start_inline : <EOL> next ( self . stream ) <EOL> token = self . stream . expect ( '<STR_LIT:name>' ) <EOL> name = token . value <EOL> while self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> name += '<STR_LIT:.>' + self . stream . expect ( '<STR_LIT:name>' ) . value <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> args , kwargs , dyn_args , dyn_kwargs = self . parse_call ( None ) <EOL> else : <EOL> args = [ ] <EOL> kwargs = [ ] <EOL> dyn_args = dyn_kwargs = None <EOL> node = nodes . Filter ( node , name , args , kwargs , dyn_args , <EOL> dyn_kwargs , lineno = token . lineno ) <EOL> start_inline = False <EOL> return node <EOL> def parse_test ( self , node ) : <EOL> token = next ( self . stream ) <EOL> if self . stream . current . test ( '<STR_LIT>' ) : <EOL> next ( self . stream ) <EOL> negated = True <EOL> else : <EOL> negated = False <EOL> name = self . stream . expect ( '<STR_LIT:name>' ) . value <EOL> while self . stream . current . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> name += '<STR_LIT:.>' + self . stream . expect ( '<STR_LIT:name>' ) . value <EOL> dyn_args = dyn_kwargs = None <EOL> kwargs = [ ] <EOL> if self . stream . current . type == '<STR_LIT>' : <EOL> args , kwargs , dyn_args , dyn_kwargs = self . parse_call ( None ) <EOL> elif self . stream . current . type in ( '<STR_LIT:name>' , '<STR_LIT:string>' , '<STR_LIT>' , <EOL> '<STR_LIT:float>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' ) and not self . stream . current . test_any ( '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' ) : <EOL> if self . stream . current . test ( '<STR_LIT>' ) : <EOL> self . fail ( '<STR_LIT>' ) <EOL> args = [ self . parse_expression ( ) ] <EOL> else : <EOL> args = [ ] <EOL> node = nodes . Test ( node , name , args , kwargs , dyn_args , <EOL> dyn_kwargs , lineno = token . lineno ) <EOL> if negated : <EOL> node = nodes . Not ( node , lineno = token . lineno ) <EOL> return node <EOL> def subparse ( self , end_tokens = None ) : <EOL> body = [ ] <EOL> data_buffer = [ ] <EOL> add_data = data_buffer . append <EOL> if end_tokens is not None : <EOL> self . _end_token_stack . append ( end_tokens ) <EOL> def flush_data ( ) : <EOL> if data_buffer : <EOL> lineno = data_buffer [ <NUM_LIT:0> ] . lineno <EOL> body . append ( nodes . Output ( data_buffer [ : ] , lineno = lineno ) ) <EOL> del data_buffer [ : ] <EOL> try : <EOL> while self . stream : <EOL> token = self . stream . current <EOL> if token . type == '<STR_LIT:data>' : <EOL> if token . value : <EOL> add_data ( nodes . TemplateData ( token . value , <EOL> lineno = token . lineno ) ) <EOL> next ( self . stream ) <EOL> elif token . type == '<STR_LIT>' : <EOL> next ( self . stream ) <EOL> add_data ( self . parse_tuple ( with_condexpr = True ) ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> elif token . type == '<STR_LIT>' : <EOL> flush_data ( ) <EOL> next ( self . stream ) <EOL> if end_tokens is not None and self . stream . current . test_any ( * end_tokens ) : <EOL> return body <EOL> rv = self . parse_statement ( ) <EOL> if isinstance ( rv , list ) : <EOL> body . extend ( rv ) <EOL> else : <EOL> body . append ( rv ) <EOL> self . stream . expect ( '<STR_LIT>' ) <EOL> else : <EOL> raise AssertionError ( '<STR_LIT>' ) <EOL> flush_data ( ) <EOL> finally : <EOL> if end_tokens is not None : <EOL> self . _end_token_stack . pop ( ) <EOL> return body <EOL> def parse ( self ) : <EOL> """<STR_LIT>""" <EOL> result = nodes . Template ( self . subparse ( ) , lineno = <NUM_LIT:1> ) <EOL> result . set_environment ( self . environment ) <EOL> return result </s>
