Skip to content

Instantly share code, notes, and snippets.

@angristan
Created May 20, 2020 17:06
Show Gist options
  • Save angristan/fa7ba0819fd517d1046cac64c0216c2c to your computer and use it in GitHub Desktop.
Save angristan/fa7ba0819fd517d1046cac64c0216c2c to your computer and use it in GitHub Desktop.
import ply.yacc as yacc
import ply.lex as lex
from genereTreeGraphviz2 import printTreeGraph
tokens = (
'NUMBER', 'MINUS',
'PLUS', 'TIMES', 'DIVIDE',
'LPAREN', 'RPAREN', 'PRINT',
'EQUALS', 'NAME', 'IF', 'SEMICOLON',
'GTH', 'LTH', 'GTHOREQUAL', 'LTHOREQUAL', 'EQUALEQUAL', 'NOTEQUAL', )
# Tokens
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_SEMICOLON = r';'
t_PRINT = r'print'
t_EQUALS = r'='
t_GTH = r'\>'
t_LTH = r'\<'
t_GTHOREQUAL = r'\>='
t_LTHOREQUAL = r'\<='
t_EQUALEQUAL = r'=='
t_NOTEQUAL = r'\!='
def t_NUMBER(t):
r'\d+'
t.value = int(t.value)
return t
def t_IF(t):
r'if'
return t
# Ignored characters
t_ignore = " \t"
\
def t_newline(t):
r'\n+'
t.lexer.lineno += t.value.count("\n")
def t_error(t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
reserved = {'print': 'PRINT'}
def t_NAME(t):
r'[a-zA-Z_][a-zA-Z0-9_]*'
t.type = reserved.get(t.value, 'NAME')
return t
# Build the lexer
lex.lex()
precedence = (
('left', 'PLUS', 'MINUS'),
('left', 'TIMES', 'DIVIDE'),
# ('right', 'SEMICOLON'),
)
myVars = {}
def p_start(p):
'''
start : block
'''
p[0] = ('START', p[1])
print('Arbre de dérivation = ', p[0])
printTreeGraph(p[1])
print('result: ', eval(p[1]))
def p_expression_binop_plus(p):
'expression : expression PLUS expression'
p[0] = ('+', p[1], p[3])
def p_expression_binop_minus(p):
'expression : expression MINUS expression'
p[0] = ('-', p[1], p[3])
def p_expression_binop_times(p):
'expression : expression TIMES expression'
p[0] = ('*', p[1], p[3])
def p_expression_binop_divide(p):
'expression : expression DIVIDE expression'
p[0] = ('/', p[1], p[3])
def p_expression_group(p):
'expression : LPAREN expression RPAREN'
p[0] = p[2]
def p_print(p):
'statement : PRINT LPAREN expression RPAREN'
p[0] = ('print', p[3])
def p_expression_number(p):
'expression : NUMBER'
p[0] = p[1]
# def p_statement_expr(p):
# '''statement : expression SEMICOLON '''
# p[0] = p[1]
def p_block(p):
'''block : statement SEMICOLON block
| statement SEMICOLON'''
if len(p) == 4:
p[0] = ('block', p[1], p[3])
else:
p[0] = ('block', p[1])
def p_assignment(p):
"statement : NAME EQUALS expression"
myVars[p[1]] = p[3]
p[0] = ('assign', p[1], p[3])
def p_expression_name(p):
"expression : NAME"
p[0] = myVars[p[1]]
def p_statement_comp_if(p):
'''expression : comparison
| if_statement'''
p[0] = p[1]
def p_IF(t):
'''if_statement : IF LPAREN comparison RPAREN'''
t[0] = t[3]
def p_expression_comparison(t):
'''comparison : expression GTH expression
| expression LTH expression
| expression GTHOREQUAL expression
| expression LTHOREQUAL expression
| expression EQUALEQUAL expression
| expression NOTEQUAL expression'''
if t[2] == '>':
if t[1] > t[3]:
t[0] = True
else:
t[0] = False
elif t[2] == '<':
if t[1] < t[3]:
t[0] = True
else:
t[0] = False
elif t[2] == '>=':
if t[1] >= t[3]:
t[0] = True
else:
t[0] = False
elif t[2] == '<=':
if t[1] <= t[3]:
t[0] = True
else:
t[0] = False
elif t[2] == '==':
if t[1] == t[3]:
t[0] = True
else:
t[0] = False
elif t[2] == '!=':
if t[1] != t[3]:
t[0] = True
else:
t[0] = False
def p_error(p):
print("Syntax error at '%s'" % p.value)
yacc.yacc()
def eval(t):
print('eval de ', t)
if type(t) is int or type(t) is bool:
return t
if type(t) is tuple:
if t[0] == '+':
return eval(t[1]) + eval(t[2])
if t[0] == '-':
return eval(t[1]) - eval(t[2])
if t[0] == '*':
return eval(t[1]) * eval(t[2])
if t[0] == '/':
return eval(t[1]) / eval(t[2])
if t[0] == 'print':
return eval(t[1])
if t[0] == 'block':
return eval(t[1])
return 'UNK'
# Multiline input
# while True:
# s = ''
# line = input('reap> ')
# while line != '':
# s += line
# line = input()
s='print(1+2);x=4;x=x+1;print(x);'
yacc.parse(s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment