test_parser.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. # vim: set fileencoding=utf-8 :
  2. from src.parser import Parser, find_possibilities
  3. from src.node import ExpressionNode as Node, ExpressionLeaf as Leaf, \
  4. SPECIAL_TOKENS, sin, cos, der, log, ln, integral, indef, absolute, \
  5. Scope
  6. from src.possibilities import Possibility as P
  7. from src.rules.numerics import add_numerics
  8. from tests.parser import ParserWrapper, run_expressions, line, graph
  9. from tests.rulestestcase import RulesTestCase, tree
  10. class TestParser(RulesTestCase):
  11. def test_constructor(self):
  12. node = Node('+', Leaf(1), Leaf(4))
  13. self.assertEqual(ParserWrapper(Parser).run(['1 + 4']), node)
  14. def test_identifiers(self):
  15. run_expressions(Parser, [('a', Leaf('a'))])
  16. def test_graph(self):
  17. self.assertEqual(graph(Parser, '4a'), ("""
  18. *
  19. ╭┴╮
  20. 4 a
  21. """).replace('\n ', '\n')[1:-1])
  22. def test_line(self):
  23. self.assertEqual(line(Parser, '4-a'), '4 - a')
  24. def test_reset_after_failure(self):
  25. parser = ParserWrapper(Parser)
  26. parser.run(['-(3a+6b)'])
  27. parser.parser.find_possibilities()
  28. possibilities1 = parser.parser.possibilities
  29. self.assertNotEqual(possibilities1, [])
  30. parser.run(['5+2*6'])
  31. parser.parser.find_possibilities()
  32. possibilities2 = parser.parser.possibilities
  33. self.assertNotEqual(possibilities2, [])
  34. self.assertNotEqual(possibilities1, possibilities2)
  35. def test_binary(self):
  36. a, b, c = tree('a, b, c')
  37. self.assertEqual(tree('a ^^ b'), a & b)
  38. self.assertEqual(tree('a vv b'), a | b)
  39. self.assertEqual(tree('a vv b vv c'), (a | b) | c)
  40. self.assertEqual(tree('a vv b ^^ c'), a | (b & c))
  41. def test_preprocessor(self):
  42. self.assertEqual(tree('ab'), tree('a * b'))
  43. self.assertEqual(tree('abc'), tree('a * b * c'))
  44. self.assertEqual(tree('a2'), tree('a ^ 2'))
  45. self.assertEqual(tree('a 2'), tree('a * 2'))
  46. self.assertEqual(tree('2a'), tree('2 * a'))
  47. self.assertEqual(tree('2(a + b)'), tree('2 * (a + b)'))
  48. self.assertEqual(tree('(a + b)2'), tree('(a + b) * 2'))
  49. self.assertEqual(tree('(a)(b)'), tree('(a) * (b)'))
  50. self.assertEqual(tree('(a)[b]\''), tree('(a) * [b]\''))
  51. # FIXME: self.assertEqual(tree('(a)|b|'), tree('(a) * |b|'))
  52. # FIXME: self.assertEqual(tree('|a|(b)'), tree('|a| * (b)'))
  53. # FIXME: self.assertEqual(tree('a|b|'), tree('a * |b|'))
  54. # FIXME: self.assertEqual(tree('|a|b'), tree('|a| * b'))
  55. self.assertEqual(tree('|a||b|'), tree('|a| * |b|'))
  56. def test_functions(self):
  57. x = tree('x')
  58. self.assertEqual(tree('sin x'), sin(x))
  59. self.assertEqual(tree('sin 2 x'), sin(2) * x) # FIXME: correct?
  60. self.assertEqual(tree('sin x ^ 2'), sin(x ** 2))
  61. self.assertEqual(tree('sin(x) ^ 2'), sin(x) ** 2)
  62. self.assertEqual(tree('sin(x ^ 2)'), sin(x ** 2))
  63. self.assertEqual(tree('sin cos x'), sin(cos(x)))
  64. self.assertEqual(tree('sin cos x ^ 2'), sin(cos(x ** 2)))
  65. self.assertEqual(tree('sin cos(x) ^ 2'), sin(cos(x) ** 2))
  66. def test_bracket_derivative(self):
  67. x = tree('x')
  68. self.assertEqual(tree('[x]\''), der(x))
  69. self.assertEqual(tree('[x]\'\''), der(der(x)))
  70. def test_delta_derivative(self):
  71. exp, x, d = tree('x ^ 2, x, d')
  72. self.assertEqual(tree('d/dx x ^ 2'), der(exp, x))
  73. self.assertEqual(tree('d / dx x ^ 2'), der(exp, x))
  74. self.assertEqual(tree('d/dx x ^ 2 + x'), der(exp + x, x))
  75. self.assertEqual(tree('(d/dx x ^ 2) + x'), der(exp, x) + x)
  76. self.assertEqual(tree('d/d'), d / d)
  77. # FIXME: self.assertEqual(tree('d(x ^ 2)/dx'), der(exp, x))
  78. def test_logarithm(self):
  79. x, g = tree('x, g')
  80. self.assertEqual(tree('log(x, e)'), ln(x))
  81. self.assertEqual(tree('log(x, 10)'), log(x))
  82. self.assertEqual(tree('log(x, 2)'), log(x, 2))
  83. self.assertEqual(tree('log(x, g)'), log(x, g))
  84. self.assertEqual(tree('log_2(x)'), log(x, 2))
  85. self.assertEqual(tree('log_10(x)'), log(x))
  86. self.assertEqual(tree('log_g(x)'), log(x, g))
  87. self.assertEqual(tree('log_g x'), log(x, g))
  88. def test_special_tokens(self):
  89. for token in SPECIAL_TOKENS:
  90. self.assertEqual(tree(token), Leaf(token))
  91. a, t = Leaf('a'), Leaf(token)
  92. self.assertEqual(tree('a' + token), a * t)
  93. # FIXME: self.assertEqual(tree('a' + token + 'a'), a * t * a)
  94. def test_integral(self):
  95. x, y, dx, a, b, l2 = tree('x, y, dx, a, b, 2')
  96. self.assertEqual(tree('int x'), integral(x, x))
  97. self.assertEqual(tree('int x2'), integral(x ** 2, x))
  98. self.assertEqual(tree('int x2 dx'), integral(x ** 2, x))
  99. self.assertEqual(tree('int x2 dy'), integral(x ** 2, y))
  100. self.assertEqual(tree('int_a^b x2'), integral(x ** 2, x, a, b))
  101. self.assertEqual(tree('int_a^b x2 dy'), integral(x ** 2, y, a, b))
  102. self.assertEqual(tree('int_(a-b)^(a+b) x2'),
  103. integral(x ** 2, x, a - b, a + b))
  104. self.assertEqual(tree('int_a^b 2x'), integral(l2 * x, x, a, b))
  105. self.assertEqual(tree('int_a^b2 x'), integral(x, x, a, b ** 2))
  106. def test_indefinite_integral(self):
  107. x2, a, b = tree('x ^ 2, a, b')
  108. self.assertEqual(tree('[x ^ 2]_a^b'), indef(x2, a, b))
  109. def test_absolute_value(self):
  110. x = tree('x')
  111. self.assertEqual(tree('|x|'), absolute(x))
  112. self.assertEqual(tree('|x2|'), absolute(x ** 2))
  113. def test_find_possibilities_basic(self):
  114. l1, l2 = root = tree('1 + 2')
  115. self.assertEqual(find_possibilities(root),
  116. [P(root, add_numerics, (Scope(root), l1, l2))])
  117. def test_find_possibilities_duplicates(self):
  118. (l1, l2), l3 = root = tree('1 + 2 + 3')
  119. self.assertEqual(find_possibilities(root),
  120. [P(root, add_numerics, (Scope(root), l1, l2)),
  121. P(root, add_numerics, (Scope(root), l1, l3)),
  122. P(root, add_numerics, (Scope(root), l2, l3))])
  123. def test_no_expression_error(self):
  124. self.assertRaises(RuntimeError, ParserWrapper(Parser).run, ['', '?'])