You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

903 lines
35 KiB

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