math syntax checker written in python

前端 未结 3 1762
情歌与酒
情歌与酒 2021-02-15 06:53

All I need is to check, using python, if a string is a valid math expression or not.

For simplicity let\'s say I just need + - * / operators (+ -

相关标签:
3条回答
  • 2021-02-15 07:01

    You could try building a simple parser yourself to tokenize the string of the arithmetic expression and then build an expression tree, if the tree is valid (the leaves are all operands and the internal nodes are all operators) then you can say that the expression is valid.

    The basic concept is to make a few helper functions to create your parser.

    def extract() will get the next character from the expression
    def peek() similar to extract but used if there is no whitespace to check the next character
    get_expression()
    get_next_token()

    Alternatively if you can guarantee whitespace between characters you could use split() to do all the tokenizing.

    Then you build your tree and evaluate if its structured correctly

    Try this for more info: http://effbot.org/zone/simple-top-down-parsing.htm

    0 讨论(0)
  • 2021-02-15 07:08

    Why not just evaluate it and catch the syntax error?

    from math import *
    
    def validateSyntax(expression):
      functions = {'__builtins__': None}
      variables = {'__builtins__': None}
    
      functions = {'acos': acos,
                   'asin': asin,
                   'atan': atan,
                   'atan2': atan2,
                   'ceil': ceil,
                   'cos': cos,
                   'cosh': cosh,
                   'degrees': degrees,
                   'exp': exp,
                   'fabs':fabs,
                   'floor': floor,
                   'fmod': fmod,
                   'frexp': frexp,
                   'hypot': hypot,
                   'ldexp': ldexp,
                   'log': log,
                   'log10': log10,
                   'modf': modf,
                   'pow': pow,
                   'radians': radians,
                   'sin': sin,
                   'sinh': sinh,
                   'sqrt': sqrt,
                   'tan': tan,
                   'tanh': tanh}
    
      variables = {'e': e, 'pi': pi}
    
      try:
        eval(expression, variables, functions)
      except (SyntaxError, NameError, ZeroDivisionError):
        return False
      else:
        return True
    

    Here are some samples:

    > print validSyntax('a+b-1') # a, b are undefined, so a NameError arises.
    > False
    
    > print validSyntax('1 + 2')
    > True
    
    > print validSyntax('1 - 2')
    > True
    
    > print validSyntax('1 / 2')
    > True
    
    > print validSyntax('1 * 2')
    > True
    
    > print validSyntax('1 +/ 2')
    > False
    
    > print validSyntax('1 + (2')
    > False
    
    > print validSyntax('import os')
    > False
    
    > print validSyntax('print "asd"')
    > False
    
    > print validSyntax('import os; os.delete("~\test.txt")')
    > False # And the file was not removed
    

    It's restricted to only mathematical operations, so it should work a bit better than a crude eval.

    0 讨论(0)
  • 2021-02-15 07:10

    This is because the pyparsing code allows functions. (And by the way, it does a lot more than what you need, i.e. create a stack and evaluate that.)

    For starters, you could remove pi and ident (and possibly something else I'm missing right now) from the code to disallow characters.

    The reason is different: PyParsing parsers won't try to consume the whole input by default. You have to add + StringEnd() (and import it, of course) to the end of expr to make it fail if it can't parse the whole input. In that case, pyparsing.ParseException will be raised. (Source: http://pyparsing-public.wikispaces.com/FAQs)

    If you care to learn a bit of parsing, what you need can propably be built in less than thirty lines with any decent parsing library (I like LEPL).

    0 讨论(0)
提交回复
热议问题