diff options
author | Paul McGuire <ptmcg@austin.rr.com> | 2019-08-04 09:52:35 -0500 |
---|---|---|
committer | Paul McGuire <ptmcg@austin.rr.com> | 2019-08-04 09:52:35 -0500 |
commit | e0db26b5cbc05df73f7917ffeb8f1d3144e74ec1 (patch) | |
tree | 00bf06406ebebb0fac5a212f473e29e6ccbf3a58 | |
parent | 36aa91c4f603ddb15054b0ff9f5daf5044b1dd31 (diff) | |
download | pyparsing-git-e0db26b5cbc05df73f7917ffeb8f1d3144e74ec1.tar.gz |
fourFn.py updates - handle leading '+' and '-' unary signs for parenthesized expressions; and real numbers with no leading digit before the decimal
-rw-r--r-- | examples/fourFn.py | 15 | ||||
-rw-r--r-- | unitTests.py | 9 |
2 files changed, 15 insertions, 9 deletions
diff --git a/examples/fourFn.py b/examples/fourFn.py index 5108c19..e07125f 100644 --- a/examples/fourFn.py +++ b/examples/fourFn.py @@ -11,7 +11,7 @@ # Copyright 2003-2019 by Paul McGuire # from pyparsing import (Literal, Word, Group, Forward, alphas, alphanums, Regex, ParseException, - CaselessKeyword, Suppress, delimitedList) + CaselessKeyword, Suppress, delimitedList, pyparsing_common as ppc, tokenMap) import math import operator @@ -49,6 +49,8 @@ def BNF(): # fnumber = Combine(Word("+-"+nums, nums) + # Optional("." + Optional(Word(nums))) + # Optional(e + Word("+-"+nums, nums))) + # or use provided pyparsing_common.number, but convert back to str: + # fnumber = ppc.number().addParseAction(lambda t: str(t[0])) fnumber = Regex(r"[+-]?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?") ident = Word(alphas, alphanums+"_$") @@ -62,9 +64,10 @@ def BNF(): expr_list = delimitedList(Group(expr)) # add parse action that replaces the function identifier with a (name, number of args) tuple fn_call = (ident + lpar - Group(expr_list) + rpar).setParseAction(lambda t: t.insert(0, (t.pop(0), len(t[0])))) - atom = (minus[...] + - (fn_call | pi | e | fnumber | ident).setParseAction(push_first) - | Group(lpar + expr + rpar)).setParseAction(push_unary_minus) + atom = (addop[...] + + ((fn_call | pi | e | fnumber | ident).setParseAction(push_first) + | Group(lpar + expr + rpar)) + ).setParseAction(push_unary_minus) # by defining exponentiation as "atom [ ^ factor ]..." instead of "atom [ ^ atom ]...", we get right-to-left # exponents, instead of left-to-right that is, 2^3^2 = 2^(3^2), not (2^3)^2. @@ -183,6 +186,8 @@ if __name__ == "__main__": test("sgn(cos(PI/4))", 1) test("sgn(cos(PI/2))", 0) test("sgn(cos(PI*3/4))", -1) + test("+(sgn(cos(PI/4)))", 1) + test("-(sgn(cos(PI/4)))", -1) """ @@ -229,4 +234,6 @@ round(PI^2, 3) = 9.87 [('round', 2), [['PI', '^', '2'], ['3']]] => ['PI', '2', ' sgn(cos(PI/4)) = 1 [('sgn', 1), [[('cos', 1), [['PI', '/', '4']]]]] => ['PI', '4', '/', ('cos', 1), ('sgn', 1)] sgn(cos(PI/2)) = 0 [('sgn', 1), [[('cos', 1), [['PI', '/', '2']]]]] => ['PI', '2', '/', ('cos', 1), ('sgn', 1)] sgn(cos(PI*3/4)) = -1 [('sgn', 1), [[('cos', 1), [['PI', '*', '3', '/', '4']]]]] => ['PI', '3', '*', '4', '/', ('cos', 1), ('sgn', 1)] ++(sgn(cos(PI/4))) = 1 ['+', [('sgn', 1), [[('cos', 1), [['PI', '/', '4']]]]]] => ['PI', '4', '/', ('cos', 1), ('sgn', 1)] +-(sgn(cos(PI/4))) = -1 ['-', [('sgn', 1), [[('cos', 1), [['PI', '/', '4']]]]]] => ['PI', '4', '/', ('cos', 1), ('sgn', 1), 'unary -'] """ diff --git a/unitTests.py b/unitTests.py index 4e27776..330afe1 100644 --- a/unitTests.py +++ b/unitTests.py @@ -127,8 +127,9 @@ class PyparsingTestInit(ParseTestCase): class ParseFourFnTest(ParseTestCase): def runTest(self): import examples.fourFn as fourFn + import math def test(s, ans): - fourFn.exprStack = [] + fourFn.exprStack[:] = [] results = fourFn.BNF().parseString(s) try: resultValue = fourFn.evaluate_stack(fourFn.exprStack) @@ -138,10 +139,6 @@ class ParseFourFnTest(ParseTestCase): self.assertTrue(resultValue == ans, "failed to evaluate %s, got %f" % (s, resultValue)) print_(s, "->", resultValue) - - import math - e = math.exp(1) - test("9", 9) test("-9", -9) test("--9", 9) @@ -183,6 +180,8 @@ class ParseFourFnTest(ParseTestCase): test("sgn(cos(PI/4))", 1) test("sgn(cos(PI/2))", 0) test("sgn(cos(PI*3/4))", -1) + test("+(sgn(cos(PI/4)))", 1) + test("-(sgn(cos(PI/4)))", -1) class ParseSQLTest(ParseTestCase): def runTest(self): |