parser.py 34 KB

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