Search code examples
pythonyaccply

PLY YACC pythonic syntax for accumulating list of comma-separated values


I'm using YACC for the first time and getting used to using BNF grammar.

I'm currently building a list of types from a comma separated list (eg. int, float, string):

def p_type(p):
    '''type : primitive_type
            | array
            | generic_type
            | ID'''
    p[0] = p[1]


def p_type_list(p):
    '''type_list : type
                 | type COMMA type_list'''
    if not isinstance(p[0], list):
        p[0] = list()
    p[0].append(p[1])
    if len(p) == 4:
        p[0] += p[3]

The rules work, but I'm getting the sense that my p_type_list logic is a bit of a kludge and could be simplified into a one-liner.

I haven't found any PLY specific examples of this online. Any help would be greatly appreciated!


Solution

  • There are two productions. Use two separate functions. (There is no extra cost :-) )

    def p_type_list_1(p):
        '''type_list : type'''
        p[0] = [p[1]]
    
    def p_type_list_2(p):
        '''type_list : type_list COMMA type'''
        p[0] = p[1] + [p[3]]
    

    Note: I fixed your grammar to use left-recursion. With bottom-up parsing, left-recursion is almost always what you want, because it avoids unnecessary parser stack usage, and more importantly because it often simplifies actions. In this case, I could have written the second function as:

    def p_type_list_2(p):
        '''type_list : type_list COMMA type'''
        p[0] = p[1]
        p[0] += [p[3]]
    

    which avoids a list copy.