| @@ -176,7 +176,12 @@ class EBNF_to_BNF(Transformer_InPlace): | |||||
| def expr(self, rule, op, *args): | def expr(self, rule, op, *args): | ||||
| if op.value == '?': | if op.value == '?': | ||||
| return ST('expansions', [rule, _EMPTY]) | |||||
| if isinstance(rule, Terminal) and rule.filter_out and not ( | |||||
| self.rule_options and self.rule_options.keep_all_tokens): | |||||
| empty = ST('expansion', []) | |||||
| else: | |||||
| empty = _EMPTY | |||||
| return ST('expansions', [rule, empty]) | |||||
| elif op.value == '+': | elif op.value == '+': | ||||
| # a : b c+ d | # a : b c+ d | ||||
| # --> | # --> | ||||
| @@ -151,7 +151,7 @@ class ParseTreeBuilder: | |||||
| wrapper_chain = filter(None, [ | wrapper_chain = filter(None, [ | ||||
| (expand_single_child and not rule.alias) and ExpandSingleChild, | (expand_single_child and not rule.alias) and ExpandSingleChild, | ||||
| maybe_create_child_filter(rule.expansion, keep_all_tokens, self.ambiguous), | maybe_create_child_filter(rule.expansion, keep_all_tokens, self.ambiguous), | ||||
| self.maybe_placeholders and partial(AddMaybePlaceholder, options.empty_indices), | |||||
| self.maybe_placeholders and partial(AddMaybePlaceholder, options.empty_indices if options else None), | |||||
| self.propagate_positions and PropagatePositions, | self.propagate_positions and PropagatePositions, | ||||
| ]) | ]) | ||||
| @@ -1249,6 +1249,16 @@ def _make_parser_test(LEXER, PARSER): | |||||
| self.assertEqual(len(res.children), 3) | self.assertEqual(len(res.children), 3) | ||||
| def test_maybe_placeholders(self): | def test_maybe_placeholders(self): | ||||
| # Anonymous tokens shouldn't count | |||||
| p = Lark("""start: "a"? "b"? "c"? """, maybe_placeholders=True) | |||||
| self.assertEqual(p.parse("").children, []) | |||||
| # Anonymous tokens shouldn't count, other constructs should | |||||
| p = Lark("""start: A? "b"? _c? | |||||
| A: "a" | |||||
| _c: "c" """, maybe_placeholders=True) | |||||
| self.assertEqual(p.parse("").children, [None, None]) | |||||
| p = Lark("""!start: "a"? "b"? "c"? """, maybe_placeholders=True) | p = Lark("""!start: "a"? "b"? "c"? """, maybe_placeholders=True) | ||||
| self.assertEqual(p.parse("").children, [None, None, None]) | self.assertEqual(p.parse("").children, [None, None, None]) | ||||
| self.assertEqual(p.parse("a").children, ['a', None, None]) | self.assertEqual(p.parse("a").children, ['a', None, None]) | ||||