我的词法分析器很难

时间:2014-10-16 00:57:51

标签: c regex compiler-construction lexical-analysis

我正在尝试将词法分析器编程为标准C转换单元,因此我将可能的标记分为6组;对于每个组,都有一个正则表达式,它将转换为DFA:

  1. 关键字 - (将有一个包含“goto”,“int”的符号表....)

  2. 识别 - [a-zA-z] [a-zA-Z0-9] *

  3. 数字常数 - [0-9] + /。?[0-9] *

  4. 字符串常量 - “”[EVERY_ASCII_CHARACTER] *“”

  5. 特殊符号 - (将有一个符号表,其中包含“;”,“(”,“{”....)

  6. 运算符 - (将包含一个包含“+”,“ - ”的符号表。)

  7. 我的分析器输入是一个字节/ ASCII字符流。我的算法如下:

    assuming there's a stream of characters, x1...xN
     foreach i=1, i<=n, i++
        if x1...xI accepts one or more of the 6 group's DFA
        {
           take the longest-token
           add x1...xI to token-linked-list
           delete x1...xI from input
        }
    

    但是,该算法假定它给出的每个字节(字母)都是一个标识符,因为在输入1个字符后,它接受标识符标记的DFA([a-zA-Z] [ A-ZA-Z0-9] *)。

    另一个可能的问题是对于输入“intx;”,我的算法会将此流标记为“int”,“x”,“;”这当然是一个错误。

    我正在考虑一种新的算法,但我一直都在失败。有什么建议吗?

3 个答案:

答案 0 :(得分:2)

对扫描仪进行编码,使其在读取完成之前将标识符和关键字视为相同。

如果您拥有完整的令牌,请在关键字表格中查找,如果找到则将其指定为关键字,如果找不到,则将其指定为标识符。这会立即处理intx问题;扫描程序读取intx并且该关键字不是关键字,因此它必须是标识符。

我注意到您的标识符不允许使用下划线。这不一定是个问题,但许多语言都允许标识符中的下划线。

答案 1 :(得分:1)

Tokenizers通常首先根据规定什么构成令牌END的规则将输入流拆分为令牌,然后才决定它是什么类型的令牌(否则就是错误)。令牌的典型结束是像空格(当不是文字字符串的一部分),运算符,特殊分隔符等等。

答案 2 :(得分:1)

您似乎错过了竞争DFA的greediness方面。 greedy匹配通常是最有用的(最左边最长匹配),因为它解决了如何在竞争DFA之间进行选择的问题。与int匹配后,IDENTIFIER DFA中的另一个节点会前进到intx。你的finate自动机不会退出,直到它达到它无法消耗的东西,如果它在输入结束时没有处于有效的接受状态,或者在另一个DFA正在接受的点上,它被修剪,其他DFA匹配。

例如,

Flex默认为贪婪匹配。

换句话说,您提出的问题intx不是问题...

如果您有2条竞争int

的规则
  1. 规则1是令牌&#34; int&#34;
  2. 规则2是IDENTIFIER
  3. 当我们到达时

    i n t

    我们不会立即接受int因为我们看到另一条规则(规则2),其中进一步输入x将自动机进展到NEXT状态:

    i n t x

    如果规则2在该点处于ACCEPT状态,则根据定义丢弃规则1。但是,如果规则2仍未处于ACCEPT状态,我们必须保持规则1,同时我们检查更多输入以查看我们是否最终可以在规则2中达到比规则1更长的ACCEPT状态。如果我们收到一些匹配的其他字符既不是规则,我们检查规则2自动机是否处于intx的ACCEPT状态,如果是,则匹配。如果没有,则将其丢弃,并接受最长的先前匹配(规则1),但在这种情况下,规则2处于ACCEPT状态并匹配intx

    如果2个规则同时达到ACCEPT或EXIT状态,则使用优先级(语法中规则的顺序)。通常,您将关键字放在首位,以便IDENTIFIER首先匹配。