parser.py 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  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. ...
  414. @typing.overload
  415. def parse_assign_target(
  416. self,
  417. with_tuple: bool = True,
  418. name_only: bool = False,
  419. extra_end_rules: t.Optional[t.Tuple[str, ...]] = None,
  420. with_namespace: bool = False,
  421. ) -> t.Union[nodes.NSRef, nodes.Name, nodes.Tuple]:
  422. ...
  423. def parse_assign_target(
  424. self,
  425. with_tuple: bool = True,
  426. name_only: bool = False,
  427. extra_end_rules: t.Optional[t.Tuple[str, ...]] = None,
  428. with_namespace: bool = False,
  429. ) -> t.Union[nodes.NSRef, nodes.Name, nodes.Tuple]:
  430. """Parse an assignment target. As Jinja allows assignments to
  431. tuples, this function can parse all allowed assignment targets. Per
  432. default assignments to tuples are parsed, that can be disable however
  433. by setting `with_tuple` to `False`. If only assignments to names are
  434. wanted `name_only` can be set to `True`. The `extra_end_rules`
  435. parameter is forwarded to the tuple parsing function. If
  436. `with_namespace` is enabled, a namespace assignment may be parsed.
  437. """
  438. target: nodes.Expr
  439. if with_namespace and self.stream.look().type == "dot":
  440. token = self.stream.expect("name")
  441. next(self.stream) # dot
  442. attr = self.stream.expect("name")
  443. target = nodes.NSRef(token.value, attr.value, lineno=token.lineno)
  444. elif name_only:
  445. token = self.stream.expect("name")
  446. target = nodes.Name(token.value, "store", lineno=token.lineno)
  447. else:
  448. if with_tuple:
  449. target = self.parse_tuple(
  450. simplified=True, extra_end_rules=extra_end_rules
  451. )
  452. else:
  453. target = self.parse_primary()
  454. target.set_ctx("store")
  455. if not target.can_assign():
  456. self.fail(
  457. f"can't assign to {type(target).__name__.lower()!r}", target.lineno
  458. )
  459. return target # type: ignore
  460. def parse_expression(self, with_condexpr: bool = True) -> nodes.Expr:
  461. """Parse an expression. Per default all expressions are parsed, if
  462. the optional `with_condexpr` parameter is set to `False` conditional
  463. expressions are not parsed.
  464. """
  465. if with_condexpr:
  466. return self.parse_condexpr()
  467. return self.parse_or()
  468. def parse_condexpr(self) -> nodes.Expr:
  469. lineno = self.stream.current.lineno
  470. expr1 = self.parse_or()
  471. expr3: t.Optional[nodes.Expr]
  472. while self.stream.skip_if("name:if"):
  473. expr2 = self.parse_or()
  474. if self.stream.skip_if("name:else"):
  475. expr3 = self.parse_condexpr()
  476. else:
  477. expr3 = None
  478. expr1 = nodes.CondExpr(expr2, expr1, expr3, lineno=lineno)
  479. lineno = self.stream.current.lineno
  480. return expr1
  481. def parse_or(self) -> nodes.Expr:
  482. lineno = self.stream.current.lineno
  483. left = self.parse_and()
  484. while self.stream.skip_if("name:or"):
  485. right = self.parse_and()
  486. left = nodes.Or(left, right, lineno=lineno)
  487. lineno = self.stream.current.lineno
  488. return left
  489. def parse_and(self) -> nodes.Expr:
  490. lineno = self.stream.current.lineno
  491. left = self.parse_not()
  492. while self.stream.skip_if("name:and"):
  493. right = self.parse_not()
  494. left = nodes.And(left, right, lineno=lineno)
  495. lineno = self.stream.current.lineno
  496. return left
  497. def parse_not(self) -> nodes.Expr:
  498. if self.stream.current.test("name:not"):
  499. lineno = next(self.stream).lineno
  500. return nodes.Not(self.parse_not(), lineno=lineno)
  501. return self.parse_compare()
  502. def parse_compare(self) -> nodes.Expr:
  503. lineno = self.stream.current.lineno
  504. expr = self.parse_math1()
  505. ops = []
  506. while True:
  507. token_type = self.stream.current.type
  508. if token_type in _compare_operators:
  509. next(self.stream)
  510. ops.append(nodes.Operand(token_type, self.parse_math1()))
  511. elif self.stream.skip_if("name:in"):
  512. ops.append(nodes.Operand("in", self.parse_math1()))
  513. elif self.stream.current.test("name:not") and self.stream.look().test(
  514. "name:in"
  515. ):
  516. self.stream.skip(2)
  517. ops.append(nodes.Operand("notin", self.parse_math1()))
  518. else:
  519. break
  520. lineno = self.stream.current.lineno
  521. if not ops:
  522. return expr
  523. return nodes.Compare(expr, ops, lineno=lineno)
  524. def parse_math1(self) -> nodes.Expr:
  525. lineno = self.stream.current.lineno
  526. left = self.parse_concat()
  527. while self.stream.current.type in ("add", "sub"):
  528. cls = _math_nodes[self.stream.current.type]
  529. next(self.stream)
  530. right = self.parse_concat()
  531. left = cls(left, right, lineno=lineno)
  532. lineno = self.stream.current.lineno
  533. return left
  534. def parse_concat(self) -> nodes.Expr:
  535. lineno = self.stream.current.lineno
  536. args = [self.parse_math2()]
  537. while self.stream.current.type == "tilde":
  538. next(self.stream)
  539. args.append(self.parse_math2())
  540. if len(args) == 1:
  541. return args[0]
  542. return nodes.Concat(args, lineno=lineno)
  543. def parse_math2(self) -> nodes.Expr:
  544. lineno = self.stream.current.lineno
  545. left = self.parse_pow()
  546. while self.stream.current.type in ("mul", "div", "floordiv", "mod"):
  547. cls = _math_nodes[self.stream.current.type]
  548. next(self.stream)
  549. right = self.parse_pow()
  550. left = cls(left, right, lineno=lineno)
  551. lineno = self.stream.current.lineno
  552. return left
  553. def parse_pow(self) -> nodes.Expr:
  554. lineno = self.stream.current.lineno
  555. left = self.parse_unary()
  556. while self.stream.current.type == "pow":
  557. next(self.stream)
  558. right = self.parse_unary()
  559. left = nodes.Pow(left, right, lineno=lineno)
  560. lineno = self.stream.current.lineno
  561. return left
  562. def parse_unary(self, with_filter: bool = True) -> nodes.Expr:
  563. token_type = self.stream.current.type
  564. lineno = self.stream.current.lineno
  565. node: nodes.Expr
  566. if token_type == "sub":
  567. next(self.stream)
  568. node = nodes.Neg(self.parse_unary(False), lineno=lineno)
  569. elif token_type == "add":
  570. next(self.stream)
  571. node = nodes.Pos(self.parse_unary(False), lineno=lineno)
  572. else:
  573. node = self.parse_primary()
  574. node = self.parse_postfix(node)
  575. if with_filter:
  576. node = self.parse_filter_expr(node)
  577. return node
  578. def parse_primary(self) -> nodes.Expr:
  579. token = self.stream.current
  580. node: nodes.Expr
  581. if token.type == "name":
  582. if token.value in ("true", "false", "True", "False"):
  583. node = nodes.Const(token.value in ("true", "True"), lineno=token.lineno)
  584. elif token.value in ("none", "None"):
  585. node = nodes.Const(None, lineno=token.lineno)
  586. else:
  587. node = nodes.Name(token.value, "load", lineno=token.lineno)
  588. next(self.stream)
  589. elif token.type == "string":
  590. next(self.stream)
  591. buf = [token.value]
  592. lineno = token.lineno
  593. while self.stream.current.type == "string":
  594. buf.append(self.stream.current.value)
  595. next(self.stream)
  596. node = nodes.Const("".join(buf), lineno=lineno)
  597. elif token.type in ("integer", "float"):
  598. next(self.stream)
  599. node = nodes.Const(token.value, lineno=token.lineno)
  600. elif token.type == "lparen":
  601. next(self.stream)
  602. node = self.parse_tuple(explicit_parentheses=True)
  603. self.stream.expect("rparen")
  604. elif token.type == "lbracket":
  605. node = self.parse_list()
  606. elif token.type == "lbrace":
  607. node = self.parse_dict()
  608. else:
  609. self.fail(f"unexpected {describe_token(token)!r}", token.lineno)
  610. return node
  611. def parse_tuple(
  612. self,
  613. simplified: bool = False,
  614. with_condexpr: bool = True,
  615. extra_end_rules: t.Optional[t.Tuple[str, ...]] = None,
  616. explicit_parentheses: bool = False,
  617. ) -> t.Union[nodes.Tuple, nodes.Expr]:
  618. """Works like `parse_expression` but if multiple expressions are
  619. delimited by a comma a :class:`~jinja2.nodes.Tuple` node is created.
  620. This method could also return a regular expression instead of a tuple
  621. if no commas where found.
  622. The default parsing mode is a full tuple. If `simplified` is `True`
  623. only names and literals are parsed. The `no_condexpr` parameter is
  624. forwarded to :meth:`parse_expression`.
  625. Because tuples do not require delimiters and may end in a bogus comma
  626. an extra hint is needed that marks the end of a tuple. For example
  627. for loops support tuples between `for` and `in`. In that case the
  628. `extra_end_rules` is set to ``['name:in']``.
  629. `explicit_parentheses` is true if the parsing was triggered by an
  630. expression in parentheses. This is used to figure out if an empty
  631. tuple is a valid expression or not.
  632. """
  633. lineno = self.stream.current.lineno
  634. if simplified:
  635. parse = self.parse_primary
  636. elif with_condexpr:
  637. parse = self.parse_expression
  638. else:
  639. def parse() -> nodes.Expr:
  640. return self.parse_expression(with_condexpr=False)
  641. args: t.List[nodes.Expr] = []
  642. is_tuple = False
  643. while True:
  644. if args:
  645. self.stream.expect("comma")
  646. if self.is_tuple_end(extra_end_rules):
  647. break
  648. args.append(parse())
  649. if self.stream.current.type == "comma":
  650. is_tuple = True
  651. else:
  652. break
  653. lineno = self.stream.current.lineno
  654. if not is_tuple:
  655. if args:
  656. return args[0]
  657. # if we don't have explicit parentheses, an empty tuple is
  658. # not a valid expression. This would mean nothing (literally
  659. # nothing) in the spot of an expression would be an empty
  660. # tuple.
  661. if not explicit_parentheses:
  662. self.fail(
  663. "Expected an expression,"
  664. f" got {describe_token(self.stream.current)!r}"
  665. )
  666. return nodes.Tuple(args, "load", lineno=lineno)
  667. def parse_list(self) -> nodes.List:
  668. token = self.stream.expect("lbracket")
  669. items: t.List[nodes.Expr] = []
  670. while self.stream.current.type != "rbracket":
  671. if items:
  672. self.stream.expect("comma")
  673. if self.stream.current.type == "rbracket":
  674. break
  675. items.append(self.parse_expression())
  676. self.stream.expect("rbracket")
  677. return nodes.List(items, lineno=token.lineno)
  678. def parse_dict(self) -> nodes.Dict:
  679. token = self.stream.expect("lbrace")
  680. items: t.List[nodes.Pair] = []
  681. while self.stream.current.type != "rbrace":
  682. if items:
  683. self.stream.expect("comma")
  684. if self.stream.current.type == "rbrace":
  685. break
  686. key = self.parse_expression()
  687. self.stream.expect("colon")
  688. value = self.parse_expression()
  689. items.append(nodes.Pair(key, value, lineno=key.lineno))
  690. self.stream.expect("rbrace")
  691. return nodes.Dict(items, lineno=token.lineno)
  692. def parse_postfix(self, node: nodes.Expr) -> nodes.Expr:
  693. while True:
  694. token_type = self.stream.current.type
  695. if token_type == "dot" or token_type == "lbracket":
  696. node = self.parse_subscript(node)
  697. # calls are valid both after postfix expressions (getattr
  698. # and getitem) as well as filters and tests
  699. elif token_type == "lparen":
  700. node = self.parse_call(node)
  701. else:
  702. break
  703. return node
  704. def parse_filter_expr(self, node: nodes.Expr) -> nodes.Expr:
  705. while True:
  706. token_type = self.stream.current.type
  707. if token_type == "pipe":
  708. node = self.parse_filter(node) # type: ignore
  709. elif token_type == "name" and self.stream.current.value == "is":
  710. node = self.parse_test(node)
  711. # calls are valid both after postfix expressions (getattr
  712. # and getitem) as well as filters and tests
  713. elif token_type == "lparen":
  714. node = self.parse_call(node)
  715. else:
  716. break
  717. return node
  718. def parse_subscript(
  719. self, node: nodes.Expr
  720. ) -> t.Union[nodes.Getattr, nodes.Getitem]:
  721. token = next(self.stream)
  722. arg: nodes.Expr
  723. if token.type == "dot":
  724. attr_token = self.stream.current
  725. next(self.stream)
  726. if attr_token.type == "name":
  727. return nodes.Getattr(
  728. node, attr_token.value, "load", lineno=token.lineno
  729. )
  730. elif attr_token.type != "integer":
  731. self.fail("expected name or number", attr_token.lineno)
  732. arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
  733. return nodes.Getitem(node, arg, "load", lineno=token.lineno)
  734. if token.type == "lbracket":
  735. args: t.List[nodes.Expr] = []
  736. while self.stream.current.type != "rbracket":
  737. if args:
  738. self.stream.expect("comma")
  739. args.append(self.parse_subscribed())
  740. self.stream.expect("rbracket")
  741. if len(args) == 1:
  742. arg = args[0]
  743. else:
  744. arg = nodes.Tuple(args, "load", lineno=token.lineno)
  745. return nodes.Getitem(node, arg, "load", lineno=token.lineno)
  746. self.fail("expected subscript expression", token.lineno)
  747. def parse_subscribed(self) -> nodes.Expr:
  748. lineno = self.stream.current.lineno
  749. args: t.List[t.Optional[nodes.Expr]]
  750. if self.stream.current.type == "colon":
  751. next(self.stream)
  752. args = [None]
  753. else:
  754. node = self.parse_expression()
  755. if self.stream.current.type != "colon":
  756. return node
  757. next(self.stream)
  758. args = [node]
  759. if self.stream.current.type == "colon":
  760. args.append(None)
  761. elif self.stream.current.type not in ("rbracket", "comma"):
  762. args.append(self.parse_expression())
  763. else:
  764. args.append(None)
  765. if self.stream.current.type == "colon":
  766. next(self.stream)
  767. if self.stream.current.type not in ("rbracket", "comma"):
  768. args.append(self.parse_expression())
  769. else:
  770. args.append(None)
  771. else:
  772. args.append(None)
  773. return nodes.Slice(lineno=lineno, *args) # noqa: B026
  774. def parse_call_args(self) -> t.Tuple:
  775. token = self.stream.expect("lparen")
  776. args = []
  777. kwargs = []
  778. dyn_args = None
  779. dyn_kwargs = None
  780. require_comma = False
  781. def ensure(expr: bool) -> None:
  782. if not expr:
  783. self.fail("invalid syntax for function call expression", token.lineno)
  784. while self.stream.current.type != "rparen":
  785. if require_comma:
  786. self.stream.expect("comma")
  787. # support for trailing comma
  788. if self.stream.current.type == "rparen":
  789. break
  790. if self.stream.current.type == "mul":
  791. ensure(dyn_args is None and dyn_kwargs is None)
  792. next(self.stream)
  793. dyn_args = self.parse_expression()
  794. elif self.stream.current.type == "pow":
  795. ensure(dyn_kwargs is None)
  796. next(self.stream)
  797. dyn_kwargs = self.parse_expression()
  798. else:
  799. if (
  800. self.stream.current.type == "name"
  801. and self.stream.look().type == "assign"
  802. ):
  803. # Parsing a kwarg
  804. ensure(dyn_kwargs is None)
  805. key = self.stream.current.value
  806. self.stream.skip(2)
  807. value = self.parse_expression()
  808. kwargs.append(nodes.Keyword(key, value, lineno=value.lineno))
  809. else:
  810. # Parsing an arg
  811. ensure(dyn_args is None and dyn_kwargs is None and not kwargs)
  812. args.append(self.parse_expression())
  813. require_comma = True
  814. self.stream.expect("rparen")
  815. return args, kwargs, dyn_args, dyn_kwargs
  816. def parse_call(self, node: nodes.Expr) -> nodes.Call:
  817. # The lparen will be expected in parse_call_args, but the lineno
  818. # needs to be recorded before the stream is advanced.
  819. token = self.stream.current
  820. args, kwargs, dyn_args, dyn_kwargs = self.parse_call_args()
  821. return nodes.Call(node, args, kwargs, dyn_args, dyn_kwargs, lineno=token.lineno)
  822. def parse_filter(
  823. self, node: t.Optional[nodes.Expr], start_inline: bool = False
  824. ) -> t.Optional[nodes.Expr]:
  825. while self.stream.current.type == "pipe" or start_inline:
  826. if not start_inline:
  827. next(self.stream)
  828. token = self.stream.expect("name")
  829. name = token.value
  830. while self.stream.current.type == "dot":
  831. next(self.stream)
  832. name += "." + self.stream.expect("name").value
  833. if self.stream.current.type == "lparen":
  834. args, kwargs, dyn_args, dyn_kwargs = self.parse_call_args()
  835. else:
  836. args = []
  837. kwargs = []
  838. dyn_args = dyn_kwargs = None
  839. node = nodes.Filter(
  840. node, name, args, kwargs, dyn_args, dyn_kwargs, lineno=token.lineno
  841. )
  842. start_inline = False
  843. return node
  844. def parse_test(self, node: nodes.Expr) -> nodes.Expr:
  845. token = next(self.stream)
  846. if self.stream.current.test("name:not"):
  847. next(self.stream)
  848. negated = True
  849. else:
  850. negated = False
  851. name = self.stream.expect("name").value
  852. while self.stream.current.type == "dot":
  853. next(self.stream)
  854. name += "." + self.stream.expect("name").value
  855. dyn_args = dyn_kwargs = None
  856. kwargs = []
  857. if self.stream.current.type == "lparen":
  858. args, kwargs, dyn_args, dyn_kwargs = self.parse_call_args()
  859. elif self.stream.current.type in {
  860. "name",
  861. "string",
  862. "integer",
  863. "float",
  864. "lparen",
  865. "lbracket",
  866. "lbrace",
  867. } and not self.stream.current.test_any("name:else", "name:or", "name:and"):
  868. if self.stream.current.test("name:is"):
  869. self.fail("You cannot chain multiple tests with is")
  870. arg_node = self.parse_primary()
  871. arg_node = self.parse_postfix(arg_node)
  872. args = [arg_node]
  873. else:
  874. args = []
  875. node = nodes.Test(
  876. node, name, args, kwargs, dyn_args, dyn_kwargs, lineno=token.lineno
  877. )
  878. if negated:
  879. node = nodes.Not(node, lineno=token.lineno)
  880. return node
  881. def subparse(
  882. self, end_tokens: t.Optional[t.Tuple[str, ...]] = None
  883. ) -> t.List[nodes.Node]:
  884. body: t.List[nodes.Node] = []
  885. data_buffer: t.List[nodes.Node] = []
  886. add_data = data_buffer.append
  887. if end_tokens is not None:
  888. self._end_token_stack.append(end_tokens)
  889. def flush_data() -> None:
  890. if data_buffer:
  891. lineno = data_buffer[0].lineno
  892. body.append(nodes.Output(data_buffer[:], lineno=lineno))
  893. del data_buffer[:]
  894. try:
  895. while self.stream:
  896. token = self.stream.current
  897. if token.type == "data":
  898. if token.value:
  899. add_data(nodes.TemplateData(token.value, lineno=token.lineno))
  900. next(self.stream)
  901. elif token.type == "variable_begin":
  902. next(self.stream)
  903. add_data(self.parse_tuple(with_condexpr=True))
  904. self.stream.expect("variable_end")
  905. elif token.type == "block_begin":
  906. flush_data()
  907. next(self.stream)
  908. if end_tokens is not None and self.stream.current.test_any(
  909. *end_tokens
  910. ):
  911. return body
  912. rv = self.parse_statement()
  913. if isinstance(rv, list):
  914. body.extend(rv)
  915. else:
  916. body.append(rv)
  917. self.stream.expect("block_end")
  918. else:
  919. raise AssertionError("internal parsing error")
  920. flush_data()
  921. finally:
  922. if end_tokens is not None:
  923. self._end_token_stack.pop()
  924. return body
  925. def parse(self) -> nodes.Template:
  926. """Parse the whole template into a `Template` node."""
  927. result = nodes.Template(self.subparse(), lineno=1)
  928. result.set_environment(self.environment)
  929. return result