6.2 将语法规则合并
最后更新于:2022-04-01 01:10:20
如果语法规则类似的话,可以合并到一个方法中。例如,考虑前面例子中的两个规则:
~~~
def p_expression_plus(p):
'expression : expression PLUS term'
p[0] = p[1] + p[3]
def p_expression_minus(t):
'expression : expression MINUS term'
p[0] = p[1] - p[3]
~~~
比起写两个方法,你可以像下面这样写在一个方法里面:
~~~
def p_expression(p):
'''expression : expression PLUS term
| expression MINUS term'''
if p[2] == '+':
p[0] = p[1] + p[3]
elif p[2] == '-':
p[0] = p[1] - p[3]
~~~
总之,方法的文档字符串可以包含多个语法规则。所以,像这样写也是合法的(尽管可能会引起困惑):
~~~
def p_binary_operators(p):
'''expression : expression PLUS term
| expression MINUS term
term : term TIMES factor
| term DIVIDE factor'''
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]
~~~
如果所有的规则都有相似的结构,那么将语法规则合并才是个不错的注意(比如,产生式的项数相同)。不然,语义动作可能会变得复杂。不过,简单情况下,可以使用`len()`方法区分,比如:
~~~
def p_expressions(p):
'''expression : expression MINUS expression
| MINUS expression'''
if (len(p) == 4):
p[0] = p[1] - p[3]
elif (len(p) == 3):
p[0] = -p[2]
~~~
如果考虑解析的性能,你应该避免像这些例子一样在一个语法规则里面用很多条件来处理。因为,每次检查当前究竟匹配的是哪个语法规则的时候,实际上重复做了分析器已经做过的事(分析器已经准确的知道哪个规则被匹配了)。为每个规则定义单独的方法,可以消除这点开销。