Commit 9e395dc2 authored by Taddeus Kroes's avatar Taddeus Kroes

Added new syntax for derivatives to the parser.

parent 30700670
...@@ -15,7 +15,8 @@ from pybison import BisonParser, BisonSyntaxError ...@@ -15,7 +15,8 @@ from pybison import BisonParser, BisonSyntaxError
from graph_drawing.graph import generate_graph from graph_drawing.graph import generate_graph
from node import ExpressionNode as Node, ExpressionLeaf as Leaf, OP_MAP, \ from node import ExpressionNode as Node, ExpressionLeaf as Leaf, OP_MAP, \
TOKEN_MAP, TYPE_OPERATOR, OP_COMMA, OP_NEG, OP_MUL, OP_DIV, Scope, PI OP_DERIV, TOKEN_MAP, TYPE_OPERATOR, OP_COMMA, OP_NEG, OP_MUL, OP_DIV, \
Scope, PI
from rules import RULES from rules import RULES
from strategy import pick_suggestion from strategy import pick_suggestion
from possibilities import filter_duplicates, apply_suggestion from possibilities import filter_duplicates, apply_suggestion
...@@ -57,7 +58,8 @@ class Parser(BisonParser): ...@@ -57,7 +58,8 @@ class Parser(BisonParser):
# TODO: add a runtime check to verify that this token list match the list # TODO: add a runtime check to verify that this token list match the list
# of tokens of the lex script. # of tokens of the lex script.
tokens = ['NUMBER', 'IDENTIFIER', 'NEWLINE', 'QUIT', 'RAISE', 'GRAPH', tokens = ['NUMBER', 'IDENTIFIER', 'NEWLINE', 'QUIT', 'RAISE', 'GRAPH',
'LPAREN', 'RPAREN', 'FUNCTION'] \ 'LPAREN', 'RPAREN', 'FUNCTION', 'LBRACKET', 'RBRACKET', \
'APOSTROPH'] \
+ filter(lambda t: t != 'FUNCTION', TOKEN_MAP.values()) + filter(lambda t: t != 'FUNCTION', TOKEN_MAP.values())
# ------------------------------ # ------------------------------
...@@ -331,6 +333,7 @@ class Parser(BisonParser): ...@@ -331,6 +333,7 @@ class Parser(BisonParser):
| unary | unary
| binary | binary
| nary | nary
| derivative
""" """
# | concat # | concat
...@@ -345,12 +348,29 @@ class Parser(BisonParser): ...@@ -345,12 +348,29 @@ class Parser(BisonParser):
if option == 2: # rule: LPAREN exp RPAREN if option == 2: # rule: LPAREN exp RPAREN
return values[1] return values[1]
if option in [3, 4, 5]: # rule: unary | binary | nary if option in [3, 4, 5, 6]: # rule: unary | binary | nary | derivative
return values[0] return values[0]
raise BisonSyntaxError('Unsupported option %d in target "%s".' raise BisonSyntaxError('Unsupported option %d in target "%s".'
% (option, target)) # pragma: nocover % (option, target)) # pragma: nocover
def on_derivative(self, target, option, names, values):
"""
derivative : LBRACKET exp RBRACKET APOSTROPH
| derivative APOSTROPH
"""
op = [k for k, v in OP_MAP.iteritems() if v == OP_DERIV][0]
if option == 0: # rule: LBRACKET exp RBRACKET APOSTROPH
return Node(op, values[1])
if option == 1: # rule: derivative APOSTROPH
return Node(op, values[0])
raise BisonSyntaxError('Unsupported option %d in target "%s".'
% (option, target)) # pragma: nocover
def on_unary(self, target, option, names, values): def on_unary(self, target, option, names, values):
""" """
unary : MINUS exp %prec NEG unary : MINUS exp %prec NEG
...@@ -482,6 +502,9 @@ class Parser(BisonParser): ...@@ -482,6 +502,9 @@ class Parser(BisonParser):
[ \t\v\f] { } [ \t\v\f] { }
[\n] { yycolumn = 0; returntoken(NEWLINE); } [\n] { yycolumn = 0; returntoken(NEWLINE); }
"[" { returntoken(LBRACKET); }
"]" { returntoken(RBRACKET); }
"'" { returntoken(APOSTROPH); }
. { printf("unknown char %c ignored.\n", yytext[0]); } . { printf("unknown char %c ignored.\n", yytext[0]); }
%% %%
......
...@@ -6,6 +6,7 @@ from src.node import ExpressionNode as Node, ExpressionLeaf as Leaf ...@@ -6,6 +6,7 @@ from src.node import ExpressionNode as Node, ExpressionLeaf as Leaf
from tests.parser import ParserWrapper, run_expressions, line, graph from tests.parser import ParserWrapper, run_expressions, line, graph
from tests.rulestestcase import tree from tests.rulestestcase import tree
from src.rules.goniometry import sin, cos from src.rules.goniometry import sin, cos
from src.rules.derivatives import der
class TestParser(unittest.TestCase): class TestParser(unittest.TestCase):
...@@ -47,12 +48,18 @@ class TestParser(unittest.TestCase): ...@@ -47,12 +48,18 @@ class TestParser(unittest.TestCase):
self.assertEqual(tree('-(a / b)'), (-a) / b) self.assertEqual(tree('-(a / b)'), (-a) / b)
def test_functions(self): def test_functions(self):
root, x = tree('sin x, x') x = tree('x')
self.assertEqual(root, sin(x)) self.assertEqual(tree('sin x'), sin(x))
self.assertEqual(tree('sin(x)'), sin(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 (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'), 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)
def test_derivative(self):
x = tree('x')
self.assertEqual(tree('[x]\''), der(x))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment