blob: 96980d1c9af66c71b0cc6c9c7e889bf08cc23af2 [file] [log] [blame]
Armin Ronacher07bc6842008-03-31 14:18:49 +02001# -*- coding: utf-8 -*-
2"""
3 jinja2.parser
4 ~~~~~~~~~~~~~
5
6 Implements the template parser.
7
Armin Ronacher55494e42010-01-22 09:41:48 +01008 :copyright: (c) 2010 by the Jinja Team.
Armin Ronacher07bc6842008-03-31 14:18:49 +02009 :license: BSD, see LICENSE for more details.
10"""
Armin Ronacher82b3f3d2008-03-31 20:01:08 +020011from jinja2 import nodes
Armin Ronachera78d2762008-05-15 23:18:07 +020012from jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError
Armin Ronacherbd357722009-08-05 20:25:06 +020013from jinja2.utils import next
Armin Ronacher5dcb7242010-02-06 14:01:26 +010014from jinja2.lexer import describe_token, describe_token_expr
Armin Ronacher07bc6842008-03-31 14:18:49 +020015
16
Armin Ronacher5dcb7242010-02-06 14:01:26 +010017#: statements that callinto
Armin Ronachere791c2a2008-04-07 18:39:54 +020018_statement_keywords = frozenset(['for', 'if', 'block', 'extends', 'print',
Armin Ronacher0a2ac692008-05-13 01:03:08 +020019 'macro', 'include', 'from', 'import',
20 'set'])
Armin Ronacher115de2e2008-05-01 22:20:05 +020021_compare_operators = frozenset(['eq', 'ne', 'lt', 'lteq', 'gt', 'gteq'])
Armin Ronacher82b3f3d2008-03-31 20:01:08 +020022
Armin Ronacher07bc6842008-03-31 14:18:49 +020023
24class Parser(object):
Armin Ronacher023b5e92008-05-08 11:03:10 +020025 """This is the central parsing class Jinja2 uses. It's passed to
26 extensions and can be used to parse expressions or statements.
Armin Ronacher07bc6842008-03-31 14:18:49 +020027 """
28
Armin Ronacherba6e25a2008-11-02 15:58:14 +010029 def __init__(self, environment, source, name=None, filename=None,
30 state=None):
Armin Ronacher07bc6842008-03-31 14:18:49 +020031 self.environment = environment
Armin Ronacherba6e25a2008-11-02 15:58:14 +010032 self.stream = environment._tokenize(source, name, filename, state)
Armin Ronacher7f15ef82008-05-16 09:11:39 +020033 self.name = name
Armin Ronacher07bc6842008-03-31 14:18:49 +020034 self.filename = filename
35 self.closed = False
Armin Ronacher05530932008-04-20 13:27:49 +020036 self.extensions = {}
Armin Ronacher023b5e92008-05-08 11:03:10 +020037 for extension in environment.extensions.itervalues():
Armin Ronacher05530932008-04-20 13:27:49 +020038 for tag in extension.tags:
39 self.extensions[tag] = extension.parse
Armin Ronacher023b5e92008-05-08 11:03:10 +020040 self._last_identifier = 0
Armin Ronacher5dcb7242010-02-06 14:01:26 +010041 self._tag_stack = []
42 self._end_token_stack = []
Armin Ronacher115de2e2008-05-01 22:20:05 +020043
Armin Ronacher7f15ef82008-05-16 09:11:39 +020044 def fail(self, msg, lineno=None, exc=TemplateSyntaxError):
45 """Convenience method that raises `exc` with the message, passed
46 line number or last line number as well as the current name and
47 filename.
48 """
49 if lineno is None:
50 lineno = self.stream.current.lineno
Armin Ronacher61a5a242008-05-26 12:07:44 +020051 raise exc(msg, lineno, self.name, self.filename)
Armin Ronacher7f15ef82008-05-16 09:11:39 +020052
Armin Ronacher5dcb7242010-02-06 14:01:26 +010053 def _fail_ut_eof(self, name, end_token_stack, lineno):
54 expected = []
55 for exprs in end_token_stack:
56 expected.extend(map(describe_token_expr, exprs))
57 currently_looking = ' or '.join("'%s'" % describe_token_expr(expr)
58 for expr in end_token_stack[-1])
59
60 if name is None:
61 message = ['Unexpected end of template.']
62 else:
63 message = ['Encountered unknown tag \'%s\'.' % name]
64
65 if name is not None and name in expected:
66 message.append('You probably made a nesting mistake. Jinja '
67 'is expecting this tag, but currently looking '
68 'for %s.' % currently_looking)
69 else:
70 message.append('Jinja was looking for the following tags: '
71 '%s.' % currently_looking)
72
73 if self._tag_stack:
74 message.append('The innermost block that needs to be '
75 'closed is \'%s\'.' % self._tag_stack[-1])
76
77 self.fail(' '.join(message), lineno)
78
79 def fail_unknown_tag(self, name, lineno=None):
80 """Called if the parser encounters an unknown tag. Tries to fail
81 with a human readable error message that could help to identify
82 the problem.
83 """
84 return self._fail_ut_eof(name, self._end_token_stack, lineno)
85
86 def fail_eof(self, end_tokens=None, lineno=None):
87 """Like fail_unknown_tag but for end of template situations."""
88 stack = list(self._end_token_stack)
89 if end_tokens is not None:
90 stack.append(end_tokens)
91 return self._fail_ut_eof(None, stack, lineno)
92
Armin Ronacherfdf95302008-05-11 22:20:51 +020093 def is_tuple_end(self, extra_end_rules=None):
Armin Ronacher115de2e2008-05-01 22:20:05 +020094 """Are we at the end of a tuple?"""
Armin Ronacherfdf95302008-05-11 22:20:51 +020095 if self.stream.current.type in ('variable_end', 'block_end', 'rparen'):
Armin Ronacher023b5e92008-05-08 11:03:10 +020096 return True
Armin Ronacherfdf95302008-05-11 22:20:51 +020097 elif extra_end_rules is not None:
98 return self.stream.current.test_any(extra_end_rules)
Armin Ronacher762079c2008-05-08 23:57:56 +020099 return False
100
Armin Ronacher023b5e92008-05-08 11:03:10 +0200101 def free_identifier(self, lineno=None):
102 """Return a new free identifier as :class:`~jinja2.nodes.InternalName`."""
103 self._last_identifier += 1
104 rv = object.__new__(nodes.InternalName)
105 nodes.Node.__init__(rv, 'fi%d' % self._last_identifier, lineno=lineno)
106 return rv
Armin Ronacher115de2e2008-05-01 22:20:05 +0200107
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200108 def parse_statement(self):
109 """Parse a single statement."""
Armin Ronacher0a2ac692008-05-13 01:03:08 +0200110 token = self.stream.current
Ali Afshar272ca2a2009-01-05 12:14:14 +0100111 if token.type != 'name':
Armin Ronacher7f15ef82008-05-16 09:11:39 +0200112 self.fail('tag name expected', token.lineno)
Armin Ronacher5dcb7242010-02-06 14:01:26 +0100113 self._tag_stack.append(token.value)
114 pop_tag = True
115 try:
116 if token.value in _statement_keywords:
117 return getattr(self, 'parse_' + self.stream.current.value)()
118 if token.value == 'call':
119 return self.parse_call_block()
120 if token.value == 'filter':
121 return self.parse_filter_block()
122 ext = self.extensions.get(token.value)
123 if ext is not None:
124 return ext(self)
125
126 # did not work out, remove the token we pushed by accident
127 # from the stack so that the unknown tag fail function can
128 # produce a proper error message.
129 self._tag_stack.pop()
130 pop_tag = False
131 self.fail_unknown_tag(token.value, token.lineno)
132 finally:
133 if pop_tag:
134 self._tag_stack.pop()
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200135
136 def parse_statements(self, end_tokens, drop_needle=False):
Armin Ronacherf59bac22008-04-20 13:11:43 +0200137 """Parse multiple statements into a list until one of the end tokens
138 is reached. This is used to parse the body of statements as it also
Armin Ronacher023b5e92008-05-08 11:03:10 +0200139 parses template data if appropriate. The parser checks first if the
140 current token is a colon and skips it if there is one. Then it checks
141 for the block end and parses until if one of the `end_tokens` is
142 reached. Per default the active token in the stream at the end of
143 the call is the matched end token. If this is not wanted `drop_needle`
144 can be set to `True` and the end token is removed.
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200145 """
146 # the first token may be a colon for python compatibility
Armin Ronacherfdf95302008-05-11 22:20:51 +0200147 self.stream.skip_if('colon')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200148
Armin Ronacher2b60fe52008-04-21 08:23:59 +0200149 # in the future it would be possible to add whole code sections
150 # by adding some sort of end of statement token and parsing those here.
151 self.stream.expect('block_end')
152 result = self.subparse(end_tokens)
153
Armin Ronacher5dcb7242010-02-06 14:01:26 +0100154 # we reached the end of the template too early, the subparser
155 # does not check for this, so we do that now
156 if self.stream.current.type == 'eof':
157 self.fail_eof(end_tokens)
158
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200159 if drop_needle:
Armin Ronacherbd357722009-08-05 20:25:06 +0200160 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200161 return result
162
Armin Ronacher0a2ac692008-05-13 01:03:08 +0200163 def parse_set(self):
164 """Parse an assign statement."""
Armin Ronacherbd357722009-08-05 20:25:06 +0200165 lineno = next(self.stream).lineno
Armin Ronacher0a2ac692008-05-13 01:03:08 +0200166 target = self.parse_assign_target()
167 self.stream.expect('assign')
168 expr = self.parse_tuple()
169 return nodes.Assign(target, expr, lineno=lineno)
170
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200171 def parse_for(self):
172 """Parse a for loop."""
Armin Ronacher115de2e2008-05-01 22:20:05 +0200173 lineno = self.stream.expect('name:for').lineno
Armin Ronacherfdf95302008-05-11 22:20:51 +0200174 target = self.parse_assign_target(extra_end_rules=('name:in',))
Armin Ronacher115de2e2008-05-01 22:20:05 +0200175 self.stream.expect('name:in')
Armin Ronacherfdf95302008-05-11 22:20:51 +0200176 iter = self.parse_tuple(with_condexpr=False,
177 extra_end_rules=('name:recursive',))
Armin Ronacher3d8b7842008-04-13 13:16:50 +0200178 test = None
Armin Ronacherfdf95302008-05-11 22:20:51 +0200179 if self.stream.skip_if('name:if'):
Armin Ronacher3d8b7842008-04-13 13:16:50 +0200180 test = self.parse_expression()
Armin Ronacherfdf95302008-05-11 22:20:51 +0200181 recursive = self.stream.skip_if('name:recursive')
Armin Ronacher115de2e2008-05-01 22:20:05 +0200182 body = self.parse_statements(('name:endfor', 'name:else'))
Armin Ronacherbd357722009-08-05 20:25:06 +0200183 if next(self.stream).value == 'endfor':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200184 else_ = []
185 else:
Armin Ronacher115de2e2008-05-01 22:20:05 +0200186 else_ = self.parse_statements(('name:endfor',), drop_needle=True)
Armin Ronacherfdf95302008-05-11 22:20:51 +0200187 return nodes.For(target, iter, body, else_, test,
188 recursive, lineno=lineno)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200189
190 def parse_if(self):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200191 """Parse an if construct."""
Armin Ronacher115de2e2008-05-01 22:20:05 +0200192 node = result = nodes.If(lineno=self.stream.expect('name:if').lineno)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200193 while 1:
Armin Ronacher09c002e2008-05-10 22:21:30 +0200194 node.test = self.parse_tuple(with_condexpr=False)
Armin Ronacher115de2e2008-05-01 22:20:05 +0200195 node.body = self.parse_statements(('name:elif', 'name:else',
196 'name:endif'))
Armin Ronacherbd357722009-08-05 20:25:06 +0200197 token = next(self.stream)
Armin Ronacher115de2e2008-05-01 22:20:05 +0200198 if token.test('name:elif'):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200199 new_node = nodes.If(lineno=self.stream.current.lineno)
200 node.else_ = [new_node]
201 node = new_node
202 continue
Armin Ronacher115de2e2008-05-01 22:20:05 +0200203 elif token.test('name:else'):
204 node.else_ = self.parse_statements(('name:endif',),
Armin Ronachere791c2a2008-04-07 18:39:54 +0200205 drop_needle=True)
206 else:
207 node.else_ = []
208 break
209 return result
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200210
211 def parse_block(self):
Armin Ronacherbd357722009-08-05 20:25:06 +0200212 node = nodes.Block(lineno=next(self.stream).lineno)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200213 node.name = self.stream.expect('name').value
Armin Ronacher74a0cd92009-02-19 15:56:53 +0100214 node.scoped = self.stream.skip_if('name:scoped')
Armin Ronacher92622e92010-02-07 01:27:47 +0100215
216 # common problem people encounter when switching from django
217 # to jinja. we do not support hyphens in block names, so let's
218 # raise a nicer error message in that case.
219 if self.stream.current.type == 'sub':
220 self.fail('Block names in Jinja have to be valid Python '
221 'identifiers and may not contain hypens, use an '
222 'underscore instead.')
223
Armin Ronacher115de2e2008-05-01 22:20:05 +0200224 node.body = self.parse_statements(('name:endblock',), drop_needle=True)
Armin Ronacherfd310492008-05-25 00:16:51 +0200225 self.stream.skip_if('name:' + node.name)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200226 return node
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200227
228 def parse_extends(self):
Armin Ronacherbd357722009-08-05 20:25:06 +0200229 node = nodes.Extends(lineno=next(self.stream).lineno)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200230 node.template = self.parse_expression()
Armin Ronachere791c2a2008-04-07 18:39:54 +0200231 return node
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200232
Armin Ronacherea847c52008-05-02 20:04:32 +0200233 def parse_import_context(self, node, default):
Armin Ronachercda43df2008-05-03 17:10:05 +0200234 if self.stream.current.test_any('name:with', 'name:without') and \
Armin Ronacherea847c52008-05-02 20:04:32 +0200235 self.stream.look().test('name:context'):
Armin Ronacherbd357722009-08-05 20:25:06 +0200236 node.with_context = next(self.stream).value == 'with'
Armin Ronacherea847c52008-05-02 20:04:32 +0200237 self.stream.skip()
238 else:
239 node.with_context = default
240 return node
241
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200242 def parse_include(self):
Armin Ronacherbd357722009-08-05 20:25:06 +0200243 node = nodes.Include(lineno=next(self.stream).lineno)
Armin Ronacher0611e492008-04-25 23:44:14 +0200244 node.template = self.parse_expression()
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100245 if self.stream.current.test('name:ignore') and \
246 self.stream.look().test('name:missing'):
247 node.ignore_missing = True
248 self.stream.skip(2)
249 else:
250 node.ignore_missing = False
Armin Ronacherea847c52008-05-02 20:04:32 +0200251 return self.parse_import_context(node, True)
Armin Ronacher0611e492008-04-25 23:44:14 +0200252
253 def parse_import(self):
Armin Ronacherbd357722009-08-05 20:25:06 +0200254 node = nodes.Import(lineno=next(self.stream).lineno)
Armin Ronacher0611e492008-04-25 23:44:14 +0200255 node.template = self.parse_expression()
256 self.stream.expect('name:as')
Armin Ronacher09c002e2008-05-10 22:21:30 +0200257 node.target = self.parse_assign_target(name_only=True).name
Armin Ronacherea847c52008-05-02 20:04:32 +0200258 return self.parse_import_context(node, False)
Armin Ronacher0611e492008-04-25 23:44:14 +0200259
260 def parse_from(self):
Armin Ronacherbd357722009-08-05 20:25:06 +0200261 node = nodes.FromImport(lineno=next(self.stream).lineno)
Armin Ronacher0611e492008-04-25 23:44:14 +0200262 node.template = self.parse_expression()
Armin Ronacher115de2e2008-05-01 22:20:05 +0200263 self.stream.expect('name:import')
Armin Ronacher0611e492008-04-25 23:44:14 +0200264 node.names = []
Armin Ronacherea847c52008-05-02 20:04:32 +0200265
266 def parse_context():
267 if self.stream.current.value in ('with', 'without') and \
268 self.stream.look().test('name:context'):
Armin Ronacherbd357722009-08-05 20:25:06 +0200269 node.with_context = next(self.stream).value == 'with'
Armin Ronacherea847c52008-05-02 20:04:32 +0200270 self.stream.skip()
271 return True
272 return False
273
Armin Ronacher0611e492008-04-25 23:44:14 +0200274 while 1:
275 if node.names:
276 self.stream.expect('comma')
Ali Afshar272ca2a2009-01-05 12:14:14 +0100277 if self.stream.current.type == 'name':
Armin Ronacherea847c52008-05-02 20:04:32 +0200278 if parse_context():
279 break
Armin Ronacher09c002e2008-05-10 22:21:30 +0200280 target = self.parse_assign_target(name_only=True)
Armin Ronacher903d1682008-05-23 00:51:58 +0200281 if target.name.startswith('_'):
282 self.fail('names starting with an underline can not '
Armin Ronacher7f15ef82008-05-16 09:11:39 +0200283 'be imported', target.lineno,
284 exc=TemplateAssertionError)
Armin Ronacherfdf95302008-05-11 22:20:51 +0200285 if self.stream.skip_if('name:as'):
Armin Ronacher09c002e2008-05-10 22:21:30 +0200286 alias = self.parse_assign_target(name_only=True)
287 node.names.append((target.name, alias.name))
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200288 else:
289 node.names.append(target.name)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100290 if parse_context() or self.stream.current.type != 'comma':
Armin Ronacher0611e492008-04-25 23:44:14 +0200291 break
292 else:
293 break
Armin Ronacherea847c52008-05-02 20:04:32 +0200294 if not hasattr(node, 'with_context'):
295 node.with_context = False
Armin Ronacherfdf95302008-05-11 22:20:51 +0200296 self.stream.skip_if('comma')
Armin Ronachere791c2a2008-04-07 18:39:54 +0200297 return node
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200298
Armin Ronacher71082072008-04-12 14:19:36 +0200299 def parse_signature(self, node):
300 node.args = args = []
301 node.defaults = defaults = []
302 self.stream.expect('lparen')
Ali Afshar272ca2a2009-01-05 12:14:14 +0100303 while self.stream.current.type != 'rparen':
Armin Ronacher71082072008-04-12 14:19:36 +0200304 if args:
305 self.stream.expect('comma')
Armin Ronacher09c002e2008-05-10 22:21:30 +0200306 arg = self.parse_assign_target(name_only=True)
Armin Ronachere9411b42008-05-15 16:22:07 +0200307 arg.set_ctx('param')
Armin Ronacherfdf95302008-05-11 22:20:51 +0200308 if self.stream.skip_if('assign'):
Armin Ronacher71082072008-04-12 14:19:36 +0200309 defaults.append(self.parse_expression())
310 args.append(arg)
311 self.stream.expect('rparen')
312
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200313 def parse_call_block(self):
Armin Ronacherbd357722009-08-05 20:25:06 +0200314 node = nodes.CallBlock(lineno=next(self.stream).lineno)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100315 if self.stream.current.type == 'lparen':
Armin Ronacher71082072008-04-12 14:19:36 +0200316 self.parse_signature(node)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200317 else:
318 node.args = []
319 node.defaults = []
Armin Ronacher71082072008-04-12 14:19:36 +0200320
Armin Ronacher8edbe492008-04-10 20:43:43 +0200321 node.call = self.parse_expression()
322 if not isinstance(node.call, nodes.Call):
Armin Ronacher7f15ef82008-05-16 09:11:39 +0200323 self.fail('expected call', node.lineno)
Armin Ronacher115de2e2008-05-01 22:20:05 +0200324 node.body = self.parse_statements(('name:endcall',), drop_needle=True)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200325 return node
326
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200327 def parse_filter_block(self):
Armin Ronacherbd357722009-08-05 20:25:06 +0200328 node = nodes.FilterBlock(lineno=next(self.stream).lineno)
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200329 node.filter = self.parse_filter(None, start_inline=True)
Armin Ronacher115de2e2008-05-01 22:20:05 +0200330 node.body = self.parse_statements(('name:endfilter',),
331 drop_needle=True)
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200332 return node
333
Armin Ronachere791c2a2008-04-07 18:39:54 +0200334 def parse_macro(self):
Armin Ronacherbd357722009-08-05 20:25:06 +0200335 node = nodes.Macro(lineno=next(self.stream).lineno)
Armin Ronacher09c002e2008-05-10 22:21:30 +0200336 node.name = self.parse_assign_target(name_only=True).name
Armin Ronacher71082072008-04-12 14:19:36 +0200337 self.parse_signature(node)
Armin Ronacher115de2e2008-05-01 22:20:05 +0200338 node.body = self.parse_statements(('name:endmacro',),
339 drop_needle=True)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200340 return node
341
342 def parse_print(self):
Armin Ronacherbd357722009-08-05 20:25:06 +0200343 node = nodes.Output(lineno=next(self.stream).lineno)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200344 node.nodes = []
Ali Afshar272ca2a2009-01-05 12:14:14 +0100345 while self.stream.current.type != 'block_end':
Armin Ronachere791c2a2008-04-07 18:39:54 +0200346 if node.nodes:
347 self.stream.expect('comma')
348 node.nodes.append(self.parse_expression())
Armin Ronachere791c2a2008-04-07 18:39:54 +0200349 return node
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200350
Armin Ronacherfdf95302008-05-11 22:20:51 +0200351 def parse_assign_target(self, with_tuple=True, name_only=False,
352 extra_end_rules=None):
Armin Ronacher09c002e2008-05-10 22:21:30 +0200353 """Parse an assignment target. As Jinja2 allows assignments to
354 tuples, this function can parse all allowed assignment targets. Per
355 default assignments to tuples are parsed, that can be disable however
356 by setting `with_tuple` to `False`. If only assignments to names are
Armin Ronacherfdf95302008-05-11 22:20:51 +0200357 wanted `name_only` can be set to `True`. The `extra_end_rules`
358 parameter is forwarded to the tuple parsing function.
Armin Ronacher09c002e2008-05-10 22:21:30 +0200359 """
360 if name_only:
361 token = self.stream.expect('name')
362 target = nodes.Name(token.value, 'store', lineno=token.lineno)
363 else:
364 if with_tuple:
Armin Ronacherfdf95302008-05-11 22:20:51 +0200365 target = self.parse_tuple(simplified=True,
366 extra_end_rules=extra_end_rules)
Armin Ronacher09c002e2008-05-10 22:21:30 +0200367 else:
368 target = self.parse_primary(with_postfix=False)
369 target.set_ctx('store')
370 if not target.can_assign():
Armin Ronacher7f15ef82008-05-16 09:11:39 +0200371 self.fail('can\'t assign to %r' % target.__class__.
372 __name__.lower(), target.lineno)
Armin Ronacher09c002e2008-05-10 22:21:30 +0200373 return target
374
375 def parse_expression(self, with_condexpr=True):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200376 """Parse an expression. Per default all expressions are parsed, if
Armin Ronacher09c002e2008-05-10 22:21:30 +0200377 the optional `with_condexpr` parameter is set to `False` conditional
Armin Ronacher023b5e92008-05-08 11:03:10 +0200378 expressions are not parsed.
379 """
Armin Ronacher09c002e2008-05-10 22:21:30 +0200380 if with_condexpr:
381 return self.parse_condexpr()
382 return self.parse_or()
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200383
384 def parse_condexpr(self):
385 lineno = self.stream.current.lineno
386 expr1 = self.parse_or()
Armin Ronacherfdf95302008-05-11 22:20:51 +0200387 while self.stream.skip_if('name:if'):
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200388 expr2 = self.parse_or()
Armin Ronacher547d0b62008-07-04 16:35:10 +0200389 if self.stream.skip_if('name:else'):
390 expr3 = self.parse_condexpr()
391 else:
392 expr3 = None
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200393 expr1 = nodes.CondExpr(expr2, expr1, expr3, lineno=lineno)
394 lineno = self.stream.current.lineno
395 return expr1
396
397 def parse_or(self):
398 lineno = self.stream.current.lineno
399 left = self.parse_and()
Armin Ronacherfdf95302008-05-11 22:20:51 +0200400 while self.stream.skip_if('name:or'):
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200401 right = self.parse_and()
402 left = nodes.Or(left, right, lineno=lineno)
403 lineno = self.stream.current.lineno
404 return left
405
406 def parse_and(self):
407 lineno = self.stream.current.lineno
Armin Ronacherd89f0f32009-02-04 18:57:27 +0100408 left = self.parse_not()
Armin Ronacherfdf95302008-05-11 22:20:51 +0200409 while self.stream.skip_if('name:and'):
Armin Ronacherd89f0f32009-02-04 18:57:27 +0100410 right = self.parse_not()
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200411 left = nodes.And(left, right, lineno=lineno)
412 lineno = self.stream.current.lineno
413 return left
414
Armin Ronacherd89f0f32009-02-04 18:57:27 +0100415 def parse_not(self):
416 if self.stream.current.test('name:not'):
Armin Ronacherbd357722009-08-05 20:25:06 +0200417 lineno = next(self.stream).lineno
Armin Ronacherd89f0f32009-02-04 18:57:27 +0100418 return nodes.Not(self.parse_not(), lineno=lineno)
419 return self.parse_compare()
420
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200421 def parse_compare(self):
422 lineno = self.stream.current.lineno
423 expr = self.parse_add()
424 ops = []
425 while 1:
426 token_type = self.stream.current.type
427 if token_type in _compare_operators:
Armin Ronacherbd357722009-08-05 20:25:06 +0200428 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200429 ops.append(nodes.Operand(token_type, self.parse_add()))
Armin Ronacherfdf95302008-05-11 22:20:51 +0200430 elif self.stream.skip_if('name:in'):
Armin Ronacher115de2e2008-05-01 22:20:05 +0200431 ops.append(nodes.Operand('in', self.parse_add()))
432 elif self.stream.current.test('name:not') and \
433 self.stream.look().test('name:in'):
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200434 self.stream.skip(2)
435 ops.append(nodes.Operand('notin', self.parse_add()))
436 else:
437 break
438 lineno = self.stream.current.lineno
439 if not ops:
440 return expr
441 return nodes.Compare(expr, ops, lineno=lineno)
442
443 def parse_add(self):
444 lineno = self.stream.current.lineno
445 left = self.parse_sub()
Ali Afshar272ca2a2009-01-05 12:14:14 +0100446 while self.stream.current.type == 'add':
Armin Ronacherbd357722009-08-05 20:25:06 +0200447 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200448 right = self.parse_sub()
449 left = nodes.Add(left, right, lineno=lineno)
450 lineno = self.stream.current.lineno
451 return left
452
453 def parse_sub(self):
454 lineno = self.stream.current.lineno
455 left = self.parse_concat()
Ali Afshar272ca2a2009-01-05 12:14:14 +0100456 while self.stream.current.type == 'sub':
Armin Ronacherbd357722009-08-05 20:25:06 +0200457 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200458 right = self.parse_concat()
459 left = nodes.Sub(left, right, lineno=lineno)
460 lineno = self.stream.current.lineno
461 return left
462
463 def parse_concat(self):
464 lineno = self.stream.current.lineno
465 args = [self.parse_mul()]
Ali Afshar272ca2a2009-01-05 12:14:14 +0100466 while self.stream.current.type == 'tilde':
Armin Ronacherbd357722009-08-05 20:25:06 +0200467 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200468 args.append(self.parse_mul())
469 if len(args) == 1:
470 return args[0]
471 return nodes.Concat(args, lineno=lineno)
472
473 def parse_mul(self):
474 lineno = self.stream.current.lineno
475 left = self.parse_div()
Ali Afshar272ca2a2009-01-05 12:14:14 +0100476 while self.stream.current.type == 'mul':
Armin Ronacherbd357722009-08-05 20:25:06 +0200477 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200478 right = self.parse_div()
479 left = nodes.Mul(left, right, lineno=lineno)
480 lineno = self.stream.current.lineno
481 return left
482
483 def parse_div(self):
484 lineno = self.stream.current.lineno
485 left = self.parse_floordiv()
Ali Afshar272ca2a2009-01-05 12:14:14 +0100486 while self.stream.current.type == 'div':
Armin Ronacherbd357722009-08-05 20:25:06 +0200487 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200488 right = self.parse_floordiv()
Armin Ronachere791c2a2008-04-07 18:39:54 +0200489 left = nodes.Div(left, right, lineno=lineno)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200490 lineno = self.stream.current.lineno
491 return left
492
493 def parse_floordiv(self):
494 lineno = self.stream.current.lineno
495 left = self.parse_mod()
Ali Afshar272ca2a2009-01-05 12:14:14 +0100496 while self.stream.current.type == 'floordiv':
Armin Ronacherbd357722009-08-05 20:25:06 +0200497 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200498 right = self.parse_mod()
499 left = nodes.FloorDiv(left, right, lineno=lineno)
500 lineno = self.stream.current.lineno
501 return left
502
503 def parse_mod(self):
504 lineno = self.stream.current.lineno
505 left = self.parse_pow()
Ali Afshar272ca2a2009-01-05 12:14:14 +0100506 while self.stream.current.type == 'mod':
Armin Ronacherbd357722009-08-05 20:25:06 +0200507 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200508 right = self.parse_pow()
509 left = nodes.Mod(left, right, lineno=lineno)
510 lineno = self.stream.current.lineno
511 return left
512
513 def parse_pow(self):
514 lineno = self.stream.current.lineno
515 left = self.parse_unary()
Ali Afshar272ca2a2009-01-05 12:14:14 +0100516 while self.stream.current.type == 'pow':
Armin Ronacherbd357722009-08-05 20:25:06 +0200517 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200518 right = self.parse_unary()
519 left = nodes.Pow(left, right, lineno=lineno)
520 lineno = self.stream.current.lineno
521 return left
522
523 def parse_unary(self):
524 token_type = self.stream.current.type
525 lineno = self.stream.current.lineno
Ali Afshar272ca2a2009-01-05 12:14:14 +0100526 if token_type == 'sub':
Armin Ronacherbd357722009-08-05 20:25:06 +0200527 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200528 node = self.parse_unary()
Armin Ronachere791c2a2008-04-07 18:39:54 +0200529 return nodes.Neg(node, lineno=lineno)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100530 if token_type == 'add':
Armin Ronacherbd357722009-08-05 20:25:06 +0200531 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200532 node = self.parse_unary()
533 return nodes.Pos(node, lineno=lineno)
534 return self.parse_primary()
535
Armin Ronacher09c002e2008-05-10 22:21:30 +0200536 def parse_primary(self, with_postfix=True):
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200537 token = self.stream.current
Ali Afshar272ca2a2009-01-05 12:14:14 +0100538 if token.type == 'name':
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200539 if token.value in ('true', 'false', 'True', 'False'):
540 node = nodes.Const(token.value in ('true', 'True'),
541 lineno=token.lineno)
542 elif token.value in ('none', 'None'):
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200543 node = nodes.Const(None, lineno=token.lineno)
544 else:
545 node = nodes.Name(token.value, 'load', lineno=token.lineno)
Armin Ronacherbd357722009-08-05 20:25:06 +0200546 next(self.stream)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100547 elif token.type == 'string':
Armin Ronacherbd357722009-08-05 20:25:06 +0200548 next(self.stream)
Armin Ronacher4778bda2008-06-22 12:48:37 +0200549 buf = [token.value]
550 lineno = token.lineno
Ali Afshar272ca2a2009-01-05 12:14:14 +0100551 while self.stream.current.type == 'string':
Armin Ronacher4778bda2008-06-22 12:48:37 +0200552 buf.append(self.stream.current.value)
Armin Ronacherbd357722009-08-05 20:25:06 +0200553 next(self.stream)
Armin Ronacher4778bda2008-06-22 12:48:37 +0200554 node = nodes.Const(''.join(buf), lineno=lineno)
555 elif token.type in ('integer', 'float'):
Armin Ronacherbd357722009-08-05 20:25:06 +0200556 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200557 node = nodes.Const(token.value, lineno=token.lineno)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100558 elif token.type == 'lparen':
Armin Ronacherbd357722009-08-05 20:25:06 +0200559 next(self.stream)
Armin Ronachere614e882010-02-06 15:04:46 +0100560 node = self.parse_tuple(explicit_parentheses=True)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200561 self.stream.expect('rparen')
Ali Afshar272ca2a2009-01-05 12:14:14 +0100562 elif token.type == 'lbracket':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200563 node = self.parse_list()
Ali Afshar272ca2a2009-01-05 12:14:14 +0100564 elif token.type == 'lbrace':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200565 node = self.parse_dict()
566 else:
Armin Ronacher5dcb7242010-02-06 14:01:26 +0100567 self.fail("unexpected '%s'" % describe_token(token), token.lineno)
Armin Ronacher09c002e2008-05-10 22:21:30 +0200568 if with_postfix:
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200569 node = self.parse_postfix(node)
570 return node
571
Armin Ronacherfdf95302008-05-11 22:20:51 +0200572 def parse_tuple(self, simplified=False, with_condexpr=True,
Armin Ronachere614e882010-02-06 15:04:46 +0100573 extra_end_rules=None, explicit_parentheses=False):
Armin Ronacher023b5e92008-05-08 11:03:10 +0200574 """Works like `parse_expression` but if multiple expressions are
575 delimited by a comma a :class:`~jinja2.nodes.Tuple` node is created.
576 This method could also return a regular expression instead of a tuple
577 if no commas where found.
578
579 The default parsing mode is a full tuple. If `simplified` is `True`
580 only names and literals are parsed. The `no_condexpr` parameter is
581 forwarded to :meth:`parse_expression`.
Armin Ronacherfdf95302008-05-11 22:20:51 +0200582
583 Because tuples do not require delimiters and may end in a bogus comma
584 an extra hint is needed that marks the end of a tuple. For example
585 for loops support tuples between `for` and `in`. In that case the
586 `extra_end_rules` is set to ``['name:in']``.
Armin Ronachere614e882010-02-06 15:04:46 +0100587
588 `explicit_parentheses` is true if the parsing was triggered by an
589 expression in parentheses. This is used to figure out if an empty
590 tuple is a valid expression or not.
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200591 """
592 lineno = self.stream.current.lineno
Armin Ronacher3d8b7842008-04-13 13:16:50 +0200593 if simplified:
Armin Ronacher09c002e2008-05-10 22:21:30 +0200594 parse = lambda: self.parse_primary(with_postfix=False)
595 elif with_condexpr:
Armin Ronacher3d8b7842008-04-13 13:16:50 +0200596 parse = self.parse_expression
Armin Ronacher09c002e2008-05-10 22:21:30 +0200597 else:
598 parse = lambda: self.parse_expression(with_condexpr=False)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200599 args = []
600 is_tuple = False
601 while 1:
602 if args:
603 self.stream.expect('comma')
Armin Ronacherfdf95302008-05-11 22:20:51 +0200604 if self.is_tuple_end(extra_end_rules):
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200605 break
606 args.append(parse())
Ali Afshar272ca2a2009-01-05 12:14:14 +0100607 if self.stream.current.type == 'comma':
Armin Ronacherb5124e62008-04-25 00:36:14 +0200608 is_tuple = True
609 else:
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200610 break
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200611 lineno = self.stream.current.lineno
Armin Ronachere614e882010-02-06 15:04:46 +0100612
613 if not is_tuple:
614 if args:
615 return args[0]
616
617 # if we don't have explicit parentheses, an empty tuple is
618 # not a valid expression. This would mean nothing (literally
619 # nothing) in the spot of an expression would be an empty
620 # tuple.
621 if not explicit_parentheses:
622 self.fail('Expected an expression, got \'%s\'' %
623 describe_token(self.stream.current))
624
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200625 return nodes.Tuple(args, 'load', lineno=lineno)
626
627 def parse_list(self):
628 token = self.stream.expect('lbracket')
629 items = []
Ali Afshar272ca2a2009-01-05 12:14:14 +0100630 while self.stream.current.type != 'rbracket':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200631 if items:
632 self.stream.expect('comma')
633 if self.stream.current.type == 'rbracket':
634 break
635 items.append(self.parse_expression())
636 self.stream.expect('rbracket')
637 return nodes.List(items, lineno=token.lineno)
638
639 def parse_dict(self):
640 token = self.stream.expect('lbrace')
641 items = []
Ali Afshar272ca2a2009-01-05 12:14:14 +0100642 while self.stream.current.type != 'rbrace':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200643 if items:
644 self.stream.expect('comma')
645 if self.stream.current.type == 'rbrace':
646 break
647 key = self.parse_expression()
648 self.stream.expect('colon')
649 value = self.parse_expression()
650 items.append(nodes.Pair(key, value, lineno=key.lineno))
651 self.stream.expect('rbrace')
Armin Ronacherbe4ae242008-04-18 09:49:08 +0200652 return nodes.Dict(items, lineno=token.lineno)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200653
654 def parse_postfix(self, node):
655 while 1:
656 token_type = self.stream.current.type
Ali Afshar272ca2a2009-01-05 12:14:14 +0100657 if token_type == 'dot' or token_type == 'lbracket':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200658 node = self.parse_subscript(node)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100659 elif token_type == 'lparen':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200660 node = self.parse_call(node)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100661 elif token_type == 'pipe':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200662 node = self.parse_filter(node)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100663 elif token_type == 'name' and self.stream.current.value == 'is':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200664 node = self.parse_test(node)
665 else:
666 break
667 return node
668
669 def parse_subscript(self, node):
Armin Ronacherbd357722009-08-05 20:25:06 +0200670 token = next(self.stream)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100671 if token.type == 'dot':
Armin Ronachere791c2a2008-04-07 18:39:54 +0200672 attr_token = self.stream.current
Armin Ronacherbd357722009-08-05 20:25:06 +0200673 next(self.stream)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100674 if attr_token.type == 'name':
Armin Ronacher6dc6f292008-06-12 08:50:07 +0200675 return nodes.Getattr(node, attr_token.value, 'load',
676 lineno=token.lineno)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100677 elif attr_token.type != 'integer':
Armin Ronacher7f15ef82008-05-16 09:11:39 +0200678 self.fail('expected name or number', attr_token.lineno)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200679 arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
Armin Ronacher6dc6f292008-06-12 08:50:07 +0200680 return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100681 if token.type == 'lbracket':
Armin Ronacher6dc6f292008-06-12 08:50:07 +0200682 priority_on_attribute = False
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200683 args = []
Ali Afshar272ca2a2009-01-05 12:14:14 +0100684 while self.stream.current.type != 'rbracket':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200685 if args:
686 self.stream.expect('comma')
687 args.append(self.parse_subscribed())
688 self.stream.expect('rbracket')
689 if len(args) == 1:
690 arg = args[0]
691 else:
Armin Ronacheree2d3c42009-02-05 23:13:15 +0100692 arg = nodes.Tuple(args, 'load', lineno=token.lineno)
Armin Ronacher6dc6f292008-06-12 08:50:07 +0200693 return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
694 self.fail('expected subscript expression', self.lineno)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200695
696 def parse_subscribed(self):
697 lineno = self.stream.current.lineno
698
Ali Afshar272ca2a2009-01-05 12:14:14 +0100699 if self.stream.current.type == 'colon':
Armin Ronacherbd357722009-08-05 20:25:06 +0200700 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200701 args = [None]
702 else:
703 node = self.parse_expression()
Ali Afshar272ca2a2009-01-05 12:14:14 +0100704 if self.stream.current.type != 'colon':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200705 return node
Armin Ronacherbd357722009-08-05 20:25:06 +0200706 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200707 args = [node]
708
Ali Afshar272ca2a2009-01-05 12:14:14 +0100709 if self.stream.current.type == 'colon':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200710 args.append(None)
711 elif self.stream.current.type not in ('rbracket', 'comma'):
712 args.append(self.parse_expression())
713 else:
714 args.append(None)
715
Ali Afshar272ca2a2009-01-05 12:14:14 +0100716 if self.stream.current.type == 'colon':
Armin Ronacherbd357722009-08-05 20:25:06 +0200717 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200718 if self.stream.current.type not in ('rbracket', 'comma'):
719 args.append(self.parse_expression())
720 else:
721 args.append(None)
722 else:
723 args.append(None)
724
725 return nodes.Slice(lineno=lineno, *args)
726
727 def parse_call(self, node):
728 token = self.stream.expect('lparen')
729 args = []
730 kwargs = []
731 dyn_args = dyn_kwargs = None
732 require_comma = False
733
734 def ensure(expr):
735 if not expr:
Armin Ronacher7f15ef82008-05-16 09:11:39 +0200736 self.fail('invalid syntax for function call expression',
737 token.lineno)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200738
Ali Afshar272ca2a2009-01-05 12:14:14 +0100739 while self.stream.current.type != 'rparen':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200740 if require_comma:
741 self.stream.expect('comma')
742 # support for trailing comma
Ali Afshar272ca2a2009-01-05 12:14:14 +0100743 if self.stream.current.type == 'rparen':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200744 break
Ali Afshar272ca2a2009-01-05 12:14:14 +0100745 if self.stream.current.type == 'mul':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200746 ensure(dyn_args is None and dyn_kwargs is None)
Armin Ronacherbd357722009-08-05 20:25:06 +0200747 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200748 dyn_args = self.parse_expression()
Ali Afshar272ca2a2009-01-05 12:14:14 +0100749 elif self.stream.current.type == 'pow':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200750 ensure(dyn_kwargs is None)
Armin Ronacherbd357722009-08-05 20:25:06 +0200751 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200752 dyn_kwargs = self.parse_expression()
753 else:
754 ensure(dyn_args is None and dyn_kwargs is None)
Ali Afshar272ca2a2009-01-05 12:14:14 +0100755 if self.stream.current.type == 'name' and \
756 self.stream.look().type == 'assign':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200757 key = self.stream.current.value
758 self.stream.skip(2)
Armin Ronacher0611e492008-04-25 23:44:14 +0200759 value = self.parse_expression()
760 kwargs.append(nodes.Keyword(key, value,
761 lineno=value.lineno))
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200762 else:
763 ensure(not kwargs)
764 args.append(self.parse_expression())
765
766 require_comma = True
767 self.stream.expect('rparen')
768
769 if node is None:
770 return args, kwargs, dyn_args, dyn_kwargs
771 return nodes.Call(node, args, kwargs, dyn_args, dyn_kwargs,
772 lineno=token.lineno)
773
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200774 def parse_filter(self, node, start_inline=False):
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200775 while self.stream.current.type == 'pipe' or start_inline:
776 if not start_inline:
Armin Ronacherbd357722009-08-05 20:25:06 +0200777 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200778 token = self.stream.expect('name')
Armin Ronacherb9e78752008-05-10 23:36:28 +0200779 name = token.value
Ali Afshar272ca2a2009-01-05 12:14:14 +0100780 while self.stream.current.type == 'dot':
Armin Ronacherbd357722009-08-05 20:25:06 +0200781 next(self.stream)
Armin Ronacherb9e78752008-05-10 23:36:28 +0200782 name += '.' + self.stream.expect('name').value
Ali Afshar272ca2a2009-01-05 12:14:14 +0100783 if self.stream.current.type == 'lparen':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200784 args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
785 else:
786 args = []
787 kwargs = []
788 dyn_args = dyn_kwargs = None
Armin Ronacherb9e78752008-05-10 23:36:28 +0200789 node = nodes.Filter(node, name, args, kwargs, dyn_args,
Armin Ronacherd55ab532008-04-09 16:13:39 +0200790 dyn_kwargs, lineno=token.lineno)
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200791 start_inline = False
Armin Ronacherd55ab532008-04-09 16:13:39 +0200792 return node
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200793
794 def parse_test(self, node):
Armin Ronacherbd357722009-08-05 20:25:06 +0200795 token = next(self.stream)
Armin Ronacher115de2e2008-05-01 22:20:05 +0200796 if self.stream.current.test('name:not'):
Armin Ronacherbd357722009-08-05 20:25:06 +0200797 next(self.stream)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200798 negated = True
799 else:
800 negated = False
801 name = self.stream.expect('name').value
Ali Afshar272ca2a2009-01-05 12:14:14 +0100802 while self.stream.current.type == 'dot':
Armin Ronacherbd357722009-08-05 20:25:06 +0200803 next(self.stream)
Armin Ronacherb9e78752008-05-10 23:36:28 +0200804 name += '.' + self.stream.expect('name').value
Armin Ronacher10f3ba22008-04-18 11:30:37 +0200805 dyn_args = dyn_kwargs = None
806 kwargs = []
Ali Afshar272ca2a2009-01-05 12:14:14 +0100807 if self.stream.current.type == 'lparen':
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200808 args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
809 elif self.stream.current.type in ('name', 'string', 'integer',
810 'float', 'lparen', 'lbracket',
Armin Ronachere3290ea2008-06-12 10:30:01 +0200811 'lbrace') and not \
812 self.stream.current.test_any('name:else', 'name:or',
813 'name:and'):
814 if self.stream.current.test('name:is'):
815 self.fail('You cannot chain multiple tests with is')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200816 args = [self.parse_expression()]
817 else:
818 args = []
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200819 node = nodes.Test(node, name, args, kwargs, dyn_args,
820 dyn_kwargs, lineno=token.lineno)
821 if negated:
Armin Ronacher9a822052008-04-17 18:44:07 +0200822 node = nodes.Not(node, lineno=token.lineno)
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200823 return node
824
825 def subparse(self, end_tokens=None):
826 body = []
827 data_buffer = []
828 add_data = data_buffer.append
829
Armin Ronacher5dcb7242010-02-06 14:01:26 +0100830 if end_tokens is not None:
831 self._end_token_stack.append(end_tokens)
832
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200833 def flush_data():
834 if data_buffer:
835 lineno = data_buffer[0].lineno
836 body.append(nodes.Output(data_buffer[:], lineno=lineno))
837 del data_buffer[:]
838
Armin Ronacher5dcb7242010-02-06 14:01:26 +0100839 try:
840 while self.stream:
841 token = self.stream.current
842 if token.type == 'data':
843 if token.value:
844 add_data(nodes.TemplateData(token.value,
845 lineno=token.lineno))
846 next(self.stream)
847 elif token.type == 'variable_begin':
848 next(self.stream)
849 add_data(self.parse_tuple(with_condexpr=True))
850 self.stream.expect('variable_end')
851 elif token.type == 'block_begin':
852 flush_data()
853 next(self.stream)
854 if end_tokens is not None and \
855 self.stream.current.test_any(*end_tokens):
856 return body
857 rv = self.parse_statement()
858 if isinstance(rv, list):
859 body.extend(rv)
860 else:
861 body.append(rv)
862 self.stream.expect('block_end')
Armin Ronacher023b5e92008-05-08 11:03:10 +0200863 else:
Armin Ronacher5dcb7242010-02-06 14:01:26 +0100864 raise AssertionError('internal parsing error')
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200865
Armin Ronacher5dcb7242010-02-06 14:01:26 +0100866 flush_data()
867 finally:
868 if end_tokens is not None:
869 self._end_token_stack.pop()
870
Armin Ronacher82b3f3d2008-03-31 20:01:08 +0200871 return body
872
873 def parse(self):
874 """Parse the whole template into a `Template` node."""
Armin Ronacherd55ab532008-04-09 16:13:39 +0200875 result = nodes.Template(self.subparse(), lineno=1)
876 result.set_environment(self.environment)
877 return result