繁体   English   中英

我的词法分析器很困难

[英]Difficulty with my lexical analyzer

我正在尝试将词法分析器编程为标准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. 运算符-(将具有包含“ +”,“-” ....的符号表)

分析仪的输入是字节/ 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个字符后,它会接受标识符令牌([a-zA-Z] [a-zA -Z0-9] *)。

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

我正在尝试考虑一种新算法,但是我一直失败。 有什么建议么?

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

当您拥有完整的令牌时,请在关键字表中查找它,如果找到它,则将其指定为关键字,如果找不到它,则将其指定为标识符。 这立即解决了intx问题。 扫描程序将读取intx ,它不是关键字,因此它必须是标识符。

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

令牌生成器通常首先根据指示令牌结束构成的规则将输入流分成令牌,然后稍后再确定它是哪种令牌(否则将产生错误)。 令牌的典型结尾是诸如空格(不属于文字字符串的一部分),运算符,特殊分隔符等内容。

看来您缺少竞争性DFA的greediness感。 greedy匹配通常是最有用的(最左最长的匹配),因为它解决了如何在竞争DFA之间进行选择的问题。 匹配int之后,IDENTIFIER DFA intx有另一个节点前进到intx 您的最终自动机只有在达到无法消耗的容量时才会退出,并且如果在输入结束时或在另一个DFA接受时未处于有效的接受状态,则会对其进行修剪,而另一个DFA已匹配。

例如,Flex默认为贪婪匹配。

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

如果您有2条竞争int规则

  1. 规则1是令牌“ int”
  2. 规则2是IDENTIFIER

当我们到达

i n t

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

i n t x

如果此时规则2处于ACCEPT状态,则定义将规则1丢弃。 但是,如果规则2仍未处于ACCEPT状态,则在检查更多输入以查看是否最终可以达到规则2中比规则1长的ACCEPT状态时,我们必须保留规则1。如果我们收到其他匹配的字符这两个规则都不行,我们检查规则2自动机是否对intx处于ACCEPT状态,如果是,则为匹配。 如果不是,则将其丢弃,并接受最长的先前匹配项(规则1),但是在这种情况下,规则2处于接受状态并匹配intx

如果两个规则同时达到接受或退出状态,则使用优先级(规则在语法中的顺序)。 通常,您将关键字放在第一位,因此IDENTIFIER不匹配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM