代码之家  ›  专栏  ›  技术社区  ›  LB40

为一个带PLY的解析器准备几个lexer?

  •  2
  • LB40  · 技术社区  · 15 年前

    有一个名为source的关键字执行包含,所以我要做的是,当lexer遇到这个关键字时,我更改lexer状态以创建一个新的lexer,该lexer将对源文件进行lex:

    def t_begin_source(t):
        r'source '
        t.lexer.begin('source')
    
    def t_source_path(t):
        r'[^\n]+\n+'
        t.lexer.begin('INITIAL') 
        global path
        source_lexer = lex.lex(errorlog=lex.NullLogger())
        source_file_name = (path +  t.value.strip(' \"\n')) 
        sourced_file = file(path + t.value.strip(' \"\n')).read()
    
        source_lexer.input(sourced_file)
    
        while True:
            tok = source_lexer.token()
            if not tok:
                break
    

    lexer = lex.lex(errorlog=lex.NullLogger()) 
    

    这是解析器将要调用的“main”或“root”词法分析器。

    我的问题是,我不知道如何告诉解析器使用不同的lexer,或者告诉“source-lexer”返回一些东西。。。

    也许应该使用克隆函数。。。

    谢谢

    3 回复  |  直到 15 年前
        1
  •  2
  •   Ned Batchelder    15 年前

    我不知道PLY的细节,但是在我构建的其他系统中,使用一个lexer来管理include文件堆栈是最有意义的。因此lexer将返回一个统一的令牌流,打开和关闭遇到的include文件。

        2
  •  2
  •   quark    15 年前

    一个有趣的巧合是,一个来自同一个谷歌搜索的链接让我想到了这个问题,它解释了如何 write your own lexer for a PLY parser . 这篇文章解释得很简单,但是它是由四个实例变量和一个 token 方法。

        3
  •  0
  •   LB40    15 年前

    好 啊,

    解析器不再调用lexer,因为在调用parse函数时,可以使用tokenfunc参数重写解析器使用的getToken函数。

    result = yacc.parse(kconfig,debug=1,tokenfunc=my_function)
    

    而我的函数现在是调用以获取下一个令牌的函数,它在先前构建的令牌列表上迭代。

    考虑到词法,当我遇到源关键字时,我克隆我的词表,并改变输入以包含文件。

    def sourcing_file(source_file_name):
        print "SOURCE FILE NAME " , source_file_name
        sourced_file = file(source_file_name).read()
        source_lexer = lexer.clone()
        source_lexer.input(sourced_file)
        print 'END OF SOURCING FILE'
    
        while True:
            tok = source_lexer.token()
            if not tok:
                break
            token_list.append(tok)