Repository: alvinwan/TexSoup

Issue:
Non-matching brackets not parsed correctly
Certain math notation involves non-matched brackets.
For example the set of nonnegative numbers is denoted `$[0, \infty)$` in interval notation. TexSoup handle this notation fine on it's own but has trouble if there is command before it this non-matching expression, e.g. `$S \cup [0, \infty)$`.

```
tokenize(categorize(r"""$\cup [0, \infty)$"""))
```

GIVES
```
tokens= '$'_MathSwitch
  '\'_Escape
  'cup'_CommandName
  ' '_MergedSpacer
  '['_BracketBegin
  '0, '_Text
  '\'_Escape
  'infty'_CommandName
  ')'_Text
  '$'_MathSwitch
```

I'm thinking it sees the command then the `_BracketBegin` so it starts to look for a closing bracket thinking these are optional arguments for the command `\cup`.


Here is the minimal failing test case:

```python
def test_mixed_brackets():
    """Tests handling of math with non-matching bracket after a tex command."""
    soup = TexSoup(r"""$(-\infty,0]$""")  # works fine
    soup = TexSoup(r"""$[0, \infty)$""")  # works fine
    # GH115
    soup = TexSoup(r"""$S \cup [0, \infty)$""")
    assert True
```


Discussion:
alvinwan: Thanks for these PRs @masonproffitt! Sorry for the delay, merging now

Patch:
diff --git a/TexSoup/reader.py b/TexSoup/reader.py
index fd53989..ba92aaa 100644
--- a/TexSoup/reader.py
+++ b/TexSoup/reader.py
@@ -31,7 +31,11 @@ SIGNATURES = {
     'textbf': (1, 0),
     'section': (1, 1),
     'label': (1, 0),
+    'cap': (0, 0),
     'cup': (0, 0),
+    'in': (0, 0),
+    'notin': (0, 0),
+    'infty': (0, 0),
     'noindent': (0, 0),
 }
 
@@ -278,7 +282,7 @@ def read_env(src, expr, skip_envs=(), tolerance=0, mode=MODE_NON_MATH):
     while src.hasNext():
         if src.peek().category == TC.Escape:
             name, args = make_read_peek(read_command)(
-                src, 1, skip=1, tolerance=tolerance, mode=mode)
+                src, skip=1, tolerance=tolerance, mode=mode)
             if name == 'end':
                 break
         contents.append(read_expr(src, skip_envs=skip_envs, tolerance=tolerance, mode=mode))


Test patch:
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 60ea596..1b97eb9 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -385,7 +385,7 @@ def test_def_item():
 
 
 def test_def_without_braces():
-    """Tests that def without braces around the new command parses correctly"""
+    """Tests that def without braces around the new command parses correctly."""
     soup = TexSoup(r"\def\acommandname{replacement text}")
     assert len(soup.find("def").args) == 2
     assert str(soup.find("def").args[0]) == r"\acommandname"
@@ -398,6 +398,19 @@ def test_grouping_optional_argument():
     assert len(soup.Theorem.args) == 1
 
 
+def test_zero_argument_signatures():
+    """Tests that specific commands that do not take arguments are parsed correctly."""
+    soup = TexSoup(r"$\cap[\cup[\in[\notin[\infty[$")
+    assert len(soup.find("cap").args) == 0
+    assert len(soup.find("cup").args) == 0
+    assert len(soup.find("in").args) == 0
+    assert len(soup.find("notin").args) == 0
+    assert len(soup.find("infty").args) == 0
+
+    soup = TexSoup(r"\begin{equation} \cup [0, \infty) \end{equation}")
+    assert len(soup.find("cup").args) == 0
+
+
 ##############
 # FORMATTING #
 ##############