5

我正在尝试实现一个词法分析器来取乐。我已经实现了一个基本的正则表达式匹配器(首先将模式转换为 NFA,然后再转换为 DFA)。现在我对如何继续一无所知。

我的词法分析器将获取令牌列表及其相应的正则表达式。用于创建词法分析器的一般算法是什么?

我考虑过(OR)所有正则表达式,但后来我无法确定匹配哪个特定令牌。即使我扩展我的正则表达式模块以在匹配成功时返回匹配的模式,我如何在匹配器中实现前瞻?

4

2 回答 2

6

假设您有一个有效的正则表达式,regex_match它返回一个布尔值(如果字符串满足正则表达式则为真)。首先,您需要有一个有序的标记列表(每个都带有正则表达式)tokens_regex,顺序很重要,因为顺序将规定优先级

一种算法可能是(这不一定是唯一的)

  1. 编写一个程序next_token,它接受一个字符串,并返回第一个标记、它的值和剩余的字符串(或者 - 如果是非法/忽略字符 - 无,有问题的字符和剩余的字符串)。注意:这必须尊重优先级,并且应该找到最长的标记。
  2. 编写一个lex递归调用的过程next_token

.

像这样的东西(用 Python 编写):

tokens_regex = [ (TOKEN_NAME, TOKEN_REGEX),...] #order describes precedence

def next_token( remaining_string ):
    for t_name, t_regex in tokens_regex: # check over in order of precedence
        for i in xrange( len(remaining_string), 0, -1 ): #check longest possibilities first (there may be a more efficient method).
            if regex_match( remaining_string[:i], t_regex ):
                return t_name, remaining_string[:i], remaining_string[i:]
    return None, remaining_string[0], remaining_string[1:] #either an ignore or illegal character

def lex( string ):
    tokens_so_far = []
    remaining_string = string
    while len(remaining_string) > 0:
        t_name, t_value, string_remaining = next_token(remaining_string)
        if t_name is not None:
            tokens_so_far.append(t_name, t_value)
        #elif not regex_match(t_value,ignore_regex):
            #check against ignore regex, if not in it add to an error list/illegal characters
   return tokens_so_far

添加一些东西来改进你的词法分析器:忽略正则表达式、错误列表和位置/行号(对于这些错误或标记)。

玩得开心!祝你制作解析器好运:)。

于 2012-09-03T20:08:14.863 回答
2

我做了几乎同样的事情。我这样做的方法是将所有表达式组合在一个非常大的 NFA 中,并将相同的东西转换为一个 DFA。这样做时,请跟踪每个相应的原始 DFA 中先前接受状态的状态及其优先级。

生成的 DFA 将有许多接受状态的状态。您运行此 DFA,直到它接收到一个没有相应转换的角色。如果 DFA 处于接受状态,那么您将查看您的哪些原始 NFA 具有该接受状态。具有最高优先级的是您要返回的令牌。

这不处理正则表达式前瞻。无论如何,这些通常并不是词法分析器工作真正需要的。那将是解析器的工作。

这种词法分析器的运行速度与单个正则表达式几乎相同,因为它基本上只有一个 DFA 可以运行。您可以完全省略 NFA 的转换,以获得更快构建但运行更慢的算法。算法基本相同。

我写的词法分析器的源代码可以在 github 上免费获得,如果你想看看我是怎么做到的。

于 2012-09-04T14:10:22.897 回答