Question

I have a file with a lot of lines like this

f(a, b)
f(abc, def)
f(a, f(u, i))
...

and I was asked to write a program in Python that would translate the strings into the following format:

a+b
abc+def
a+(u+i)
...

Rule: f(a, b) -> a+b

The approach I am following right now uses eval functions:

def f(a, b):
    return "({0} + {1})".format(a,b)

eval("f(f('b','a'),'c')")

which returns

'((b + a) + c)'

However, as you can see, I need to put the letters as strings so that the eval function does not throw me a NameError when I run it.

Is there any way that will allow me to get the same behavior out of the eval function but without declaring the letters as strings?

Was it helpful?

Solution

eval is overkill here. this is just a simple string processing exercise:

  • replace the first 'f(' and the last ')' with ''
  • replace all remaining 'f(' with '('
  • replace all ', ' with '+'

and you're done.

this assumes that the only time the characters 'f(' appear next to each other is when it's supposed to represent a call to function f.

OTHER TIPS

Yes, you can. The key is to use a mapping which returns the string as a key when it is missing.

>>> class Mdict(dict):
...     def __missing__(self, k):
...         return k
... 
>>> eval('foo + bar', Mdict())
'foobar'

Of course, the general caveats about eval apply -- Please don't use it unless you trust the input completely.

You could use the shlex module to give yourself a nice token stack and then parse it as a sort of push down automaton.

>>> import shlex
>>> def parsef(tokens):
    ftok = tokens.get_token()       # there's no point to naming these tokens
    oparentok = tokens.get_token()  # unless you want to assert correct syntax
    lefttok = tokens.get_token()
    if 'f' == lefttok:
        tokens.push_token(lefttok)
        lefttok = "("+parsef(tokens)+")"
    commatok = tokens.get_token()
    righttok = tokens.get_token()
    if 'f' == righttok:
        tokens.push_token(righttok)
        righttok = "("+parsef(tokens)+")"
    cparentok = tokens.get_token()
    return lefttok+"+"+righttok
>>> def parseline(line):
    return parsef(shlex.shlex(line.strip()))
>>> parseline('f(a, b)')
'a+b'
>>> parseline('f(abc, def)')
'abc+def'
>>> parseline('f(a, f(u, i))')
'a+(u+i)'

Note that this assumes you are getting correct syntax.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top