bison マニュアルの多機能電卓 練習問題2
定数 PI, E を追加
#!/usr/bin/env python import ply.lex as lex tokens = ( 'NUM', 'VAR', 'FNCT', ) literals = ['+', '-', '*', '/', '^', '(', ')', '='] def t_NUM(t): r'\d+(\.\d+)*' try: t.value = float(t.value) except ValueError: print "Integer value too large", t.value t.value = 0 return t def t_VAR(t): r'[a-zA-Z_][a-zA-Z0-9_]*' s = getsym(t.value) if not s: s = putsym(t.value, "VAR") t.type = s["TYPE"] return t t_ignore = " \t" def t_error(t): print "Illegal character '%s'" % t.value[0] t.lexer.skip(1) lex.lex() import ply.yacc as yacc precedence = ( ('right', '='), ('left', '+', '-'), ('left', '*', '/'), ('left', 'NEG'), ('right', '^'), ) def p_input(p): "input : exp" print "\t%f" % p[1] def p_input_error(p): "input : exp error" def p_exp_num(p): "exp : NUM" p[0] = p[1] def p_exp_var(p): "exp : VAR" p[0] = sym[p[1]]["VAL"] def p_exp(p): '''exp : VAR '=' exp | FNCT '(' exp ')' | exp '+' exp | exp '-' exp | exp '*' exp | exp '/' exp | '-' exp %prec NEG | exp '^' exp | '(' exp ')' ''' if p[1] == '(' : p[0] = p[2] elif p[1] == '-' : p[0] = -p[2] elif p[2] == '=' : p[0] = p[3]; putsym(p[1], "VAR", p[3]) elif p[2] == '(' : p[0] = func(p[1], p[3]) elif p[2] == '+' : p[0] = p[1] + p[3] elif p[2] == '-' : p[0] = p[1] - p[3] elif p[2] == '*' : p[0] = p[1] * p[3] elif p[2] == '/' : p[0] = p[1] / p[3] elif p[2] == '^' : p[0] = p[1] ** p[3] def p_error(p): print "Syntax error at '%s'" % p.value yacc.yacc() sym = {} def putsym(sym_name, sym_type, value = 0): global sym sym[sym_name] = { "NAME" : sym_name, "TYPE" : sym_type, "VAL" : value } return sym[sym_name] def getsym(sym_name): global sym if sym.has_key(sym_name): return sym[sym_name] else: return None def func(sym_name, arg): import math if sym_name == "sin": return math.sin(arg) elif sym_name == "cos": return math.cos(arg) elif sym_name == "atan": return math.atan(arg) elif sym_name == "ln": return math.log(arg) elif sym_name == "exp": return math.exp(arg) elif sym_name == "sqrt": return math.sqrt(arg) def init_table(): for f in ["sin", "cos", "atan", "ln", "exp", "sqrt"]: putsym(f, "FNCT") def init_const_table(): putsym("PI", "VAR", 3.14159265358979) putsym("E", "VAR", 2.71828182845905) init_table() init_const_table() while 1: try: s = raw_input('input > ') except EOFError: break if not s: continue yacc.parse(s)
で、
yacc: 5 shift/reduce conflicts input > E 2.718282 input > PI 3.141593 input > ln(E) 1.000000 input > pi = 3.141592653589 3.141593 input > sin(pi) 0.000000 input > alpha = beta1 = 2.3 2.300000 input > alpha 2.300000 input > ln(alpha) 0.832909 input > exp(ln(beta1)) 2.300000 input > 4 + 4.5 - (34/(8*3+-3)) 6.880952 input > -56 + 2 -54.000000 input > 3 ^ 2 9.000000