虽然循环实施永远不会以层问题结束



我试图在python 3.8中用ply实现一种小型编程语言,问题是我对while循环的实现永远不会停止,而且似乎p[3]中的条件永远不会更新,这是语句:

def p_statement_if(p):
'''statement : IF LPAREN comparison RPAREN LBRAKET statement RBRAKET
| IF LPAREN comparison RPAREN LBRAKET statement RBRAKET ELSE LBRAKET statement RBRAKET'''
if p[3]:
p[0] = p[6]
else:
if p[10] is not None:
p[0] = p[10]
def p_statement_while(p):
'statement : WHILE LPAREN comparison RPAREN LBRAKET statement RBRAKET'
while(p[3]):
p[0] = p[6]

我的问题是我怎样才能让它始终更新p[3]中的条件?

我的整个代码是这样的:

tokens = (
'NAME','NUMBER',
'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
'LPAREN','RPAREN','LBRAKET','RBRAKET',
'EQUAL','NOTEQ','LARGE','SMALL','LRGEQ','SMLEQ',
'ENDSTM',
)
reserved = {
'while' : 'WHILE',
'if'    : 'IF',
'else'  : 'ELSE',
'print' : "PRINT",
}
tokens += tuple(reserved.values())
# Tokens
t_PLUS    = r'+'
t_MINUS   = r'-'
t_TIMES   = r'*'
t_DIVIDE  = r'/'
t_EQUALS  = r'='
t_LPAREN  = r'('
t_RPAREN  = r')'
t_LBRAKET  = r'{'
t_RBRAKET  = r'}'
t_EQUAL   = r'=='
t_NOTEQ   = r'!='
t_LARGE   = r'>'
t_SMALL   = r'<'
t_LRGEQ   = r'>='
t_SMLEQ   = r'<='
t_ENDSTM  = r';'
def t_NUMBER(t):
r'd+'
t.value = int(t.value)
return t
def t_NAME(t):
r'[a-zA-Z_][a-zA-Z0-9_]*'
if t.value in reserved:
t.type = reserved[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(f"Illegal character {t.value[0]!r}")
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_statement(p):
'statement : statement statement'
def p_statement_assign(p):
'statement : NAME EQUALS expression ENDSTM'
names[p[1]] = p[3]
def p_statement_expr(p):
'statement : expression ENDSTM'
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_comparison_binop(p):
'''comparison : expression EQUAL expression
| expression NOTEQ expression
| expression LARGE expression
| expression SMALL expression
| expression LRGEQ expression
| expression SMLEQ 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]
elif p[2] == '>=':
p[0] = p[1] >= p[3]
elif p[2] == '<=':
p[0] = p[1] <= p[3]
def p_statement_if(p):
'''statement : IF LPAREN comparison RPAREN LBRAKET statement RBRAKET
| IF LPAREN comparison RPAREN LBRAKET statement RBRAKET ELSE LBRAKET statement RBRAKET'''
if p[3]:
p[0] = p[6]
else:
if p[10] is not None:
p[0] = p[10]
def p_statement_while(p):
'statement : WHILE LPAREN comparison RPAREN LBRAKET statement RBRAKET'
while(p[3]):
p[0] = p[6]
def p_statement_print(p):
'statement : PRINT LPAREN expression RPAREN ENDSTM'
print(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_number(p):
'expression : NUMBER'
p[0] = p[1]
def p_expression_name(p):
'expression : NAME'
try:
p[0] = names[p[1]]
except LookupError:
print(f"Undefined name {p[1]!r}")
p[0] = 0
def p_error(p):
try:
print(f"Syntax error at {p.value!r}")
except:
print("Error")
import ply.yacc as yacc
yacc.yacc()
s = open('input.txt','r').read()
yacc.parse(s)

示例输入文件输入.txt如下所示:

a = 7;
b = a * 2;
print(a + b);
if(a<b){
print(a);
}
while(a<b){
a = a + 1;
print(a);
}

我得到了这个输出(永不停止(:

21
7
8

Ply不会改变Python的规则。它解析输入(一次(,生成您选择在解析操作函数中实现的任何结果。就是这样。

因此,很明显,您不能将即时解释器编写为解析规则。执行发生在程序解析之后,程序代码和执行之间没有一对一的关系:一些表达式(如你的while条件(被多次计算;其他表达式(如if-then-else语句的失败分支(根本不计算。调用函数,每次使用不同的参数;编译代码时,无法预测这些参数的值是什么。

编译程序的结果是"可执行文件"。该可执行文件可能是低级机器代码,也可能是程序的一些更高级别描述,用于解释程序在执行时的作用。

如果这一切看起来太过手足无措,我强烈建议你通过Abelson & Sussman的《计算机程序的结构和解释》,由于其作者的慷慨解囊,它可以在线免费阅读,并且在首次出版近40年后,仍然是对计算机程序基础概念的最佳单卷介绍。如果你想写一个编译器(或解释器(,从那里开始。

最新更新