我在读第一个例子
它是一个基本的计算器,只允许表达式涉及'(',')','+','-','*','/'
、整数和赋值(例如x=3
),并抛出表达式的求值(即使它的结果不是整数,例如'3/4'
)。在
我希望允许使用浮点数,因此我基本上修改了示例中的代码,如下所示,但它不起作用:
# -----------------------------------------------------------------------------
# calc.py
#
# A simple calculator with variables.
# -----------------------------------------------------------------------------
tokens = (
'NAME','INTEGER', 'FLOAT',
'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
'LPAREN','RPAREN',
)
# Tokens
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_EQUALS = r'='
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
def t_INTEGER(t):
r'\d+'
t.value = int(t.value)
return t
def t_FLOAT(t):
r'/^(?!0\d)\d*(\.\d+)?$/mg'
t.value = float(t.value)
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)
# Build the lexer
import ply.lex as lex
lex.lex()
# Precedence rules for the arithmetic operators
precedence = (
('left','PLUS','MINUS'),
('left','TIMES','DIVIDE'),
('right','UMINUS'),
)
# dictionary of names (for storing variables)
names = { }
def p_statement_assign(p):
'statement : NAME EQUALS expression'
names[p[1]] = p[3]
def p_statement_expr(p):
'statement : expression'
print(p[1])
def p_expression_binop(p):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression'''
if 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_expression_uminus(p):
'expression : MINUS expression %prec UMINUS'
p[0] = -p[2]
def p_expression_group(p):
'expression : LPAREN expression RPAREN'
p[0] = p[2]
def p_expression_integer(p):
'expression : INTEGER'
p[0] = p[1]
def p_expression_float(p):
'expression : FLOAT'
p[0] = p[1]
def p_expression_name(p):
'expression : NAME'
try:
p[0] = names[p[1]]
except LookupError:
print("Undefined name '%s'" % p[1])
p[0] = 0
def p_error(p):
print("Syntax error at '%s'" % p.value)
import ply.yacc as yacc
yacc.yacc()
while True:
try:
s = input('calc > ')
except EOFError:
break
yacc.parse(s)
我有错误:
^{pr2}$
ply按照声明的顺序解析
T_xxx
成员(使用模块上的反射)。这里发生的是T_INTEGER
在T_FLOAT
之前匹配。所以浮点的整数部分被解析,然后ply
在点上阻塞。在如果您的regex for floats没有关闭(在我的第一个回答中完全忽略了这一点,被明显的错误顺序蒙蔽了双眼),这将直接起作用。在
我已经把它简化为}不匹配,所以不是最佳选择),但是您可以从类似的问题中借用一个更好的版本:PLY lexer for numbers always returns double
\d+\.\d+
(这与1.
或{您必须在
T_INTEGER
之前对T_FLOAT
进行解析。只需交换两个声明即可:作为
ply
的一般规则,对于比其他模式更长/更具体的所有模式都要这样做,以避免冲突。在你的lex文件有两个问题。首先是令牌顺序,正如Jean-francois所解释的:较长的令牌必须首先在lex中定义(来自ply doc.):
但是定义令牌的字符串应该是
re
兼容的字符串。你的浮动定义在这里被严重破坏了。如果我们定义一个由一个点组成的浮点数,以及该点之前或之后的可选数字,而不是一个单独的点,则可接受的定义可以是:尤其是,斜杠
/
不应包括在字符串中。。。在相关问题 更多 >
编程相关推荐