From: benselme Date: Fri, 9 Jan 2015 00:01:48 +0000 (-0500) Subject: More extraction in _Parser, more tests X-Git-Tag: dev-2a51c9b95d06~51^2~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c7ae2dbdb153d20fb5e6a49a1edc669a7d02e1fd;p=thirdparty%2Fbabel.git More extraction in _Parser, more tests --- diff --git a/babel/plural.py b/babel/plural.py index 5749bb04..e4acd41d 100644 --- a/babel/plural.py +++ b/babel/plural.py @@ -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): diff --git a/tests/test_plural.py b/tests/test_plural.py index 49bdfa73..d20d186a 100644 --- a/tests/test_plural.py +++ b/tests/test_plural.py @@ -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