在Python中实现可定制的Lexer类

在Python中实现可定制的Lexer类,python,parsing,lexical-analysis,Python,Parsing,Lexical Analysis,我想实现一个可定制和可扩展的lexer类 我的想法 2种不同类型的处理程序: 字符集处理程序 函数处理程序 当一个字符被读取时,它会被推送到所有注册到lexer的处理程序中。一旦处理程序匹配并返回有效令牌,就会返回该令牌。当没有处理程序匹配该字符时,将调用最坏情况下的函数,如果该函数未返回有效标记,则将读取下一个字符并递归执行 字符集处理程序由一个字符串和一个带有三个参数的函数组成。该字符串表示一组字符,当当前解析的字符包含在该字符串中时,将导致调用该函数。当函数无法创建以下字符的标记时,它可能

我想实现一个可定制和可扩展的lexer类

我的想法

2种不同类型的处理程序:

字符集处理程序 函数处理程序 当一个字符被读取时,它会被推送到所有注册到lexer的处理程序中。一旦处理程序匹配并返回有效令牌,就会返回该令牌。当没有处理程序匹配该字符时,将调用最坏情况下的函数,如果该函数未返回有效标记,则将读取下一个字符并递归执行

字符集处理程序由一个字符串和一个带有三个参数的函数组成。该字符串表示一组字符,当当前解析的字符包含在该字符串中时,将导致调用该函数。当函数无法创建以下字符的标记时,它可能返回None。如果无法处理所有正在读取的字符,则函数必须将其推回,以便创建令牌。下一次调用scanner.read_next_char时,将返回推回到扫描仪的字符,这样可以读取输入的字节流,就像函数从未接触过扫描仪一样

函数处理程序是一个包含三个参数的函数,如果它无法创建一个有效的令牌,并且该令牌后面的字符是调用该处理程序的字符,则该函数将返回一个有效令牌或无,就像与上面的字符集相关联的函数一样

当没有处理程序能够从当前标记创建有效标记时,将调用最坏情况下的函数,该标记包含以下字符并遵循上述模式

每个处理程序都有三个参数,lexer本身、lexer用来读取以下字符的扫描器以及实际调用处理程序的当前字符

Lexer本身和处理程序是分开的

class LexingRules(object):

    def __init__(self):
        self.charset_handlers  = []
        self.function_handlers = []
        self.worst_case        = None

    # convenient methods for adding handlers

class Lexer(object):

    def __init__(self, scanner, rules):
        self.scanner = scanner
        self.rules   = rules
        self.current_token = None
        self.read_next_token()

    def read_next_token(self):
        current_char = self.scanner.current_char

        for charset, handler in self.rules.charset_handlers:
            if current_char in charset:
                token = handler(self, self.scanner, current_char)
                if isinstance(token, Token):
                    self.current_token = token
                    return token
        for function in self.rules.function_handlers:
            token = function(self, self.scanner, current_char)
            if isinstance(token, Token):
                self.current_token = token
                return token
        if self.rules.worst_case:
            token = self.rules.worst_case(self, self.scanner, current_char)
            if isinstance(token, Token):
                self.current_token = token
                return token

        self.scanner.read()
        return self.read_next_token()
一个可能的LexingRules子类

目的

基本Lexer实现和硬编码Lexing操作的分离

我目前正处于我自己项目的开始阶段。我想创建一种可扩展的编译/翻译语言。应该可以创建语法和语句扩展等

问题


您对lexer的设计有何看法?您是否有什么可抱怨的,或者有什么想法可以改进它,增加更多功能?

这看起来像是大规模的过度工程。。。你想做什么?只是添加了一个小的编辑,基本Lexer实现和硬编码Lexing操作的分离。。我的新语言的语言扩展应该不仅能够创建新语句,甚至实现新类型的标记,因此语法将被扩展解析并转换为AST。@delnan忘记了@stuff..@NiklasR:1从不在注释中添加关键事实。你的目标应该是第一个,而不是最后一个。然后,您可以删除这两个无用的注释,因为它们现在被放在您的问题的显著位置。2您熟悉哪些现有的Python lexer?你应该在你的问题中提到它们。帘布层相当好,目前尚不清楚这如何可能改善帘布层。
import string
class MyLexingRules(LexingRules):

    def __init__(self):
        super(MyLexingRules, self).__init__()
        self.charset_handlers.append(string.ascii_letters, self.handle_letters)

    def handle_letters(self, lexer, scanner, char):
        tkn = ''
        while scanner.current_char in string.ascii_letters:
            tkn += scanner.current_char
            scanner.read()
        return Token(tkn, TOKEN_ID_IDENTIFIER)