Path: blob/main/third_party/ply/example/optcalc/calc.py
7087 views
# -----------------------------------------------------------------------------1# calc.py2#3# A simple calculator with variables. This is from O'Reilly's4# "Lex and Yacc", p. 63.5# -----------------------------------------------------------------------------67import sys8sys.path.insert(0,"../..")910if sys.version_info[0] >= 3:11raw_input = input1213tokens = (14'NAME','NUMBER',15'PLUS','MINUS','TIMES','DIVIDE','EQUALS',16'LPAREN','RPAREN',17)1819# Tokens2021t_PLUS = r'\+'22t_MINUS = r'-'23t_TIMES = r'\*'24t_DIVIDE = r'/'25t_EQUALS = r'='26t_LPAREN = r'\('27t_RPAREN = r'\)'28t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'2930def t_NUMBER(t):31r'\d+'32try:33t.value = int(t.value)34except ValueError:35print("Integer value too large %s" % t.value)36t.value = 037return t3839t_ignore = " \t"4041def t_newline(t):42r'\n+'43t.lexer.lineno += t.value.count("\n")4445def t_error(t):46print("Illegal character '%s'" % t.value[0])47t.lexer.skip(1)4849# Build the lexer50import ply.lex as lex51lex.lex(optimize=1)5253# Parsing rules5455precedence = (56('left','PLUS','MINUS'),57('left','TIMES','DIVIDE'),58('right','UMINUS'),59)6061# dictionary of names62names = { }6364def p_statement_assign(t):65'statement : NAME EQUALS expression'66names[t[1]] = t[3]6768def p_statement_expr(t):69'statement : expression'70print(t[1])7172def p_expression_binop(t):73'''expression : expression PLUS expression74| expression MINUS expression75| expression TIMES expression76| expression DIVIDE expression'''77if t[2] == '+' : t[0] = t[1] + t[3]78elif t[2] == '-': t[0] = t[1] - t[3]79elif t[2] == '*': t[0] = t[1] * t[3]80elif t[2] == '/': t[0] = t[1] / t[3]81elif t[2] == '<': t[0] = t[1] < t[3]8283def p_expression_uminus(t):84'expression : MINUS expression %prec UMINUS'85t[0] = -t[2]8687def p_expression_group(t):88'expression : LPAREN expression RPAREN'89t[0] = t[2]9091def p_expression_number(t):92'expression : NUMBER'93t[0] = t[1]9495def p_expression_name(t):96'expression : NAME'97try:98t[0] = names[t[1]]99except LookupError:100print("Undefined name '%s'" % t[1])101t[0] = 0102103def p_error(t):104if t:105print("Syntax error at '%s'" % t.value)106else:107print("Syntax error at EOF")108109import ply.yacc as yacc110yacc.yacc(optimize=1)111112while 1:113try:114s = raw_input('calc > ')115except EOFError:116break117yacc.parse(s)118119120121