Skip to content

Commit ce130ca

Browse files
committed
Change the behaviour of Repetition and Integer max constructor arguments
Re: #394. The *max* constructor arguments of the Repetition and Integer class- es are now treated as inclusive, rather than inclusive. This seems more sensible and matches the treatment of the *min* argument. For the Integer class, I have elected not to change the complex int- ernal classes that do the most of the work. They receive the value *max + 1*. This shouldn't matter, but I'm noting it here. The Digits element class is affected by this change, as it is a sub- class of Repetition.
1 parent f6413f4 commit ce130ca

File tree

3 files changed

+27
-11
lines changed

3 files changed

+27
-11
lines changed

dragonfly/grammar/elements_basic.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -570,8 +570,8 @@ class Repetition(Sequence):
570570
be recognized (inclusive); may be 0
571571
- *max* (*int*, default: *None*) --
572572
the maximum number of times that the child element must
573-
be recognized (exclusive!); if *None*, the child element must be
574-
recognized exactly *min* times (i.e. *max = min + 1*)
573+
be recognized (inclusive); if *None*, the child element may be
574+
recognized up to *min + 1* times (i.e. *max = min + 1*)
575575
- *name* (*str*, default: *None*) --
576576
the name of this element
577577
- *default* (*object*, default: *None*) --
@@ -585,11 +585,11 @@ class Repetition(Sequence):
585585
least *min* times and strictly less than *max* times.
586586
587587
Examples:
588-
- *Repetition(child, min=2, max=5)* -- child 2, 3, or 4 times
589-
- *Repetition(child, min=0, max=3)* -- child 0, 1, or 2 times
590-
- *Repetition(child, max=3)* -- child 1 or 2 times
591-
- *Repetition(child, min=1, max=2)* -- child exactly once
592-
- *Repetition(child, min=1)* -- child exactly once
588+
- *Repetition(child, min=2, max=4)* -- child 2, 3, or 4 times
589+
- *Repetition(child, min=0, max=2)* -- child 0, 1, or 2 times
590+
- *Repetition(child, max=2)* -- child 1 or 2 times
591+
- *Repetition(child, min=1, max=1)* -- child exactly once
592+
- *Repetition(child, min=1)* -- child 1 or 2 times
593593
- *Repetition(child)* -- child exactly once
594594
595595
If the *optimize* argument is set to *True*, the engine's compiler may
@@ -610,15 +610,15 @@ def __init__(self, child, min=1, max=None, name=None, default=None,
610610
" ElementBase instance." % self)
611611
assert isinstance(min, six.integer_types)
612612
assert max is None or isinstance(max, six.integer_types)
613-
assert max is None or min < max, "min must be less than max"
613+
assert max is None or min <= max, "min must be less than or equal to max"
614614

615615
self._child = child
616616
self._min = min
617617
if max is None: self._max = min + 1
618618
else: self._max = max
619619
self._optimize = optimize
620620

621-
optional_length = self._max - self._min - 1
621+
optional_length = self._max - self._min
622622
if optional_length > 0:
623623
element = Optional(child)
624624
for index in range(optional_length-1):
@@ -644,8 +644,8 @@ def __init__(self, child, min=1, max=None, name=None, default=None,
644644
max = property(
645645
lambda self: self._max,
646646
doc="The maximum number of times that the child element must be "
647-
"recognized; if *None*, the child element must be "
648-
"recognized exactly *min* times (i.e. *max = min + 1*). "
647+
"recognized; if *None*, the child element may be "
648+
"recognized up to *min + 1* times (i.e. *max = min + 1*). "
649649
"(Read-only)"
650650
)
651651

dragonfly/language/base/integer.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
2525
"""
2626

27+
from six import integer_types
28+
2729
from dragonfly.language.loader import language
2830
from dragonfly.grammar.elements import (Alternative, Sequence, Optional,
2931
Compound, ListRef, RuleWrap)
@@ -60,6 +62,15 @@ def __init__(self, name=None, min=None, max=None, default=None,
6062
self._set_content(language.IntegerContent)
6163
self._builders = self._content.builders
6264

65+
assert isinstance(min, integer_types), "min must be a number"
66+
assert isinstance(max, integer_types), "max must be a number"
67+
assert min <= max, "min must be less than or equal to max"
68+
69+
# Make the *max* argument behave inclusively.
70+
# Note: This is an easier change than modifying the internal integer
71+
# classes.
72+
max = max + 1
73+
6374
self._min = min; self._max = max
6475
children = self._build_children(min, max)
6576
Alternative.__init__(self, children, name=name, default=default)

dragonfly/language/base/integer_internal.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@
3636

3737
#---------------------------------------------------------------------------
3838
# Numeric element builder classes.
39+
#
40+
# Note: The classes in this file treat the *max* argument as exclusive,
41+
# meaning that build_element() methods will return element trees for
42+
# recognizing integers up to max - 1.
43+
3944

4045
class IntBuilderBase(object):
4146

0 commit comments

Comments
 (0)