Repository: erikrose/parsimonious

Issue:
IncompleteParseError
I'm getting an IncompleteParseError creating a Grammar object on a very simple grammar that seems valid to me:

```
IncompleteParseError
Rule 'rules' matched in its entirety, but it didn't consume all the text. The non-matching portion of the text begins with '/ "5"
    ' (line 2, column 21).
```
And the grammar:
```
Grammar(r"""
    value = "[" "]" / "5"
    """
)
```

Discussion:

Patch:
diff --git a/README.rst b/README.rst
index ee2d3f7..4d98805 100644
--- a/README.rst
+++ b/README.rst
@@ -445,7 +445,7 @@ Niceties
 Version History
 ===============
 (Next release)
-  * ...
+  * Fix bug #238: correctly handle `/` expressions with multiple terms in a row. (lucaswiman)
 
 0.10.0
   * Fix infinite recursion in __eq__ in some cases. (FelisNivalis)
diff --git a/parsimonious/grammar.py b/parsimonious/grammar.py
index 367f27e..90c40c0 100644
--- a/parsimonious/grammar.py
+++ b/parsimonious/grammar.py
@@ -197,8 +197,8 @@ class BootstrappingGrammar(Grammar):
         term.members = (not_term,) + term.members
 
         sequence = Sequence(term, OneOrMore(term), name='sequence')
-        or_term = Sequence(Literal('/'), _, term, name='or_term')
-        ored = Sequence(term, OneOrMore(or_term), name='ored')
+        or_term = Sequence(Literal('/'), _, OneOrMore(term), name='or_term')
+        ored = Sequence(OneOrMore(term), OneOrMore(or_term), name='ored')
         expression = OneOf(ored, sequence, term, name='expression')
         rule = Sequence(label, equals, expression, name='rule')
         rules = Sequence(_, OneOrMore(rule), name='rules')
@@ -231,8 +231,8 @@ rule_syntax = (r'''
                         ~"u?r?b?'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'"is
 
     expression = ored / sequence / term
-    or_term = "/" _ term
-    ored = term or_term+
+    or_term = "/" _ term+
+    ored = term+ or_term+
     sequence = term term+
     not_term = "!" term _
     lookahead_term = "&" term _
@@ -367,6 +367,10 @@ class RuleVisitor(NodeVisitor):
 
     def visit_ored(self, node, ored):
         first_term, other_terms = ored
+        if len(first_term) == 1:
+            first_term = first_term[0]
+        else:
+            first_term = Sequence(*first_term)
         return OneOf(first_term, *other_terms)
 
     def visit_or_term(self, node, or_term):
@@ -375,8 +379,11 @@ class RuleVisitor(NodeVisitor):
         We already know it's going to be ored, from the containing ``ored``.
 
         """
-        slash, _, term = or_term
-        return term
+        slash, _, terms = or_term
+        if len(terms) == 1:
+            return terms[0]
+        else:
+            return Sequence(*terms)
 
     def visit_label(self, node, label):
         """Turn a label into a unicode string."""


Test patch:
diff --git a/parsimonious/tests/test_grammar.py b/parsimonious/tests/test_grammar.py
index 3527311..ba5aa9d 100644
--- a/parsimonious/tests/test_grammar.py
+++ b/parsimonious/tests/test_grammar.py
@@ -504,6 +504,29 @@ class GrammarTests(TestCase):
             list(grammar.keys()),
             ['r%s' % i for i in range(100)])
 
+    def test_sequence_choice_bug(self):
+        """
+        Regression test for https://github.com/erikrose/parsimonious/issues/238
+        """
+        grammar = Grammar(r'''
+            value = "[" "]" / "5"
+        ''')
+        self.assertTrue(grammar.parse('[]') is not None)
+        self.assertTrue(grammar.parse('5') is not None)
+        grammar2 = Grammar(r'''
+            value = "5" / "[" "]"
+        ''')
+        self.assertTrue(grammar2.parse('[]') is not None)
+        self.assertTrue(grammar2.parse('5') is not None)
+        grammar3 = Grammar(r'''
+            value = "4" / "[" "]" / "(" ")" / "{" "}" / "5"
+        ''')
+        self.assertTrue(grammar3.parse('[]') is not None)
+        self.assertTrue(grammar3.parse('5') is not None)
+        self.assertTrue(grammar3.parse('()') is not None)
+        self.assertTrue(grammar3.parse('{}') is not None)
+        self.assertTrue(grammar3.parse('4') is not None)
+
     def test_repetitions(self):
         grammar = Grammar(r'''
             left_missing = "a"{,5}