Python Forum
How to split a string containing function calls? - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: How to split a string containing function calls? (/thread-13622.html)



How to split a string containing function calls? - Metalman488 - Oct-24-2018

So I am working on a program that takes function calls like:
add(2,2)
multiply(1,2)
add(add(2,2),6)
multiply(add(add(1,3),2),3)
add(add(2,2),add(1,1))

My current code can solve the first 2 just fine and I have an idea on how to solve the ones with the nested functions using recursion, but I can't figure out how to split the string up for the nested calls.

My current function just takes in a string, then gets each value from between the parentheses,
so for the first example I have:
val1 = 2
val2 = 2

so what I need to do for a line like the last one is have it split it so that:
val1 = add(2,2)
val2 = add(1,1)

I figure in my current code I could add an if statement that checks to see if each value contains "add" or "multiply", then call the processing function recursively so that it could evaluate it and return the result.
so some pseudo code for that would be something like:
def f(str):
val1 = left side of comma #add(2,2) for first run
val2 = right side of comma #add(1,1) for first run

if(val1.find("add") != -1):
val1 = f(val1)
elif(val2.find("add") != -1):
val2 = f(val2)
elif(val1 == number and val2 == number):
Result = val1 + val2
return Result
f(add(add(2,2),add(1,1))

This is basically what I'm thinking so far on that aspect of my program, but before I can work on figuring that out I must first figure out how to split the line correctly.

Here is what I just tried:
st = "add(add(2,2),add(3,3))"

print("1: ", st[st.find('(')+1:st.rfind(',')])
print("2: ", st[st.rfind(',')+1:st.rfind(')')])
the output was:
1: add(2,2),add(3
2: 3)

The above code works if st were something like "add(add(1,2),6)", but not if there's another add function in there. I see why, I'm just not sure how to fix it. Then there's how I would deal with something like "multiply(add(add(1,3),2),3)".
Maybe I need to find the last '(' then the first ')' get the result of that, and replace the function call with it's answer, then repeat? Like multiply(add(add(1,3),2),3) => multiply(add(4,2),3) => multiply(6,3) => 18
But besides the parentheses I need to check what operation I'm supposed to perform. Would it work to find last operation? Like I check last of '(' and first of ')' to get 1,3 then I check last operation and get "add" so then I perform add on 1 and 3. But I'm not sure how to get it to check for either function. Like if I were to check last of "multiply", then that wouldn't give me the correct result because I need last of "add". The reason I haven't just tested the above is because I don't know the python code for find_first_of and find_last_of. From what I can tell Python doesn't have functions built in for that like C++, so I'm not sure how to do it.

I'm not asking for code, although it would be appreciated, I'm mainly just looking for ideas because I'm still new to Python.
The main thing I need help on is the string splitting, but if you have any advice on my recursive evaluation idea then I would appreciate that as well.

Sorry if my explanation seems a little sloppy, I am pretty tired at the time of posting this. I'd wait until morning to post this, but I wanted to get it up as soon as possible. I'll look at it in the morning and clean it up as needed.

Thanks in advance.


RE: How to split a string containing function calls? - buran - Oct-24-2018

I am note sure I understand what you try to do, but look at tokenize module


RE: How to split a string containing function calls? - Metalman488 - Oct-25-2018

What I'm trying to do at the moment is split the strings I get in the following examples:
add(add(1,2),3) #This one I can already do somewhat. Its infix equivalent is (1+2)+3
multiply(add(1,1),add(2,2)) #This is where I get lost on how to do it. Its infix equivalent is (1+1)*(2+2)
multiply(add(add(1,3),2),3) #Its infix equivalent is ((1+3)+2)*3

I just mixed up the "add" and "multiply" in the above examples because they are interchangeable. What I am needing to do is take those expressions in as strings and evaluate them. I currently have a function that can solve expressions like add(1,2) or multiply(2,2), but I need to be able to evaluate the examples above. But before I can evaluate them I need to split them up.

so for the first example "add(add(1,2),3)"
I need to split the contents of the parentheses like so: val1 = add(1,2) val2 = 3
Then I need to evaluate add(1,2) and replace val1 with that value, then evaluate add(3,3)

For the second example "multiply(add(1,1),add(2,2))"
I need val1 = add(1,1) and val2 = add(2,2)
I then need to evaluate each of the vals (val1 = 2, val2 = 4) and then evaluate multiply(2,4)

For the third example "multiply(add(add(1,3),2),3)"
This one goes a bit deeper due to nested recursive calls (the recursive calls can be up to 3 levels deep)
1st run: val1 = add(add(1,3),2) val2 = 3
2nd run: val1 = add(1,3) val2 = 2
3rd run: val1 = 1 val2 = 3
This will evaluate add(1,3), then return to second run which should then evaluate (1+3)+2, then the 1st run gets the result of (1+3)+2 and multiplies it with 3.

The main thing I was trying to get help with in this post was how to split the expressions into the val1's and val2's like what I showed above, the evaluation is just the next step which I'll try to figure out after I find out how to do the strings the way I need to. I looked up the tokenize module you shared with me, but I didn't really see how to use it for this.

Thank you for the reply.


RE: How to split a string containing function calls? - Metalman488 - Oct-27-2018

Can anyone give me any suggestions?
I'm playing with it a bit, but all I've gotten so far is to take the example: add(add(2,2),add(3,3))
and do this:
st = "add(add(2,2),add(3,3))"

print(st[st.find('(')+1:st.rfind(')')])
which outputs: add(2,2),add(3,3)

But I'm unsure of where to go from here. I could do something to find that second comma and then set val1 to everything before the second comma and set val2 equal to everything after the second comma, but I feel like this is too specific a solution. This will work for an example like the above, but not for "multiply(add(add(1,3),2),3)". I'll continue playing with it, but I would really appreciate any advice someone could give me to make it more flexible.

If I could find some way to find all the function calls in the string that only have integers as the parameters, solve them, and replace them in the line with their results then that would probably be a good solution. This sounds good, but the problem is that I have absolutely no idea how to do that.


RE: How to split a string containing function calls? - Metalman488 - Oct-27-2018

I believe I have found the answer to my problem: regular expressions.
Remember I said if there was a way to look for all expressions in form add/multiply(int,int) and replace with value? I found out that regular expressions can do that first part.

Here is a simple example of the code I'm using:
import re

pattern = re.compile(r'(add|multiply)\([0-9]+,[0-9]+\)')

s = multiply(add(1,2), add(3,4))

match = pattern.search(s)

print(match.group(0))
This will print out "add(1,2)" which I can then pass to my evaluation function to solve.
I can then replace "add(1,2)" with its value by using string.replace
#My evaluation function takes in a string of the form add(int,int) and returns the result in string form
s = s.replace(match.group(0), add(match.group(0))
after this s will be "multiply(3, add(3,4))

So I can just put this in a loop and it will eventually get me the answer!

Thank you viewers for the moral support and thank you buran for your earlier reply.

Here is the link to the regular expressions tutorial I watched in case someone else needs it: https://www.youtube.com/watch?v=K8L6KVGG-7o