4

I have a syntax tree

Tree(if, [Tree(condition, [Token(VARIABLE, 'age'), Token(ACTION_OPERATOR, '>'), Token(SIGNED_NUMBER, '18')]), Tree(result, [Tree(if, [Tree(condition, [Token(VARIABLE, 'salary'), Token(ACTION_OPERATOR, '>'), Token(SIGNED_NUMBER, '100000')]), Tree(result, [Token(STRING, 'success')]), Tree(condition, [Token(VARIABLE, 'salary'), Token(ACTION_OPERATOR, '<'), Token(SIGNED_NUMBER, '50000')]), Tree(result, [Token(STRING, 'fail')]), Tree(else, [Token(STRING, 'get_more_info')])])]), Tree(else, [Token(STRING, 'fail')])])

And I convert it to string:

if age > 18:
    if salary > 100000:
        print('success')
    elif salary < 50000:
        print('fail')
    else: 
        print('get_more_info')
else:
    print('fail')

I declare variables:

age = 20
salary = 60000

And try to execute this code with

eval(code)

and get an error

File "<string>", line 1
if age > 18: 
 ^
SyntaxError: invalid syntax
Petr Petrov
  • 4,090
  • 10
  • 31
  • 68
  • Possible duplicate of [Eval not working on multi-line string](https://stackoverflow.com/questions/30671563/eval-not-working-on-multi-line-string) – Georgy Mar 30 '18 at 09:56
  • 1
    Found more detailed answer. https://stackoverflow.com/questions/2220699/whats-the-difference-between-eval-exec-and-compile-in-python – Ryan Mar 30 '18 at 10:01
  • May I ask how you convert back and forth between syntax tree and code as a string? – jmd_dk Mar 30 '18 at 10:06
  • Does this answer your question? [What's the difference between eval, exec, and compile?](https://stackoverflow.com/questions/2220699/whats-the-difference-between-eval-exec-and-compile) – SuperStormer Nov 07 '21 at 01:55

2 Answers2

3

You're looking for exec not eval:

code = """
if age > 18:
    if salary > 100000:
        print('success')
    elif salary < 50000:
        print('fail')
    else: 
        print('get_more_info')
else:
    print('fail')"""

exec(code, {"age": 20, "salary": 60000})
# out: get_more_info

exec takes a code string, or an code object. While eval takes an expression.


Alternatively, you can always evaluate (using eval) code objects by compiling the code string beforehand:

eval(compile(code, '<string>', 'exec'), {"age": 20, "salary": 60000})
# out: get_more_info

Just for the fun of it, you can use eval for your syntax tree without needing to compile your code, but your code has to be a bit different:

code = 'print(("success" if salary > 100000  else "fail" if salary < 50000 else "get_more_info") if age > 18 else "fail")'

eval(code, {"age": 20, "salary": 60000})
# out: get_more_info

This utilizes Python's ternary conditions, which technically is still counted as an expression.

Taku
  • 31,927
  • 11
  • 74
  • 85
  • and can you say, If I have not formated string like `"if age > 18: if salary > 100000: print('success') elif salary < 50000: print('fail') else: print('get_more_info') else: print('fail')"` is any way to add markup? – Petr Petrov Mar 30 '18 at 12:11
  • My last example uses the ternary syntax, it changed more than just the formatting. You can add comments (if that's what you meant by markup) at the end of the expression, since ternary conditions are no different than normal expressions. Though I do advise to use my first example because it's the clearest and the simplest to use. – Taku Mar 30 '18 at 12:21
1

You are confusing eval() with exec().

eval() is used for expressions, such as False==True:

>>> eval('False==True')
False

exec() is used to dynamically execute code:

age = 10
s = '''
if age > 18:
    if salary > 100000:
        print('success')
    elif salary < 50000:
        print('fail')
    else: 
        print('get_more_info')
else:
    print('fail')
'''

exec(s)

Output:

fail
user3483203
  • 50,081
  • 9
  • 65
  • 94