parser.py 39 KB

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