]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Properly handle signed variables
authorKevin Brown <kevin@kevin-brown.com>
Sat, 16 May 2020 19:03:57 +0000 (15:03 -0400)
committerKevin Brown <kevin@kevin-brown.com>
Sat, 16 May 2020 19:03:57 +0000 (15:03 -0400)
Previously we were only handling signed numbers but we were handling
them as constants. Jinja implements a full system for unarary
operators that can be customized, so this switches the grammar and
the parser to use that system instead.

grammar.ebnf
src/jinja2/new_parser.py

index f1dfba287f968dfadb3aaedb631b8688fb2921e2..18496d4af42114a31899f241330df2b4cd4a0ff2 100644 (file)
@@ -219,6 +219,7 @@ variable_identifier_parentheses
 \r
 variable_identifier_raw\r
     =\r
+    [ signed:( "-" | "+" ) ]\r
     variable:( LITERAL | IDENTIFIER )\r
     accessors:{ variable_accessor }*\r
     { {SP}* filters+:variable_filter }*\r
@@ -577,7 +578,7 @@ SIGNED_INTEGER_LITERAL
 NUMBER_LITERAL\r
     =\r
     literal_type:`number`\r
-    whole:SIGNED_INTEGER_LITERAL\r
+    whole:INTEGER_LITERAL\r
     [ "." fractional:INTEGER_LITERAL ]\r
     [ ( "e" | "E" ) exponent:SIGNED_INTEGER_LITERAL ]\r
     ;\r
index 8b6d10fa3aa8f7ff43c04747e2d5e776b273931b..92764a4bc85e26645f5fcb03aa51b7fe0ca85d9a 100644 (file)
@@ -263,6 +263,12 @@ def parse_block_for(ast):
     target = parse_variable(block_parameters[0]['value'], variable_context='store')\r
     iter = parse_variable(block_parameters[2]['value'])\r
 \r
+    if not isinstance(target, (nodes.Name, nodes.Tuple)):\r
+        raise TemplateSyntaxError(\r
+            "expected token 'in'",\r
+            lineno=target.lineno\r
+        )\r
+\r
     if len(block_parameters) > 3:\r
         if block_parameters[3]['value']['variable'] == 'if':\r
             test = parse_conditional_expression(block_parameters[4]['value'])\r
@@ -812,6 +818,16 @@ def parse_variable(ast, variable_context='load'):
     for accessor_ast in ast['accessors']:\r
         node = parse_variable_accessor(node, accessor_ast)\r
 \r
+    signed_node_map = {\r
+        '-': nodes.Neg,\r
+        '+': nodes.Pos,\r
+    }\r
+\r
+    if 'signed' in ast:\r
+        node_class = signed_node_map[ast['signed']]\r
+\r
+        node = node_class(node)\r
+\r
     if ast['filters']:\r
         for filter_ast in ast['filters']:\r
             node = parse_variable_filter(node, filter_ast)\r