parser.py 35 KB

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