1b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# -*- coding: utf-8 -*- 2b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)""" 3b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) jinja2.parser 4b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ~~~~~~~~~~~~~ 5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 6b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Implements the template parser. 7b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) :copyright: (c) 2010 by the Jinja Team. 9b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) :license: BSD, see LICENSE for more details. 10b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)""" 11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from jinja2 import nodes 12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError 13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from jinja2.utils import next 14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from jinja2.lexer import describe_token, describe_token_expr 15b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#: statements that callinto 18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)_statement_keywords = frozenset(['for', 'if', 'block', 'extends', 'print', 19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'macro', 'include', 'from', 'import', 20b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'set']) 21b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)_compare_operators = frozenset(['eq', 'ne', 'lt', 'lteq', 'gt', 'gteq']) 22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class Parser(object): 25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """This is the central parsing class Jinja2 uses. It's passed to 26b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) extensions and can be used to parse expressions or statements. 27b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """ 28b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def __init__(self, environment, source, name=None, filename=None, 30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) state=None): 31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.environment = environment 32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream = environment._tokenize(source, name, filename, state) 33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.name = name 34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.filename = filename 35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.closed = False 36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.extensions = {} 37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for extension in environment.iter_extensions(): 38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for tag in extension.tags: 39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.extensions[tag] = extension.parse 40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._last_identifier = 0 41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._tag_stack = [] 42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._end_token_stack = [] 43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def fail(self, msg, lineno=None, exc=TemplateSyntaxError): 45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Convenience method that raises `exc` with the message, passed 46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) line number or last line number as well as the current name and 47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) filename. 48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """ 49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if lineno is None: 50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) raise exc(msg, lineno, self.name, self.filename) 52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def _fail_ut_eof(self, name, end_token_stack, lineno): 54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) expected = [] 55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for exprs in end_token_stack: 56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) expected.extend(map(describe_token_expr, exprs)) 57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if end_token_stack: 58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) currently_looking = ' or '.join( 59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) "'%s'" % describe_token_expr(expr) 60b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for expr in end_token_stack[-1]) 61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 62b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) currently_looking = None 63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if name is None: 65b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) message = ['Unexpected end of template.'] 66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) message = ['Encountered unknown tag \'%s\'.' % name] 68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 69b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if currently_looking: 70b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if name is not None and name in expected: 71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) message.append('You probably made a nesting mistake. Jinja ' 72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'is expecting this tag, but currently looking ' 73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'for %s.' % currently_looking) 74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 75b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) message.append('Jinja was looking for the following tags: ' 76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) '%s.' % currently_looking) 77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self._tag_stack: 79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) message.append('The innermost block that needs to be ' 80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'closed is \'%s\'.' % self._tag_stack[-1]) 81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail(' '.join(message), lineno) 83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 84b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def fail_unknown_tag(self, name, lineno=None): 85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Called if the parser encounters an unknown tag. Tries to fail 86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) with a human readable error message that could help to identify 87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) the problem. 88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """ 89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self._fail_ut_eof(name, self._end_token_stack, lineno) 90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def fail_eof(self, end_tokens=None, lineno=None): 92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Like fail_unknown_tag but for end of template situations.""" 93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stack = list(self._end_token_stack) 94b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if end_tokens is not None: 95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stack.append(end_tokens) 96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self._fail_ut_eof(None, stack, lineno) 97b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def is_tuple_end(self, extra_end_rules=None): 99b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Are we at the end of a tuple?""" 100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type in ('variable_end', 'block_end', 'rparen'): 101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return True 102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif extra_end_rules is not None: 103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self.stream.current.test_any(extra_end_rules) 104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return False 105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def free_identifier(self, lineno=None): 107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Return a new free identifier as :class:`~jinja2.nodes.InternalName`.""" 108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._last_identifier += 1 109b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) rv = object.__new__(nodes.InternalName) 110b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) nodes.Node.__init__(rv, 'fi%d' % self._last_identifier, lineno=lineno) 111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return rv 112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 113b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_statement(self): 114b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Parse a single statement.""" 115b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token = self.stream.current 116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token.type != 'name': 117b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail('tag name expected', token.lineno) 118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._tag_stack.append(token.value) 119b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) pop_tag = True 120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) try: 121b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token.value in _statement_keywords: 122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return getattr(self, 'parse_' + self.stream.current.value)() 123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token.value == 'call': 124b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self.parse_call_block() 125b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token.value == 'filter': 126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self.parse_filter_block() 127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ext = self.extensions.get(token.value) 128b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if ext is not None: 129b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return ext(self) 130b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # did not work out, remove the token we pushed by accident 132b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # from the stack so that the unknown tag fail function can 133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # produce a proper error message. 134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._tag_stack.pop() 135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) pop_tag = False 136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail_unknown_tag(token.value, token.lineno) 137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) finally: 138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if pop_tag: 139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._tag_stack.pop() 140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_statements(self, end_tokens, drop_needle=False): 142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Parse multiple statements into a list until one of the end tokens 143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) is reached. This is used to parse the body of statements as it also 144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) parses template data if appropriate. The parser checks first if the 145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) current token is a colon and skips it if there is one. Then it checks 146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for the block end and parses until if one of the `end_tokens` is 147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) reached. Per default the active token in the stream at the end of 148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) the call is the matched end token. If this is not wanted `drop_needle` 149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) can be set to `True` and the end token is removed. 150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """ 151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # the first token may be a colon for python compatibility 152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.skip_if('colon') 153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # in the future it would be possible to add whole code sections 155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # by adding some sort of end of statement token and parsing those here. 156b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('block_end') 157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) result = self.subparse(end_tokens) 158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 159b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # we reached the end of the template too early, the subparser 160b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # does not check for this, so we do that now 161b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'eof': 162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail_eof(end_tokens) 163b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 164b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if drop_needle: 165b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 166b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return result 167b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 168b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_set(self): 169b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Parse an assign statement.""" 170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = next(self.stream).lineno 171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) target = self.parse_assign_target() 172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('assign') 173b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) expr = self.parse_tuple() 174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Assign(target, expr, lineno=lineno) 175b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 176b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_for(self): 177b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Parse a for loop.""" 178b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.expect('name:for').lineno 179b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) target = self.parse_assign_target(extra_end_rules=('name:in',)) 180b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('name:in') 181b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) iter = self.parse_tuple(with_condexpr=False, 182b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) extra_end_rules=('name:recursive',)) 183b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) test = None 184b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.skip_if('name:if'): 185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) test = self.parse_expression() 186b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) recursive = self.stream.skip_if('name:recursive') 187b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) body = self.parse_statements(('name:endfor', 'name:else')) 188b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if next(self.stream).value == 'endfor': 189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else_ = [] 190b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 191b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else_ = self.parse_statements(('name:endfor',), drop_needle=True) 192b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.For(target, iter, body, else_, test, 193b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) recursive, lineno=lineno) 194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 195b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_if(self): 196b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Parse an if construct.""" 197b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = result = nodes.If(lineno=self.stream.expect('name:if').lineno) 198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while 1: 199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.test = self.parse_tuple(with_condexpr=False) 200b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.body = self.parse_statements(('name:elif', 'name:else', 201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'name:endif')) 202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token = next(self.stream) 203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token.test('name:elif'): 204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) new_node = nodes.If(lineno=self.stream.current.lineno) 205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.else_ = [new_node] 206b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = new_node 207b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue 208b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token.test('name:else'): 209b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.else_ = self.parse_statements(('name:endif',), 210b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) drop_needle=True) 211b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 212b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.else_ = [] 213b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return result 215b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_block(self): 217b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Block(lineno=next(self.stream).lineno) 218b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.name = self.stream.expect('name').value 219b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.scoped = self.stream.skip_if('name:scoped') 220b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 221b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # common problem people encounter when switching from django 222b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # to jinja. we do not support hyphens in block names, so let's 223b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # raise a nicer error message in that case. 224b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'sub': 225b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail('Block names in Jinja have to be valid Python ' 226b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'identifiers and may not contain hypens, use an ' 227b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'underscore instead.') 228b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 229b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.body = self.parse_statements(('name:endblock',), drop_needle=True) 230b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.skip_if('name:' + node.name) 231b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 232b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 233b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_extends(self): 234b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Extends(lineno=next(self.stream).lineno) 235b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.template = self.parse_expression() 236b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 237b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_import_context(self, node, default): 239b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.test_any('name:with', 'name:without') and \ 240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.look().test('name:context'): 241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.with_context = next(self.stream).value == 'with' 242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.skip() 243b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 244b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.with_context = default 245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 246b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_include(self): 248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Include(lineno=next(self.stream).lineno) 249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.template = self.parse_expression() 250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.test('name:ignore') and \ 251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.look().test('name:missing'): 252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.ignore_missing = True 253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.skip(2) 254b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 255b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.ignore_missing = False 256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self.parse_import_context(node, True) 257b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 258b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_import(self): 259b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Import(lineno=next(self.stream).lineno) 260b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.template = self.parse_expression() 261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('name:as') 262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.target = self.parse_assign_target(name_only=True).name 263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self.parse_import_context(node, False) 264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_from(self): 266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.FromImport(lineno=next(self.stream).lineno) 267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.template = self.parse_expression() 268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('name:import') 269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.names = [] 270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_context(): 272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.value in ('with', 'without') and \ 273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.look().test('name:context'): 274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.with_context = next(self.stream).value == 'with' 275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.skip() 276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return True 277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return False 278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while 1: 280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if node.names: 281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('comma') 282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'name': 283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if parse_context(): 284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) target = self.parse_assign_target(name_only=True) 286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if target.name.startswith('_'): 287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail('names starting with an underline can not ' 288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'be imported', target.lineno, 289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) exc=TemplateAssertionError) 290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.skip_if('name:as'): 291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) alias = self.parse_assign_target(name_only=True) 292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.names.append((target.name, alias.name)) 293b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 294b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.names.append(target.name) 295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if parse_context() or self.stream.current.type != 'comma': 296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 297b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 298b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not hasattr(node, 'with_context'): 300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.with_context = False 301b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.skip_if('comma') 302b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 303b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 304b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_signature(self, node): 305b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.args = args = [] 306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.defaults = defaults = [] 307b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('lparen') 308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type != 'rparen': 309b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if args: 310b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('comma') 311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) arg = self.parse_assign_target(name_only=True) 312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) arg.set_ctx('param') 313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.skip_if('assign'): 314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) defaults.append(self.parse_expression()) 315b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args.append(arg) 316b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('rparen') 317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 318b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_call_block(self): 319b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.CallBlock(lineno=next(self.stream).lineno) 320b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'lparen': 321b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.parse_signature(node) 322b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 323b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.args = [] 324b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.defaults = [] 325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 326b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.call = self.parse_expression() 327b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not isinstance(node.call, nodes.Call): 328b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail('expected call', node.lineno) 329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.body = self.parse_statements(('name:endcall',), drop_needle=True) 330b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_filter_block(self): 333b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.FilterBlock(lineno=next(self.stream).lineno) 334b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.filter = self.parse_filter(None, start_inline=True) 335b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.body = self.parse_statements(('name:endfilter',), 336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) drop_needle=True) 337b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 338b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 339b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_macro(self): 340b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Macro(lineno=next(self.stream).lineno) 341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.name = self.parse_assign_target(name_only=True).name 342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.parse_signature(node) 343b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.body = self.parse_statements(('name:endmacro',), 344b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) drop_needle=True) 345b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 346b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 347b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_print(self): 348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Output(lineno=next(self.stream).lineno) 349b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.nodes = [] 350b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type != 'block_end': 351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if node.nodes: 352b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('comma') 353b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node.nodes.append(self.parse_expression()) 354b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 356b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_assign_target(self, with_tuple=True, name_only=False, 357b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) extra_end_rules=None): 358b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Parse an assignment target. As Jinja2 allows assignments to 359b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) tuples, this function can parse all allowed assignment targets. Per 360b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) default assignments to tuples are parsed, that can be disable however 361b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) by setting `with_tuple` to `False`. If only assignments to names are 362b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) wanted `name_only` can be set to `True`. The `extra_end_rules` 363b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) parameter is forwarded to the tuple parsing function. 364b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """ 365b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if name_only: 366b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token = self.stream.expect('name') 367b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) target = nodes.Name(token.value, 'store', lineno=token.lineno) 368b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 369b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if with_tuple: 370b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) target = self.parse_tuple(simplified=True, 371b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) extra_end_rules=extra_end_rules) 372b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 373b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) target = self.parse_primary() 374b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) target.set_ctx('store') 375b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not target.can_assign(): 376b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail('can\'t assign to %r' % target.__class__. 377b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) __name__.lower(), target.lineno) 378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return target 379b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 380b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_expression(self, with_condexpr=True): 381b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Parse an expression. Per default all expressions are parsed, if 382b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) the optional `with_condexpr` parameter is set to `False` conditional 383b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) expressions are not parsed. 384b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """ 385b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if with_condexpr: 386b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self.parse_condexpr() 387b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self.parse_or() 388b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 389b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_condexpr(self): 390b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 391b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) expr1 = self.parse_or() 392b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.skip_if('name:if'): 393b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) expr2 = self.parse_or() 394b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.skip_if('name:else'): 395b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) expr3 = self.parse_condexpr() 396b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 397b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) expr3 = None 398b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) expr1 = nodes.CondExpr(expr2, expr1, expr3, lineno=lineno) 399b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 400b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return expr1 401b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 402b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_or(self): 403b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 404b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = self.parse_and() 405b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.skip_if('name:or'): 406b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) right = self.parse_and() 407b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = nodes.Or(left, right, lineno=lineno) 408b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 409b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return left 410b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 411b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_and(self): 412b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 413b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = self.parse_not() 414b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.skip_if('name:and'): 415b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) right = self.parse_not() 416b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = nodes.And(left, right, lineno=lineno) 417b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return left 419b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 420b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_not(self): 421b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.test('name:not'): 422b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = next(self.stream).lineno 423b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Not(self.parse_not(), lineno=lineno) 424b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self.parse_compare() 425b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 426b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_compare(self): 427b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 428b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) expr = self.parse_add() 429b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ops = [] 430b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while 1: 431b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token_type = self.stream.current.type 432b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token_type in _compare_operators: 433b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 434b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ops.append(nodes.Operand(token_type, self.parse_add())) 435b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif self.stream.skip_if('name:in'): 436b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ops.append(nodes.Operand('in', self.parse_add())) 437b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif self.stream.current.test('name:not') and \ 438b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.look().test('name:in'): 439b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.skip(2) 440b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ops.append(nodes.Operand('notin', self.parse_add())) 441b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 442b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 443b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 444b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not ops: 445b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return expr 446b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Compare(expr, ops, lineno=lineno) 447b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 448b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_add(self): 449b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 450b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = self.parse_sub() 451b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'add': 452b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 453b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) right = self.parse_sub() 454b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = nodes.Add(left, right, lineno=lineno) 455b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 456b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return left 457b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 458b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_sub(self): 459b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 460b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = self.parse_concat() 461b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'sub': 462b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 463b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) right = self.parse_concat() 464b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = nodes.Sub(left, right, lineno=lineno) 465b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 466b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return left 467b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 468b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_concat(self): 469b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 470b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args = [self.parse_mul()] 471b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'tilde': 472b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 473b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args.append(self.parse_mul()) 474b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if len(args) == 1: 475b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return args[0] 476b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Concat(args, lineno=lineno) 477b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 478b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_mul(self): 479b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 480b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = self.parse_div() 481b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'mul': 482b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 483b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) right = self.parse_div() 484b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = nodes.Mul(left, right, lineno=lineno) 485b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 486b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return left 487b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 488b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_div(self): 489b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 490b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = self.parse_floordiv() 491b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'div': 492b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 493b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) right = self.parse_floordiv() 494b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = nodes.Div(left, right, lineno=lineno) 495b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 496b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return left 497b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 498b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_floordiv(self): 499b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 500b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = self.parse_mod() 501b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'floordiv': 502b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 503b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) right = self.parse_mod() 504b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = nodes.FloorDiv(left, right, lineno=lineno) 505b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 506b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return left 507b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 508b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_mod(self): 509b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 510b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = self.parse_pow() 511b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'mod': 512b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 513b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) right = self.parse_pow() 514b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = nodes.Mod(left, right, lineno=lineno) 515b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 516b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return left 517b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 518b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_pow(self): 519b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 520b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = self.parse_unary() 521b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'pow': 522b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 523b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) right = self.parse_unary() 524b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) left = nodes.Pow(left, right, lineno=lineno) 525b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 526b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return left 527b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 528b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_unary(self, with_filter=True): 529b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token_type = self.stream.current.type 530b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 531b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token_type == 'sub': 532b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 533b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Neg(self.parse_unary(False), lineno=lineno) 534b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token_type == 'add': 535b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 536b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Pos(self.parse_unary(False), lineno=lineno) 537b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 538b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_primary() 539b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_postfix(node) 540b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if with_filter: 541b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_filter_expr(node) 542b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 543b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 544b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_primary(self): 545b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token = self.stream.current 546b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token.type == 'name': 547b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token.value in ('true', 'false', 'True', 'False'): 548b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Const(token.value in ('true', 'True'), 549b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno=token.lineno) 550b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token.value in ('none', 'None'): 551b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Const(None, lineno=token.lineno) 552b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 553b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Name(token.value, 'load', lineno=token.lineno) 554b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 555b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token.type == 'string': 556b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 557b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) buf = [token.value] 558b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = token.lineno 559b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'string': 560b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) buf.append(self.stream.current.value) 561b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 562b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Const(''.join(buf), lineno=lineno) 563b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token.type in ('integer', 'float'): 564b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 565b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Const(token.value, lineno=token.lineno) 566b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token.type == 'lparen': 567b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 568b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_tuple(explicit_parentheses=True) 569b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('rparen') 570b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token.type == 'lbracket': 571b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_list() 572b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token.type == 'lbrace': 573b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_dict() 574b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 575b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail("unexpected '%s'" % describe_token(token), token.lineno) 576b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 577b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 578b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_tuple(self, simplified=False, with_condexpr=True, 579b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) extra_end_rules=None, explicit_parentheses=False): 580b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Works like `parse_expression` but if multiple expressions are 581b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) delimited by a comma a :class:`~jinja2.nodes.Tuple` node is created. 582b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) This method could also return a regular expression instead of a tuple 583b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if no commas where found. 584b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 585b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) The default parsing mode is a full tuple. If `simplified` is `True` 586b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) only names and literals are parsed. The `no_condexpr` parameter is 587b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) forwarded to :meth:`parse_expression`. 588b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 589b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Because tuples do not require delimiters and may end in a bogus comma 590b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) an extra hint is needed that marks the end of a tuple. For example 591b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for loops support tuples between `for` and `in`. In that case the 592b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) `extra_end_rules` is set to ``['name:in']``. 593b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 594b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) `explicit_parentheses` is true if the parsing was triggered by an 595b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) expression in parentheses. This is used to figure out if an empty 596b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) tuple is a valid expression or not. 597b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """ 598b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if simplified: 600b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) parse = self.parse_primary 601b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif with_condexpr: 602b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) parse = self.parse_expression 603b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 604b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) parse = lambda: self.parse_expression(with_condexpr=False) 605b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args = [] 606b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) is_tuple = False 607b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while 1: 608b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if args: 609b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('comma') 610b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.is_tuple_end(extra_end_rules): 611b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 612b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args.append(parse()) 613b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'comma': 614b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) is_tuple = True 615b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 616b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 617b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 618b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 619b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not is_tuple: 620b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if args: 621b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return args[0] 622b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 623b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # if we don't have explicit parentheses, an empty tuple is 624b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # not a valid expression. This would mean nothing (literally 625b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # nothing) in the spot of an expression would be an empty 626b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # tuple. 627b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not explicit_parentheses: 628b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail('Expected an expression, got \'%s\'' % 629b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) describe_token(self.stream.current)) 630b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 631b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Tuple(args, 'load', lineno=lineno) 632b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 633b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_list(self): 634b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token = self.stream.expect('lbracket') 635b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) items = [] 636b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type != 'rbracket': 637b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if items: 638b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('comma') 639b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'rbracket': 640b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 641b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) items.append(self.parse_expression()) 642b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('rbracket') 643b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.List(items, lineno=token.lineno) 644b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 645b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_dict(self): 646b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token = self.stream.expect('lbrace') 647b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) items = [] 648b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type != 'rbrace': 649b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if items: 650b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('comma') 651b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'rbrace': 652b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 653b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) key = self.parse_expression() 654b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('colon') 655b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) value = self.parse_expression() 656b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) items.append(nodes.Pair(key, value, lineno=key.lineno)) 657b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('rbrace') 658b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Dict(items, lineno=token.lineno) 659b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 660b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_postfix(self, node): 661b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while 1: 662b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token_type = self.stream.current.type 663b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token_type == 'dot' or token_type == 'lbracket': 664b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_subscript(node) 665b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # calls are valid both after postfix expressions (getattr 666b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # and getitem) as well as filters and tests 667b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token_type == 'lparen': 668b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_call(node) 669b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 670b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 671b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 672b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 673b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_filter_expr(self, node): 674b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while 1: 675b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token_type = self.stream.current.type 676b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token_type == 'pipe': 677b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_filter(node) 678b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token_type == 'name' and self.stream.current.value == 'is': 679b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_test(node) 680b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # calls are valid both after postfix expressions (getattr 681b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # and getitem) as well as filters and tests 682b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token_type == 'lparen': 683b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_call(node) 684b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 685b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 686b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 687b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 688b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_subscript(self, node): 689b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token = next(self.stream) 690b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token.type == 'dot': 691b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) attr_token = self.stream.current 692b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 693b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if attr_token.type == 'name': 694b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Getattr(node, attr_token.value, 'load', 695b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno=token.lineno) 696b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif attr_token.type != 'integer': 697b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail('expected name or number', attr_token.lineno) 698b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) arg = nodes.Const(attr_token.value, lineno=attr_token.lineno) 699b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Getitem(node, arg, 'load', lineno=token.lineno) 700b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token.type == 'lbracket': 701b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) priority_on_attribute = False 702b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args = [] 703b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type != 'rbracket': 704b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if args: 705b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('comma') 706b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args.append(self.parse_subscribed()) 707b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('rbracket') 708b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if len(args) == 1: 709b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) arg = args[0] 710b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 711b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) arg = nodes.Tuple(args, 'load', lineno=token.lineno) 712b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Getitem(node, arg, 'load', lineno=token.lineno) 713b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail('expected subscript expression', self.lineno) 714b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 715b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_subscribed(self): 716b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = self.stream.current.lineno 717b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 718b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'colon': 719b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 720b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args = [None] 721b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 722b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.parse_expression() 723b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type != 'colon': 724b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 725b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 726b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args = [node] 727b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 728b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'colon': 729b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args.append(None) 730b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif self.stream.current.type not in ('rbracket', 'comma'): 731b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args.append(self.parse_expression()) 732b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 733b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args.append(None) 734b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 735b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'colon': 736b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 737b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type not in ('rbracket', 'comma'): 738b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args.append(self.parse_expression()) 739b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 740b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args.append(None) 741b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 742b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args.append(None) 743b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 744b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Slice(lineno=lineno, *args) 745b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 746b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_call(self, node): 747b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token = self.stream.expect('lparen') 748b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args = [] 749b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) kwargs = [] 750b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) dyn_args = dyn_kwargs = None 751b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) require_comma = False 752b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 753b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def ensure(expr): 754b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not expr: 755b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail('invalid syntax for function call expression', 756b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token.lineno) 757b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 758b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type != 'rparen': 759b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if require_comma: 760b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('comma') 761b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # support for trailing comma 762b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'rparen': 763b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 764b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'mul': 765b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ensure(dyn_args is None and dyn_kwargs is None) 766b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 767b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) dyn_args = self.parse_expression() 768b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif self.stream.current.type == 'pow': 769b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ensure(dyn_kwargs is None) 770b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 771b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) dyn_kwargs = self.parse_expression() 772b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 773b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ensure(dyn_args is None and dyn_kwargs is None) 774b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'name' and \ 775b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.look().type == 'assign': 776b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) key = self.stream.current.value 777b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.skip(2) 778b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) value = self.parse_expression() 779b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) kwargs.append(nodes.Keyword(key, value, 780b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno=value.lineno)) 781b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 782b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ensure(not kwargs) 783b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args.append(self.parse_expression()) 784b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 785b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) require_comma = True 786b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('rparen') 787b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 788b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if node is None: 789b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return args, kwargs, dyn_args, dyn_kwargs 790b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Call(node, args, kwargs, dyn_args, dyn_kwargs, 791b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno=token.lineno) 792b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 793b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_filter(self, node, start_inline=False): 794b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'pipe' or start_inline: 795b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not start_inline: 796b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 797b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token = self.stream.expect('name') 798b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) name = token.value 799b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'dot': 800b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 801b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) name += '.' + self.stream.expect('name').value 802b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'lparen': 803b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None) 804b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 805b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args = [] 806b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) kwargs = [] 807b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) dyn_args = dyn_kwargs = None 808b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Filter(node, name, args, kwargs, dyn_args, 809b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) dyn_kwargs, lineno=token.lineno) 810b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) start_inline = False 811b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 812b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 813b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse_test(self, node): 814b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token = next(self.stream) 815b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.test('name:not'): 816b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 817b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) negated = True 818b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 819b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) negated = False 820b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) name = self.stream.expect('name').value 821b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream.current.type == 'dot': 822b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 823b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) name += '.' + self.stream.expect('name').value 824b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) dyn_args = dyn_kwargs = None 825b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) kwargs = [] 826b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.type == 'lparen': 827b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None) 828b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif self.stream.current.type in ('name', 'string', 'integer', 829b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'float', 'lparen', 'lbracket', 830b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'lbrace') and not \ 831b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.current.test_any('name:else', 'name:or', 832b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 'name:and'): 833b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if self.stream.current.test('name:is'): 834b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.fail('You cannot chain multiple tests with is') 835b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args = [self.parse_expression()] 836b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 837b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) args = [] 838b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Test(node, name, args, kwargs, dyn_args, 839b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) dyn_kwargs, lineno=token.lineno) 840b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if negated: 841b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = nodes.Not(node, lineno=token.lineno) 842b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 843b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 844b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def subparse(self, end_tokens=None): 845b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) body = [] 846b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) data_buffer = [] 847b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) add_data = data_buffer.append 848b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 849b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if end_tokens is not None: 850b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._end_token_stack.append(end_tokens) 851b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 852b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def flush_data(): 853b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if data_buffer: 854b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno = data_buffer[0].lineno 855b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) body.append(nodes.Output(data_buffer[:], lineno=lineno)) 856b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) del data_buffer[:] 857b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 858b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) try: 859b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while self.stream: 860b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) token = self.stream.current 861b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token.type == 'data': 862b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if token.value: 863b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) add_data(nodes.TemplateData(token.value, 864b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno=token.lineno)) 865b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 866b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token.type == 'variable_begin': 867b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 868b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) add_data(self.parse_tuple(with_condexpr=True)) 869b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('variable_end') 870b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif token.type == 'block_begin': 871b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) flush_data() 872b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) next(self.stream) 873b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if end_tokens is not None and \ 874b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.current.test_any(*end_tokens): 875b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return body 876b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) rv = self.parse_statement() 877b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if isinstance(rv, list): 878b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) body.extend(rv) 879b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 880b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) body.append(rv) 881b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.stream.expect('block_end') 882b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 883b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) raise AssertionError('internal parsing error') 884b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 885b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) flush_data() 886b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) finally: 887b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if end_tokens is not None: 888b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._end_token_stack.pop() 889b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 890b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return body 891b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 892b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def parse(self): 893b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Parse the whole template into a `Template` node.""" 894b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) result = nodes.Template(self.subparse(), lineno=1) 895b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) result.set_environment(self.environment) 896b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return result 897