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)