如何在 lex 中创建没有特定字母组的正则表达式

How to create a regex without certain group of letters in lex

我最近开始学习 lex ,所以我在练习并决定制作一个程序来识别普通变量的声明。 (有点)

这是我的代码:

%{
#include "stdio.h"
%}
dataType "int"|"float"|"char"|"String"
alphaNumeric [_\*a-zA-Z][0-9]*
space [ ]
variable {dataType}{space}{alphaNumeric}+
%option noyywrap
%%
{variable} printf("ok");
. printf("incorect");
%%
int main(){
yylex();
}

某些情况下输出应该return ok

int var3
int _varR3
int _AA3_

如果我输入: int float ,它是 returns ok ,这是错误的,因为它们都是保留字。

所以我的问题是我应该修改什么才能使我的表达式忽略 space 之后的 'dataType' 个词?

谢谢。

这确实不是解决这个特定问题的方法。

通常的做法是编写单独的模式规则来识别关键字和变量名。 (加上忽略白色的模式规则space。)这意味着分词器将为输入 return 两个标记 int var3。识别这两个标记是有效声明是解析器的责任,解析器将重复调用标记器以解析标记流。

不过,如果你真的想把两个单词识别为一个标记,那当然是可以的。 (F)lex 不允许在正则表达式中使用负先行,但您可以使用模式匹配优先规则来捕获错误的标记。

例如,您可以这样做:

dataType       int|float|char|String
id             [[:alpha:]_][[:alnum:]_]*

%%

{dataType}[[:white:]]+{dataType}   { puts("Error: two types"); }
{dataType}[[:white:]]+{id}         { puts("Valid declaration"); }

  /* ...  more rules ... */

上面使用Posix字符classes而不是写出可能的字符。有关 Posix 个字符 class 的列表,请参阅 man isalpha;字符 class 组件 [:xxxxx:] 完全包含 isxxxxx 标准库函数接受的字符。我修复了模式,以便在 dataTypeid 之间允许多个 space,并简化了 ids.

的模式

初步考虑:通常,检测您指出的结构不是在词法分析阶段完成的,而是在解析阶段完成的。例如,在 yacc/bison 上,您的规则只匹配 "type" 标记后跟 "identifier" 标记。

不过,要使用 lex/flex 实现这一点,您可以考虑使用否定 (^) 和尾随上下文 (/) 运算符。或者...

如果您是 运行 灵活的,也许只需用括号将所有正则表达式括起来并传递 -l 标志就可以了。请注意 lex 和 flex 之间存在一些差异,如 the Flex manual.

中所述