parser.py 39 KB

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