虽然循环实现永远不会在 Ply 问题中结束
While cycle implementation never ends in Ply issue
我试图在 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)
示例输入文件 input.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 的计算机程序的结构和解释,这可以是read for free on-line 由于其作者的慷慨,在首次出版近 40 年后,它仍然是 概念 基础计算机程序的最佳单卷介绍。如果你想写一个编译器(或解释器),从这里开始。
我试图在 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)
示例输入文件 input.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 的计算机程序的结构和解释,这可以是read for free on-line 由于其作者的慷慨,在首次出版近 40 年后,它仍然是 概念 基础计算机程序的最佳单卷介绍。如果你想写一个编译器(或解释器),从这里开始。