Skip to content

Commit

Permalink
integrate fixes for optional whitespace when using #strip_lines
Browse files Browse the repository at this point in the history
  • Loading branch information
msolo committed Jun 9, 2011
1 parent 3e71378 commit abaef3e
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 28 deletions.
9 changes: 5 additions & 4 deletions spitfire/compiler/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -801,9 +801,10 @@ def make_optional(node_list):
pass

# this is another hack to support line-wise stripping of white space nodes
# inside a #strip_lines directive
def strip_whitespace(node_list):
optional = True
# inside a #strip_lines directive.
def strip_whitespace(node_list, starts_new_line=True):
# starts as optional only if we're at the beginning of a new line.
optional = starts_new_line
for i, node in enumerate(node_list):
if isinstance(node, (OptionalWhitespaceNode, NewlineNode)):
optional = True
Expand All @@ -820,7 +821,7 @@ def strip_whitespace(node_list):
optional = False
elif not (node.statement or node.child_nodes or isinstance(node, CommentNode)):
optional = False

if optional and i > 0:
prev_node = node_list[i - 1]
if isinstance(prev_node, TextNode):
Expand Down
18 changes: 9 additions & 9 deletions spitfire/compiler/parser.g
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ parser _SpitfireParser:
'block' SPACE ID CLOSE_DIRECTIVE {{ _block = BlockNode(ID) }}
{{ start = CLOSE_DIRECTIVE.endswith('\n') }}
( block<<start>> {{ _block.append(block) }} ) *
{{ self.make_optional(_block.child_nodes) }}
{{ self.make_optional(_block.child_nodes, start) }}
END_DIRECTIVE SPACE 'block' CLOSE_DIRECTIVE {{ _node_list.append(_block) }}
|
'i18n' {{ _macro = MacroNode('i18n') }}
Expand All @@ -180,14 +180,14 @@ parser _SpitfireParser:
CLOSE_DIRECTIVE
{{ start = CLOSE_DIRECTIVE.endswith('\n') }}
( block<<start>> {{ _def.append(block) }} ) *
{{ self.make_optional(_def.child_nodes) }}
{{ self.make_optional(_def.child_nodes, start) }}
END_DIRECTIVE SPACE 'def' CLOSE_DIRECTIVE {{ _node_list.append(_def) }}
|
'for[ \t]*' target_list '[ \t]*in[ \t]*' expression_list CLOSE_DIRECTIVE
{{ _for_loop = ForNode(target_list, expression_list) }}
{{ start = CLOSE_DIRECTIVE.endswith('\n') }}
( block<<start>> {{ _for_loop.append(block) }} ) *
{{ self.make_optional(_for_loop.child_nodes) }}
{{ self.make_optional(_for_loop.child_nodes, start) }}
END_DIRECTIVE SPACE 'for' CLOSE_DIRECTIVE {{ _node_list.append(_for_loop) }}
|
'strip_lines'
Expand All @@ -198,27 +198,27 @@ parser _SpitfireParser:
{{ _strip_lines_node = StripLinesNode() }}
{{ start = CLOSE_DIRECTIVE.endswith('\n') }}
( block<<start>> {{ _strip_lines_node.append(block) }} ) *
{{ self.make_optional(_strip_lines_node.child_nodes) }}
{{ self.make_optional(_strip_lines_node.child_nodes, start) }}
{{ self.strip_whitespace = False }}
END_DIRECTIVE SPACE 'strip_lines' CLOSE_DIRECTIVE {{ _node_list.append(_strip_lines_node) }}
|
'if' SPACE expression CLOSE_DIRECTIVE {{ _if_node = IfNode(expression) }}
{{ _last_condition_node = _if_node }}
{{ start = CLOSE_DIRECTIVE.endswith('\n') }}
( block<<start>> {{ _if_node.append(block) }} ) *
{{ self.make_optional(_if_node.child_nodes) }}
{{ self.make_optional(_if_node.child_nodes, start) }}
(
'#elif' SPACE expression CLOSE_DIRECTIVE {{ _elif_node = IfNode(expression) }}
{{ _last_condition_node.else_.append(_elif_node) }}
{{ _last_condition_node = _elif_node }}
{{ start = CLOSE_DIRECTIVE.endswith('\n') }}
( block<<start>> {{ _elif_node.append(block) }} ) *
{{ self.make_optional(_elif_node.child_nodes, start) }}
) *
{{ self.make_optional(_last_condition_node.child_nodes) }}
[ '#else' CLOSE_DIRECTIVE
{{ start = CLOSE_DIRECTIVE.endswith('\n') }}
( block<<start>> {{ _last_condition_node.else_.append(block) }} ) *
{{ self.make_optional(_last_condition_node.else_.child_nodes) }}
{{ self.make_optional(_last_condition_node.else_.child_nodes, start) }}
]
END_DIRECTIVE SPACE 'if' CLOSE_DIRECTIVE {{ _node_list.append(_if_node) }}
|
Expand Down Expand Up @@ -570,8 +570,8 @@ parser _SpitfireParser:
class SpitfireParser(_SpitfireParser):
strip_whitespace = False

def make_optional(self, node_list):
def make_optional(self, node_list, starts_new_line=False):
if self.strip_whitespace:
return strip_whitespace(node_list)
return strip_whitespace(node_list, starts_new_line=starts_new_line)
else:
return make_optional(node_list)
20 changes: 10 additions & 10 deletions spitfire/compiler/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ def directive(self):
while self._peek('LITERAL_DOLLAR_SIGN', 'LITERAL_BACKSLASH', 'START_DIRECTIVE', 'SPACE', 'NEWLINE', 'START_PLACEHOLDER', 'END_DIRECTIVE', 'TEXT') != 'END_DIRECTIVE':
block = self.block(start)
_block.append(block)
self.make_optional(_block.child_nodes)
self.make_optional(_block.child_nodes, start)
END_DIRECTIVE = self._scan('END_DIRECTIVE')
SPACE = self._scan('SPACE')
self._scan("'block'")
Expand Down Expand Up @@ -306,7 +306,7 @@ def directive(self):
while self._peek('LITERAL_DOLLAR_SIGN', 'LITERAL_BACKSLASH', 'START_DIRECTIVE', 'SPACE', 'NEWLINE', 'START_PLACEHOLDER', 'END_DIRECTIVE', 'TEXT') != 'END_DIRECTIVE':
block = self.block(start)
_def.append(block)
self.make_optional(_def.child_nodes)
self.make_optional(_def.child_nodes, start)
END_DIRECTIVE = self._scan('END_DIRECTIVE')
SPACE = self._scan('SPACE')
self._scan("'def'")
Expand All @@ -323,7 +323,7 @@ def directive(self):
while self._peek('LITERAL_DOLLAR_SIGN', 'LITERAL_BACKSLASH', 'START_DIRECTIVE', 'SPACE', 'NEWLINE', 'START_PLACEHOLDER', 'END_DIRECTIVE', 'TEXT') != 'END_DIRECTIVE':
block = self.block(start)
_for_loop.append(block)
self.make_optional(_for_loop.child_nodes)
self.make_optional(_for_loop.child_nodes, start)
END_DIRECTIVE = self._scan('END_DIRECTIVE')
SPACE = self._scan('SPACE')
self._scan("'for'")
Expand All @@ -338,7 +338,7 @@ def directive(self):
while self._peek('LITERAL_DOLLAR_SIGN', 'LITERAL_BACKSLASH', 'START_DIRECTIVE', 'SPACE', 'NEWLINE', 'START_PLACEHOLDER', 'TEXT', 'END_DIRECTIVE') != 'END_DIRECTIVE':
block = self.block(start)
_strip_lines_node.append(block)
self.make_optional(_strip_lines_node.child_nodes)
self.make_optional(_strip_lines_node.child_nodes, start)
self.strip_whitespace = False
END_DIRECTIVE = self._scan('END_DIRECTIVE')
SPACE = self._scan('SPACE')
Expand All @@ -356,8 +356,8 @@ def directive(self):
while self._peek('LITERAL_DOLLAR_SIGN', 'LITERAL_BACKSLASH', 'START_DIRECTIVE', 'SPACE', 'NEWLINE', 'START_PLACEHOLDER', "'#elif'", 'TEXT', "'#else'", 'END_DIRECTIVE') not in ["'#elif'", "'#else'", 'END_DIRECTIVE']:
block = self.block(start)
_if_node.append(block)
self.make_optional(_if_node.child_nodes)
while self._peek("'#elif'", 'LITERAL_DOLLAR_SIGN', 'LITERAL_BACKSLASH', 'START_DIRECTIVE', 'SPACE', 'NEWLINE', 'START_PLACEHOLDER', "'#else'", 'TEXT', 'END_DIRECTIVE') == "'#elif'":
self.make_optional(_if_node.child_nodes, start)
while self._peek("'#elif'", "'#else'", 'END_DIRECTIVE') == "'#elif'":
self._scan("'#elif'")
SPACE = self._scan('SPACE')
expression = self.expression()
Expand All @@ -369,15 +369,15 @@ def directive(self):
while self._peek('LITERAL_DOLLAR_SIGN', 'LITERAL_BACKSLASH', 'START_DIRECTIVE', 'SPACE', 'NEWLINE', 'START_PLACEHOLDER', 'TEXT', "'#elif'", "'#else'", 'END_DIRECTIVE') not in ["'#elif'", "'#else'", 'END_DIRECTIVE']:
block = self.block(start)
_elif_node.append(block)
self.make_optional(_last_condition_node.child_nodes)
self.make_optional(_elif_node.child_nodes, start)
if self._peek("'#else'", 'END_DIRECTIVE') == "'#else'":
self._scan("'#else'")
CLOSE_DIRECTIVE = self.CLOSE_DIRECTIVE()
start = CLOSE_DIRECTIVE.endswith('\n')
while self._peek('LITERAL_DOLLAR_SIGN', 'LITERAL_BACKSLASH', 'START_DIRECTIVE', 'SPACE', 'NEWLINE', 'START_PLACEHOLDER', 'TEXT', 'END_DIRECTIVE') != 'END_DIRECTIVE':
block = self.block(start)
_last_condition_node.else_.append(block)
self.make_optional(_last_condition_node.else_.child_nodes)
self.make_optional(_last_condition_node.else_.child_nodes, start)
END_DIRECTIVE = self._scan('END_DIRECTIVE')
SPACE = self._scan('SPACE')
self._scan("'if'")
Expand Down Expand Up @@ -867,8 +867,8 @@ def parse(rule, text):
class SpitfireParser(_SpitfireParser):
strip_whitespace = False

def make_optional(self, node_list):
def make_optional(self, node_list, starts_new_line=False):
if self.strip_whitespace:
return strip_whitespace(node_list)
return strip_whitespace(node_list, starts_new_line=starts_new_line)
else:
return make_optional(node_list)
17 changes: 15 additions & 2 deletions tests/condensed_if.tmpl
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
#strip_lines
<crap>
#set $there = "there"
#if $there
<span> everywhere </span>

#if $there
<span> everywhere </span>
#end if

## Test for a bug where the space after #if $foo# is considered optional.
#if $there# <span> somewhere </span> #end if#

## Test for a bug where the space is preserved only inside the #elif.
#if not $there
<span> will not evaluate </span>
#elif $there.strip()
<span> nowhere </span>
#elif $there
<span> will not evaluate </span>
#end if
$there
#end strip_lines
Expand Down
2 changes: 1 addition & 1 deletion tests/output-preserve-whitespace/condensed_if.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<crap><span> everywhere </span>there
<crap><span> everywhere </span> <span> somewhere </span> <span> nowhere </span>there
2 changes: 1 addition & 1 deletion tests/output/condensed_if.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<crap><span> everywhere </span>there
<crap><span> everywhere </span> <span> somewhere </span> <span> nowhere </span>there
2 changes: 1 addition & 1 deletion tests/output/template_elif_2.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
test if 1
test elif 1 1
test elif 2 1
test elif 2 1
else nothing 0 0

0 comments on commit abaef3e

Please sign in to comment.