Python 考虑到'|';?(Ply/Yacc)
考虑到以下语法:Python 考虑到'|';?(Ply/Yacc),python,abstract-syntax-tree,yacc,ply,Python,Abstract Syntax Tree,Yacc,Ply,考虑到以下语法: expr : expr '+' term | expr '-' term | term term : term '*' factor | term '/' factor | factor factor : '(' expr ')' | identifier | number 这是我使用ply的代码: from ply import lex, yacc tokens = [ "identifier", "number", "plus", "mi
expr : expr '+' term | expr '-' term | term
term : term '*' factor | term '/' factor | factor
factor : '(' expr ')' | identifier | number
这是我使用ply的代码:
from ply import lex, yacc
tokens = [
"identifier",
"number",
"plus",
"minus",
"mult",
"div"
]
t_ignore = r" \t"
t_identifier = r"^[a-zA-Z]+$"
t_number = r"[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?"
t_plus = r"\+"
t_minus = r"-"
t_mult = r"\*"
t_div = r"/"
def p_stmt(p):
"""stmt : expr"""
p[0] = ("stmt", p[1])
def p_expr(p):
"""expr : expr plus term
| expr minus term
| term"""
p[0] = ("expr", p[1], p[2]) # Problem here <<<
def p_term(p):
"""term : term mult factor
| term div factor
| factor"""
def p_factor(p):
"""factor : '(' expr ')'
| identifier
| number"""
if __name__ == "__main__":
lex.lex()
yacc.yacc()
data = "32 + 10"
result = yacc.parse(data)
print(result)
来自ply import lex,yacc
代币=[
“标识符”,
“数字”,
“加”,
“负”,
“骡子”,
“部门”
]
t_ignore=r“\t”
t_identifier=r“^[a-zA-Z]+$”
t\U编号=r“[+-]?(\d+(\.\d*)?\.\d+([eE][+-]?\d+)?”
t\u plus=r“\+”
t_减=r“-”
t\u mult=r“\*”
t_div=r/“
def p_stmt(p):
“”“stmt:expr”“”
p[0]=(“stmt”,p[1])
def p_expr(p):
“”“expr:expr+term
|表达式负项
|术语“”
p[0]=“expr”,p[1],p[2])#这里的问题据我所见,在p[0]=“expr,p[1],p[2])
,p[1]
将是左手表达式,p[2]
将是运算符,p[3]
(您没有使用)将是右手项
只需使用p[2]
来确定操作员,添加p[3]
,因为您需要它,您应该可以随时使用
此外,您必须验证p
有多少项,因为如果最后一条规则,|term”“
匹配,p
将只有两项而不是四项
请看一段来自
问题是,当我使用P[3 ]时,我得到一个列表索引超出范围。操作符没有被考虑。在PDF中,我已经链接了,他们明确地保存了操作符:(+,p(1),p(2))。问题是,它可以是任何操作符,我需要考虑优先权。噢,对。肯定是因为最后一行,<代码>名词“”。
:当最后一条规则匹配时,p
将只有两项而不是四项。这很奇怪,因为“32+10”应该匹配“expr+term”,因为expr和term最终都是一个数字。首先,是的,但请注意规则是递归的,因此将再次匹配与最后一条规则匹配的“32”。我建议在函数的开头放一个断点或一个日志,这样你就可以更好地理解我的意思了。。。我看到了递归的结束(如此明显,不知何故我忘记了那里的基本原理)。非常感谢。我不明白你为什么因为优先权而觉得“不能分离功能”。优先权没有问题。你没有使用优先权,真的;语法是明确的,运算符优先级是语法中固有的。在两个不同的动作函数之间划分一个非终结符不会改变语法,并产生更简单的动作。
def p_comparison(p):
"""comparison : comparison PLUS comparison
| comparison MINUS comparison
| comparison MULT comparison
| comparison DIV comparison
| comparison LT comparison
| comparison EQ comparison
| comparison GT comparison
| PLUS comparison
| MINUS comparison
| power"""
if len(p) == 4:
p[0] = binary_ops[p[2]]((p[1], p[3]))
elif len(p) == 3:
p[0] = unary_ops[p[1]](p[2])
else:
p[0] = p[1]