]> git.ipfire.org Git - thirdparty/babel.git/commitdiff
More extraction in _Parser, more tests
authorbenselme <benselme@gmail.com>
Fri, 9 Jan 2015 00:01:48 +0000 (19:01 -0500)
committerbenselme <benselme@gmail.com>
Fri, 9 Jan 2015 00:01:48 +0000 (19:01 -0500)
babel/plural.py
tests/test_plural.py

index 5749bb04e60d75a44d99377a4b39cf3674e83bad..e4acd41d62578af7d9f89adf642498f49b47a34c 100644 (file)
@@ -296,6 +296,22 @@ def skip_token(tokens, type_, value=None):
         return tokens.pop()
 
 
+def value_node(value):
+    return 'value', (value, )
+
+
+def ident_node(name):
+    return name, ()
+
+
+def range_list_node(range_list):
+    return 'range_list', range_list
+
+
+def negate(rv):
+    return 'not', (rv,)
+
+
 class _Parser(object):
     """Internal parser.  This class can translate a single rule into an abstract
     tree of tuples. It implements the following grammar::
@@ -385,9 +401,7 @@ class _Parser(object):
                     raise RuleError('Cannot negate operator based rules.')
                 return self.newfangled_relation(left)
         rv = 'relation', (method, left, self.range_list())
-        if negated:
-            rv = 'not', (rv,)
-        return rv
+        return negate(rv) if negated else rv
 
     def newfangled_relation(self, left):
         if skip_token(self.tokens, 'symbol', '='):
@@ -412,7 +426,7 @@ class _Parser(object):
         range_list = [self.range_or_value()]
         while skip_token(self.tokens, 'symbol', ','):
             range_list.append(self.range_or_value())
-        return 'range_list', range_list
+        return range_list_node(range_list)
 
     def expr(self):
         word = skip_token(self.tokens, 'word')
@@ -423,10 +437,10 @@ class _Parser(object):
             return 'mod', ((name, ()), self.value())
         elif skip_token(self.tokens, 'symbol', '%'):
             return 'mod', ((name, ()), self.value())
-        return name, ()
+        return ident_node(name)
 
     def value(self):
-        return 'value', (int(self.expect('value')[1]),)
+        return value_node(int(self.expect('value')[1]))
 
 
 def _binary_compiler(tmpl):
index 49bdfa737c7f48e3aded710b44677e08fea23c0c..d20d186a480a0d8abfac10879860fa82c4942bb9 100644 (file)
@@ -142,4 +142,37 @@ class TestNextTokenTestCase(unittest.TestCase):
         assert plural.test_next_token([('word', 'and')], 'word', 'and')
 
     def test_type_not_ok_and_value_ok(self):
-        assert not plural.test_next_token([('abc', 'and')], 'word', 'and')
\ No newline at end of file
+        assert not plural.test_next_token([('abc', 'and')], 'word', 'and')
+
+
+def make_range_list(*values):
+    ranges = []
+    for v in values:
+        if isinstance(v, int):
+            val_node = plural.value_node(v)
+            ranges.append((val_node, val_node))
+        else:
+            assert isinstance(v, tuple)
+            ranges.append((plural.value_node(v[0]),
+                           plural.value_node(v[1])))
+    return plural.range_list_node(ranges)
+
+
+class PluralRuleParserTestCase(unittest.TestCase):
+    def setUp(self):
+        self.n = plural.ident_node('n')
+        self.n_eq_1 = ('relation', ('in', self.n, make_range_list(1)))
+
+    def test_error_when_unexpected_end(self):
+        with pytest.raises(plural.RuleError):
+            plural._Parser('n =')
+
+    def test_eq_relation(self):
+        assert plural._Parser('n = 1').ast == self.n_eq_1
+
+    def test_in_range_relation(self):
+        assert plural._Parser('n = 2..4').ast == \
+            ('relation', ('in', self.n, make_range_list((2, 4))))
+
+    def test_negate(self):
+        assert plural._Parser('n != 1').ast == plural.negate(self.n_eq_1)
\ No newline at end of file