Skip to content

Commit

Permalink
Move custom rules to a custom kwarg.
Browse files Browse the repository at this point in the history
Custom rules are enough of a niche thing that it's not worth making future kwargs so hard to add.
  • Loading branch information
erikrose committed Jul 15, 2014
1 parent 0bbd3c0 commit 40d8bbe
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 12 deletions.
11 changes: 6 additions & 5 deletions parsimonious/grammar.py
Expand Up @@ -44,23 +44,24 @@ class Grammar(StrAndRepr, dict):
increase cache hit ratio. [Is this implemented yet?]
"""
def __init__(self, rules='', default_rule=None, **custom_rules):
def __init__(self, rules='', default_rule=None, custom=None):
"""Construct a grammar.
:arg rules: A string of production rules, one per line.
:arg default_rule: The name of the rule invoked when you call
:meth:`parse()` or :meth:`match()` on the grammar. Defaults to the
first rule. Falls back to None if there are no string-based rules
in this grammar.
:arg custom_rules: Custom-coded rules: Expressions or plain callables
to accomplish things the built-in rule syntax cannot. These take
precedence over ``rules`` in case of naming conflicts.
:arg custom_rules: A map of names to custom-coded rules, Expressions or
plain callables to accomplish things the built-in rule syntax
cannot. These take precedence over ``rules`` in case of naming
conflicts.
"""
decorated_custom_rules = dict(
(k, expression(v, k, self) if isfunction(v) or
ismethod(v) else
v) for k, v in custom_rules.iteritems())
v) for k, v in (custom or {}).iteritems())

exprs, first = self._expressions_from_rules(rules, decorated_custom_rules)

Expand Down
14 changes: 7 additions & 7 deletions parsimonious/tests/test_grammar.py
Expand Up @@ -303,9 +303,9 @@ def test_simple_custom_rules(self):
grammar = Grammar("""
bracketed_digit = start digit end
start = '['
end = ']'""",
end = ']'""", custom=dict(
digit = lambda text, pos:
(pos + 1) if text[pos].isdigit() else None)
(pos + 1) if text[pos].isdigit() else None))
s = '[6]'
eq_(grammar.parse(s),
Node('bracketed_digit', s, 0, 3, children=[
Expand All @@ -323,13 +323,13 @@ def test_complex_custom_rules(self):
bracketed_digit = start digit end
start = '['
end = ']'
real_digit = '6'""",
real_digit = '6'""", custom=dict(
# In this particular implementation of the digit rule, no node is
# generated for `digit`; it falls right through to `real_digit`.
# I'm not sure if this could lead to problems; I can't think of
# any, but it's probably not a great idea.
digit = lambda text, pos, cache, error, grammar:
grammar['real_digit']._match(text, pos, cache, error))
grammar['real_digit']._match(text, pos, cache, error)))
s = '[6]'
eq_(grammar.parse(s),
Node('bracketed_digit', s, 0, 3, children=[
Expand All @@ -347,10 +347,10 @@ def test_lazy_custom_rules(self):
"""
grammar = Grammar("""
four = '4'
five = '5'""",
five = '5'""", custom=dict(
forty_five = Sequence(LazyReference('four'),
LazyReference('five'),
name='forty_five'),
name='forty_five')),
default_rule='forty_five')
s = '45'
eq_(grammar.parse(s),
Expand All @@ -366,7 +366,7 @@ def test_unconnected_custom_rules(self):
Incidentally test Grammar's `rules` default arg.
"""
grammar = Grammar(one_char=lambda text, pos: pos + 1,
grammar = Grammar(custom=dict(one_char=lambda text, pos: pos + 1),
default_rule='one_char')
s = '4'
eq_(grammar.parse(s),
Expand Down

0 comments on commit 40d8bbe

Please sign in to comment.