use*_*915 6 c regex compiler-construction lexical-analysis flex-lexer
我正在尝试为编译器创建一个词法分析器。但是我在使用正则表达式来查找关键字和实数之类的东西时遇到了问题.. 例如一些定义:
id [aA-zZ][aA-zZ-0-9_]*
keyword if|else|when|while
integer [0-9]+
real integer\.integer
Run Code Online (Sandbox Code Playgroud)
..虽然有一些问题,但分析器无法获取关键字,例如,如果我给出“else”这个词,它会将其视为 id(我收到一条警告,例如规则也无法匹配。
此外,如果我尝试给出一个实数,例如 1.2,链接器会将其视为整数分隔符整数而不是实数。不过,我不擅长正则表达式语言,..我想为实数/整数区别放置一个规则,例如(“读取一个不以 . 结尾的数字,它是一个整数,否则它是一个数字”)但是我怎么能把它放在 reg. 语。
Flex 未检测到所需字符串的原因是在读取输入时存在歧义。单词“else”对应于正则表达式“else”和 [a-zA-Z][a-zA-Z0-9]*,但最后一个是最先写入的,因此 Flex 决定输入必须符合此正则表达式。
Flex 是一个词法分析器,它读取输入文件并使用您希望它检查的任何正则表达式检查当前字符串。您必须始终记住驱动其字符串匹配系统的两个基本规则:
“最长最佳匹配”告诉 Flex 读取输入必须匹配尽可能长的模式;LBM 规则优先使用效果更好。
优先级规则告诉 Flex,如果输入匹配多个正则表达式,则只需要考虑第一个。
在编写代码时,关键字必须被视为关键字而不是 ID,那么您应该在其他任何事情之前编写关键字的正则表达式:如果某些内容与“关键字”正则表达式不匹配,则意味着我们正在阅读其他内容,例如 id 或函数的名称。
我会写这样的东西:
keyword "if"|"else"|"when"|"while"
id [a-zA-Z][a-zA-Z0-9_-]*
nat [0-9]|([1-9][0-9]*)
integer [+|-]*{nat}
real {integer}[.]{integer}
Run Code Online (Sandbox Code Playgroud)
关键字优先;如果我们没有读取关键字,它可能是一个 id;如果只有数字,让我们看看它是一个什么样的数字。优先级规则将让 Flex 将 'else'、'if' 和其他关键字读取为 'keyword' 标记,而最长的最佳匹配将确保像 1.2 这样的数字将被视为一个 'real' 而不是两个由点分隔的 'nat' .
当同一词位可以与多个规则匹配时,lex 将选择文件中第一个出现的规则。因此,关键字规则必须位于标识符规则之前。
该规则的问题integer.integer不在于它无法与整数规则消除歧义 - 事实上它可以简单地消除歧义,因为根本没有重叠。问题在于它匹配字符串“integer”,后跟任何字符,后跟字符串“integer”。您不能在规则内引用其他规则。您可以使用花括号创建定义和引用,也可以只编写[0-9]+ '.' [0-9]+.