Kaynağa Gözat

Added token with highest precedence for functions wih parentheses.

Taddeus Kroes 14 yıl önce
ebeveyn
işleme
fdca04eac6
3 değiştirilmiş dosya ile 15 ekleme ve 10 silme
  1. 11 6
      src/parser.py
  2. 3 3
      tests/test_parser.py
  3. 1 1
      tests/test_rules_goniometry.py

+ 11 - 6
src/parser.py

@@ -57,7 +57,7 @@ class Parser(BisonParser):
     # TODO: add a runtime check to verify that this token list match the list
     # of tokens of the lex script.
     tokens = ['NUMBER', 'IDENTIFIER', 'NEWLINE', 'QUIT', 'RAISE', 'GRAPH',
-              'LPAREN', 'RPAREN', 'FUNCTION'] \
+              'LPAREN', 'RPAREN', 'FUNCTION', 'FUNCTION_LPAREN'] \
              + filter(lambda t: t != 'FUNCTION', TOKEN_MAP.values())
 
     # ------------------------------
@@ -67,11 +67,11 @@ class Parser(BisonParser):
         ('left', ('COMMA', )),
         ('left', ('MINUS', 'PLUS')),
         ('left', ('TIMES', 'DIVIDE')),
+        ('right', ('FUNCTION', )),
         ('left', ('EQ', )),
         ('left', ('NEG', )),
         ('right', ('POW', )),
-        ('right', ('FUNCTION', )),
-        #('right', ('SIN', 'COS', 'TAN', 'SOLVE', 'INT', 'SQRT')),
+        ('right', ('FUNCTION_LPAREN', )),
         )
 
     interactive = 0
@@ -364,6 +364,7 @@ class Parser(BisonParser):
     def on_unary(self, target, option, names, values):
         """
         unary : MINUS exp %prec NEG
+              | FUNCTION_LPAREN exp RPAREN
               | FUNCTION exp
         """
 
@@ -378,11 +379,13 @@ class Parser(BisonParser):
 
             return node
 
-        if option == 1:  # rule: FUNCTION exp
+        if option in (1, 2):  # rule: FUNCTION_LPAREN exp RPAREN | FUNCTION exp
+            op = values[0].split(' ', 1)[0]
+
             if values[1].is_op(OP_COMMA):
-                return Node(values[0], *values[1])
+                return Node(op, *values[1])
 
-            return Node(*values)
+            return Node(op, values[1])
 
         raise BisonSyntaxError('Unsupported option %d in target "%s".'
                                % (option, target))  # pragma: nocover
@@ -445,6 +448,8 @@ class Parser(BisonParser):
 
     # Put all functions in a single regex
     if functions:
+        operators += '("%s")[ ]*"(" { returntoken(FUNCTION_LPAREN); }\n' \
+                     % '"|"'.join(functions)
         operators += '("%s") { returntoken(FUNCTION); }\n' \
                      % '"|"'.join(functions)
 

+ 3 - 3
tests/test_parser.py

@@ -50,10 +50,10 @@ class TestParser(unittest.TestCase):
         root, x = tree('sin x, x')
 
         self.assertEqual(root, sin(x))
-        #FIXME: self.assertEqual(tree('sin x ^ 2'), sin(x ** 2))
         self.assertEqual(tree('sin 2 x'), sin(2) * x)
+        self.assertEqual(tree('sin x ^ 2'), sin(x ** 2))
         self.assertEqual(tree('sin(x) ^ 2'), sin(x) ** 2)
-        self.assertEqual(tree('sin (x) ^ 2'), sin(x) ** 2)
         self.assertEqual(tree('sin(x ^ 2)'), sin(x ** 2))
         self.assertEqual(tree('sin cos x'), sin(cos(x)))
-        self.assertEqual(tree('sin cos x ^ 2'), sin(cos(x)) ** 2)
+        self.assertEqual(tree('sin cos x ^ 2'), sin(cos(x ** 2)))
+        self.assertEqual(tree('sin cos(x) ^ 2'), sin(cos(x) ** 2))

+ 1 - 1
tests/test_rules_goniometry.py

@@ -16,7 +16,7 @@ class TestRulesGoniometry(RulesTestCase):
         self.assertEqual(doctest.testmod(m=goniometry)[0], 0)
 
     def test_match_add_quadrants(self):
-        root = tree('sin t ^ 2 + cos t ^ 2')
+        root = tree('sin(t) ^ 2 + cos(t) ^ 2')
         possibilities = match_add_quadrants(root)
         self.assertEqualPos(possibilities, [P(root, add_quadrants, ())])