This package offers both a portable {py3} module and a command-line
tool.
-WARNING: This version of Normand is 0.13, meaning both the Normand
+WARNING: This version of Normand is 0.14, meaning both the Normand
language and the module/CLI interface aren't stable.
ifdef::env-github[]
!if {ICITTE > 10}
"bar"
+ !else
+ "fight"
!end
) * 4
----
Output:
+
----
-aa bb cc 66 6f 6f 66 6f 6f 66 6f 6f 62 61 72 66 ┆ •••foofoofoobarf
-6f 6f 62 61 72 ┆ oobar
+aa bb cc 66 6f 6f 66 69 67 68 74 66 6f 6f 66 69 ┆ •••foofightfoofi
+67 68 74 66 6f 6f 62 61 72 66 6f 6f 62 61 72 ┆ ghtfoobarfoobar
----
Repetition::
=== Conditional block
-A _conditional block_ represents either the bytes of one or more items
-if some expression is true, or no bytes at all if it's false.
+A _conditional block_ represents either the bytes of zero or more items
+if some expression is true, or the bytes of zero or more other items if
+it's false.
A conditional block is:
For the name `__NAME__`, this is equivalent to the
`pass:[{]__NAME__pass:[}]` form above.
-. Zero or more items.
+. Zero or more items to be handled when the condition is true.
+
+. **Optional**:
+
+.. The `!else` opening.
+.. Zero or more items to be handled when the condition is false.
. The `!end` closing.
!if {ICITTE > 25}
"mix"
-
- !if {at < rep_count} 20 !end
+ !else
+ "zoom"
!end
+ !if {at < rep_count} 20 !end
+
{at = at + 1}
!end
----
Output:
----
-6d 65 6f 77 20 6d 65 6f 77 20 6d 65 6f 77 20 6d ┆ meow meow meow m
-65 6f 77 20 6d 65 6f 77 20 6d 65 6f 77 20 6d 69 ┆ eow meow meow mi
+6d 65 6f 77 20 7a 6f 6f 6d 20 6d 65 6f 77 20 7a ┆ meow zoom meow z
+6f 6f 6d 20 6d 65 6f 77 20 7a 6f 6f 6d 20 6d 65 ┆ oom meow zoom me
+6f 77 20 6d 69 78 20 6d 65 6f 77 20 6d 69 78 20 ┆ ow mix meow mix
+6d 65 6f 77 20 6d 69 78 20 6d 65 6f 77 20 6d 69 ┆ meow mix meow mi
78 20 6d 65 6f 77 20 6d 69 78 20 6d 65 6f 77 20 ┆ x meow mix meow
-6d 69 78 20 6d 65 6f 77 20 6d 69 78 ┆ mix meow mix
+6d 69 78 ┆ mix
----
====
# Upstream repository: <https://github.com/efficios/normand>.
__author__ = "Philippe Proulx"
-__version__ = "0.13.0"
+__version__ = "0.14.0"
__all__ = [
"__author__",
"__version__",
# Conditional item.
class _Cond(_Item, _ExprMixin):
def __init__(
- self, item: _Item, expr_str: str, expr: ast.Expression, text_loc: TextLocation
+ self,
+ true_item: _Item,
+ false_item: _Item,
+ expr_str: str,
+ expr: ast.Expression,
+ text_loc: TextLocation,
):
super().__init__(text_loc)
_ExprMixin.__init__(self, expr_str, expr)
- self._item = item
+ self._true_item = true_item
+ self._false_item = false_item
- # Conditional item.
+ # Item when condition is true.
@property
- def item(self):
- return self._item
+ def true_item(self):
+ return self._true_item
+
+ # Item when condition is false.
+ @property
+ def false_item(self):
+ return self._false_item
def __repr__(self):
- return "_Cond({}, {}, {}, {})".format(
- repr(self._item),
+ return "_Cond({}, {}, {}, {}, {})".format(
+ repr(self._true_item),
+ repr(self._false_item),
repr(self._expr_str),
repr(self._expr),
repr(self._text_loc),
# Pattern for _try_parse_cond_block()
_cond_block_prefix_pat = re.compile(r"!if\b")
+ _cond_block_else_pat = re.compile(r"!else\b")
# Tries to parse a conditional block, returning a conditional item
# on success.
self._skip_ws_and_comments()
expr_str, expr = self._expect_const_int_name_expr(False)
- # Parse items
+ # Parse "true" items
self._skip_ws_and_comments()
- items_text_loc = self._text_loc
- items = self._parse_items()
+ true_items_text_loc = self._text_loc
+ true_items = self._parse_items()
+ false_items = [] # type: List[_Item]
+ false_items_text_loc = begin_text_loc
- # Expect end of block
+ # `!else`?
self._skip_ws_and_comments()
+
+ if self._try_parse_pat(self._cond_block_else_pat) is not None:
+ # Parse "false" items
+ self._skip_ws_and_comments()
+ false_items_text_loc = self._text_loc
+ false_items = self._parse_items()
+
+ # Expect end of block
self._expect_pat(
self._block_end_pat,
- "Expecting an item or `!end` (end of conditional block)",
+ "Expecting an item, `!else`, or `!end` (end of conditional block)",
)
# Return item
- return _Cond(_Group(items, items_text_loc), expr_str, expr, begin_text_loc)
+ return _Cond(
+ _Group(true_items, true_items_text_loc),
+ _Group(false_items, false_items_text_loc),
+ expr_str,
+ expr,
+ begin_text_loc,
+ )
# Common left parenthesis pattern
_left_paren_pat = re.compile(r"\(")
self._handle_item(item.item, state)
# Handles the conditional item `item`.
- def _handle_cond_item(self, item: _Rep, state: _GenState):
+ def _handle_cond_item(self, item: _Cond, state: _GenState):
# Compute the conditional value
val = _Gen._eval_item_expr(item, state)
# Generate item data if needed
if val:
- self._handle_item(item.item, state)
+ self._handle_item(item.true_item, state)
+ else:
+ self._handle_item(item.false_item, state)
# Evaluates the parameters of the macro expansion item `item`
# considering the initial state `init_state` and returns a new state