6.2 将语法规则合并

如果语法规则类似的话,可以合并到一个方法中。例如,考虑前面例子中的两个规则:

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]

如果考虑解析的性能,你应该避免像这些例子一样在一个语法规则里面用很多条件来处理。因为,每次检查当前究竟匹配的是哪个语法规则的时候,实际上重复做了分析器已经做过的事(分析器已经准确的知道哪个规则被匹配了)。为每个规则定义单独的方法,可以消除这点开销。

文章导航