Skip to content
Snippets Groups Projects
Commit 2b325ca8 authored by Taddeus Kroes's avatar Taddeus Kroes
Browse files

added 'delta' syntax for derivatives.

parent 41f07554
No related branches found
No related tags found
No related merge requests found
...@@ -101,3 +101,5 @@ Division of 0 by 1 reduces to 0. ...@@ -101,3 +101,5 @@ Division of 0 by 1 reduces to 0.
ERROR: 41.14-41.15: "syntax error, unexpected RPAREN" near ")". ERROR: 41.14-41.15: "syntax error, unexpected RPAREN" near ")".
- No matches for sin(pi), sin(2pi), sin(4pi), etc... - No matches for sin(pi), sin(2pi), sin(4pi), etc...
- Line generator: 'der(f(x), x)' -> 'd/dx f(x)'
...@@ -59,7 +59,7 @@ class Parser(BisonParser): ...@@ -59,7 +59,7 @@ class Parser(BisonParser):
# 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', 'LBRACKET', 'RBRACKET', \ 'LPAREN', 'RPAREN', 'FUNCTION', 'LBRACKET', 'RBRACKET', \
'APOSTROPH'] \ 'APOSTROPH', 'DELTA'] \
+ filter(lambda t: t != 'FUNCTION', TOKEN_MAP.values()) + filter(lambda t: t != 'FUNCTION', TOKEN_MAP.values())
# ------------------------------ # ------------------------------
...@@ -153,13 +153,13 @@ class Parser(BisonParser): ...@@ -153,13 +153,13 @@ class Parser(BisonParser):
# - "4a" with "4*a". # - "4a" with "4*a".
# - "a4" with "a^4". # - "a4" with "a^4".
pattern = ('(?:(\))\s*(\()' # match: )( result: ) * ( pattern = ('(?:(\))\s*(\()' # match: )( result: ) * (
+ '|([a-z0-9])\s*(\()' # match: a( result: a * ( + '|([a-ce-z0-9])\s*(\()' # match: a( result: a * (
+ '|(\))\s*([a-z0-9])' # match: )a result: ) * a + '|(\))\s*([a-ce-z0-9])' # match: )a result: ) * a
+ '|([a-z])\s*([a-z]+)' # match: ab result: a * b + '|([a-ce-z])\s*([a-ce-z]+)' # match: ab result: a * b
+ '|([0-9])\s*([a-z])' # match: 4a result: 4 * a + '|([0-9])\s*([a-ce-z])' # match: 4a result: 4 * a
+ '|([a-z])\s*([0-9])' # match: a4 result: a ^ 4 + '|([a-ce-z])\s*([0-9])' # match: a4 result: a ^ 4
+ '|([0-9])\s+([0-9]))') # match: 4 4 result: 4 * 4 + '|([0-9])\s+([0-9]))') # match: 4 4 result: 4 * 4
def preprocess_data(match): def preprocess_data(match):
left, right = filter(None, match.groups()) left, right = filter(None, match.groups())
...@@ -333,7 +333,8 @@ class Parser(BisonParser): ...@@ -333,7 +333,8 @@ class Parser(BisonParser):
| unary | unary
| binary | binary
| nary | nary
| derivative | bracket_derivative
| delta_derivative
""" """
# | concat # | concat
...@@ -348,16 +349,17 @@ class Parser(BisonParser): ...@@ -348,16 +349,17 @@ 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, 6]: # rule: unary | binary | nary | derivative if 3 <= option <= 7: # rule: unary | binary | nary
# | bracket_derivative | delta_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): def on_bracket_derivative(self, target, option, names, values):
""" """
derivative : LBRACKET exp RBRACKET APOSTROPH bracket_derivative : LBRACKET exp RBRACKET APOSTROPH
| derivative APOSTROPH | bracket_derivative APOSTROPH
""" """
op = [k for k, v in OP_MAP.iteritems() if v == OP_DERIV][0] op = [k for k, v in OP_MAP.iteritems() if v == OP_DERIV][0]
...@@ -365,12 +367,29 @@ class Parser(BisonParser): ...@@ -365,12 +367,29 @@ class Parser(BisonParser):
if option == 0: # rule: LBRACKET exp RBRACKET APOSTROPH if option == 0: # rule: LBRACKET exp RBRACKET APOSTROPH
return Node(op, values[1]) return Node(op, values[1])
if option == 1: # rule: derivative APOSTROPH if option == 1: # rule: bracket_derivative APOSTROPH
return Node(op, values[0]) return Node(op, 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_delta_derivative(self, target, option, names, values):
"""
delta_derivative : DELTA DIVIDE DELTA IDENTIFIER TIMES exp
| DELTA LPAREN exp RPAREN DIVIDE DELTA IDENTIFIER
"""
op = [k for k, v in OP_MAP.iteritems() if v == OP_DERIV][0]
if option == 0: # rule: DELTA DIVIDE DELTA IDENTIFIER TIMES exp
return Node(op, values[5], Leaf(values[3]))
if option == 1: # rule: DELTA LPAREN exp RPAREN DIVIDE DELTA IDENTIFIER
return Node(op, values[2], Leaf(values[6]))
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
...@@ -440,8 +459,9 @@ class Parser(BisonParser): ...@@ -440,8 +459,9 @@ class Parser(BisonParser):
% (option, target)) # pragma: nocover % (option, target)) # pragma: nocover
# ----------------------------------------- # -----------------------------------------
# PI and operator tokens # Special characters and operator tokens
# ----------------------------------------- # -----------------------------------------
#delta = '"%s"%s' % (DELTA, ' ' * (8 - len(DELTA)))
operators = '"%s"%s{ returntoken(IDENTIFIER); }\n' \ operators = '"%s"%s{ returntoken(IDENTIFIER); }\n' \
% (PI, ' ' * (8 - len(PI))) % (PI, ' ' * (8 - len(PI)))
functions = [] functions = []
...@@ -491,8 +511,9 @@ class Parser(BisonParser): ...@@ -491,8 +511,9 @@ class Parser(BisonParser):
%% %%
"d" { returntoken(DELTA); }
[0-9]+"."?[0-9]* { returntoken(NUMBER); } [0-9]+"."?[0-9]* { returntoken(NUMBER); }
[a-zA-Z] { returntoken(IDENTIFIER); } [a-ce-zA-Z] { returntoken(IDENTIFIER); }
"(" { returntoken(LPAREN); } "(" { returntoken(LPAREN); }
")" { returntoken(RPAREN); } ")" { returntoken(RPAREN); }
""" + operators + r""" """ + operators + r"""
......
...@@ -59,8 +59,14 @@ class TestParser(unittest.TestCase): ...@@ -59,8 +59,14 @@ class TestParser(unittest.TestCase):
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): def test_bracket_derivative(self):
x = tree('x') x = tree('x')
self.assertEqual(tree('[x]\''), der(x)) self.assertEqual(tree('[x]\''), der(x))
self.assertEqual(tree('[x]\'\''), der(der(x))) self.assertEqual(tree('[x]\'\''), der(der(x)))
def test_bracket_derivative(self):
exp, x = tree('x ^ 2, x')
self.assertEqual(tree('d/dx x ^ 2'), der(exp, x))
self.assertEqual(tree('d(x ^ 2)/dx'), der(exp, x))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment