Skip to content

Instantly share code, notes, and snippets.

@ohaz
Created March 8, 2016 09:07
Show Gist options
  • Save ohaz/ed0b14a487b0569aad2d to your computer and use it in GitHub Desktop.
Save ohaz/ed0b14a487b0569aad2d to your computer and use it in GitHub Desktop.
Parse math formulas in python and put parentheses around Mult/Div
from __future__ import print_function
import ast
def recurse(node):
if isinstance(node, ast.BinOp):
if isinstance(node.op, ast.Mult) or isinstance(node.op, ast.Div):
print('(', end='')
recurse(node.left)
recurse(node.op)
recurse(node.right)
if isinstance(node.op, ast.Mult) or isinstance(node.op, ast.Div):
print(')', end='')
elif isinstance(node, ast.Add):
print('+', end='')
elif isinstance(node, ast.Sub):
print('-', end='')
elif isinstance(node, ast.Mult):
print('*', end='')
elif isinstance(node, ast.Div):
print('/', end='')
elif isinstance(node, ast.Num):
print(node.n, end='')
else:
for child in ast.iter_child_nodes(node):
recurse(child)
def search_expr(node):
returns = []
for child in ast.iter_child_nodes(node):
if isinstance(child, ast.Expr):
return child
returns.append(search_expr(child))
for ret in returns:
if isinstance(ret, ast.Expr):
return ret
return None
formula = '3+7*8/2'
a = ast.parse(formula)
expr = search_expr(a)
if expr is not None:
recurse(expr)
@ohaz
Copy link
Author

ohaz commented Apr 29, 2020

The issue is that this gist is printing the results, not putting them in a variable. That's why it returns None

@bigtoerag
Copy link

Would it be easy/possible to switch it over to variable? I could try but I am greener than grass at this.

@ohaz
Copy link
Author

ohaz commented Apr 29, 2020

yep like this:

from __future__ import print_function
import ast

def fix(formula):
    def recurse(node):
        result = ''
        if isinstance(node, ast.BinOp):
            if isinstance(node.op, ast.Mult) or isinstance(node.op, ast.Div):
                result += '('
            result += recurse(node.left)
            result += recurse(node.op)
            result += recurse(node.right)
            if isinstance(node.op, ast.Mult) or isinstance(node.op, ast.Div):
                result += ')'
        elif isinstance(node, ast.Add):
            result += '+'
        elif isinstance(node, ast.Sub):
            result += '-'
        elif isinstance(node, ast.Mult):
            result += '*'
        elif isinstance(node, ast.Div):
            result += '/'
        elif isinstance(node, ast.Num):
            result += str(node.n)
        else:
            for child in ast.iter_child_nodes(node):
                result += recurse(child)
        return result
    
    
    def search_expr(node):
        returns = []
        for child in ast.iter_child_nodes(node):
            if isinstance(child, ast.Expr):
                return child
            returns.append(search_expr(child))
        for ret in returns:
            if isinstance(ret, ast.Expr):
                return ret
        return None
    a = ast.parse(formula)
    expr = search_expr(a)
    output = recurse(expr)
    return output

@bigtoerag
Copy link

bigtoerag commented Apr 30, 2020

Legend Thankyou, just tested perfectly. I will trawl over it and see if I can learn more about it and not have to ask next time.
All part of my new COVID skills in python
Dice roller

@ohaz
Copy link
Author

ohaz commented Apr 30, 2020

Looking good! So nice to see that there are good things coming out of COVID :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment