提问人:FoxH Gaming 提问时间:7/6/2023 最后编辑:FoxH Gaming 更新时间:7/6/2023 访问量:100
我在 Python 中使用 PLY 创建词法分析器时遇到问题
I'm having a problem with creating a lexer using PLY in Python
问:
我最近试图创建一个 Lexer,但效果不佳。
问题是它抛出一条错误消息,显示“无法构建词法分析器”。以下是回溯:
ERROR: Rule 't_TIMES' defined for an unspecified token TIMES
ERROR: Rule 't_DIVIDE' defined for an unspecified token DIVIDE
Traceback (most recent call last):
File "...\Lexer.py", line 24, in <module>
lexer = lex.lex()
^^^^^^^^^
File "...\lex.py", line 910, in lex
raise SyntaxError("Can't build lexer")
SyntaxError: Can't build lexer
我知道这是因为我的功能。我也感觉到我制作的令牌可能有问题。请帮帮我,我知道这有点愚蠢,但我是新来的,所以请对我好一点。
顺便说一句,这是源代码t_error()
import ply.lex as lex
import ply.yacc as yacc
import sys
tokens = [
"INT",
"ID",
"PLUS",
"MINUS",
"EOF",
]
t_INT = r"\d+"
t_ID = r"[a-zA-Z_][a-zA-Z0-9_]*"
t_PLUS = r"+"
t_MINUS = r"-"
t_TIMES = r"*"
t_DIVIDE = r"/"
def t_error(t):
print("Illegal character '%s'" % t.lexer.lexeme, file=sys.stderr)
lexer = lex.lex()
def p_expression(p):
"""expression : INT
| ID
| expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression"""
if len(p) == 2:
if isinstance(p[1], int):
p[0] = p[1]
elif isinstance(p[1], str):
p[0] = p[1]
else:
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]
parser = yacc.yacc()
def test(text):
try:
result = parser.parse(text)
if result:
print(result)
else:
print("Empty expression")
except yacc.YaccError:
print("Error parsing input")
if __name__ == "__main__":
test("123")
test("hello")
test("123 + 456")
test("123 - 456")
test("123 * 456")
test("123 / 456")
也许我只是愚蠢,但正因为如此,所以我无法让它跑。
答:
1赞
larsks
7/6/2023
#1
这些错误...
ERROR: Rule 't_TIMES' defined for an unspecified token TIMES
ERROR: Rule 't_DIVIDE' defined for an unspecified token DIVIDE
...似乎很清楚。您尚未定义名为 或 在数组中命名的令牌。你需要:TIMES
DIVIDE
tokens
tokens = [
"INT",
"ID",
"PLUS",
"MINUS",
"EOF",
"TIMES",
"DIVIDE",
]
修复这些错误后,您将获得:
ERROR: Invalid regular expression for rule 't_PLUS'. nothing to repeat at position 11
ERROR: Invalid regular expression for rule 't_TIMES'. nothing to repeat at position 12
这是因为字符 和 都是正则表达式通配符,所以如果你想要文字字符,你需要对它们进行转义:+
*
t_PLUS = r"\+"
t_TIMES = r"\*"
修复这些错误后,最终将从方法中得到以下信息:t_error
AttributeError: 'Lexer' object has no attribute 'lexeme'. Did you mean: 'lexre'?
似乎没有属性,但您可以使用:lexeme
t.value
def t_error(t):
print("Illegal character '%s'" % t.value, file=sys.stderr)
修复该错误后,您现在将获得:
123
hello
Illegal character ' + 456'
.
.
.
ply.lex.LexError: Scanning error. Illegal character ' '
你的表达式中有空格,但你没有在规则中考虑到这一点。快速解决方法是删除测试表达式中的空格:
if __name__ == "__main__":
test("123")
test("hello")
test("123+456")
test("123-456")
test("123*456")
test("123/456")
修复该错误后,您现在将获得:
123
hello
123456
.
.
.
TypeError: unsupported operand type(s) for -: 'str' and 'str'
这是因为您正在尝试在方法中添加字符串值。在应用算术运算符之前,您需要将它们转换为数字。最简单的解决方案是用这种方法替换你的定义:p_expression
t_INT
def t_INT(t):
r'\d+'
t.value = int(t.value)
return t
现在运行代码会产生:
123
hello
579
-333
56088
0.26973684210526316
评论