Lex / Flex 中的起始状态

6
我正在使用Flex和Bison作为解析器生成器,但是我的扫描器中的起始状态存在问题。
我正在使用排他规则来处理注释,但是该语法似乎无法匹配引用标记:
%x COMMENT

//                    { BEGIN(COMMENT); }
<COMMENT>[^\n]        ;
<COMMENT>\n           { BEGIN(INITIAL); }

"=="                  { return EQUALEQUAL; }

.                     ;

在这个简单的例子中,这行代码是:

// a == b

如果不包含以下规则,该注释将无法完全匹配:

<COMMENT>"=="             ;

我该如何解决这个问题,而不必将所有这些令牌添加到我的独占规则中?
3个回答

10

在Lex/Flex或其他地方匹配C风格的注释有很好的文档记录:

文档中详细介绍了这个过程,同时互联网上也有各种变体。

下面是在Flex文档中找到的一个变体:

   <INITIAL>{
     "//"              BEGIN(IN_COMMENT);
     }
     <IN_COMMENT>{
     \n      BEGIN(INITIAL);
     [^\n]+    // eat comment
     "/"       // eat the lone /
     }

如果可以避免的话,我宁愿不使用包容状态,因为我有很多规则。问题是这个“吃掉注释”的规则似乎无法匹配具有多个字符(例如==)的标记。 - Dan
那么我认为你可能做错了一些事情。你需要为注释创建一个“子解析器”,它不匹配你的正常标记。 - Aiden Bell
假设你想要储存每个输入行,那么这样做会给你错误的行号吗? - Don Code
@DonCode 如果我没记错,yylineno会给出正确的行数,无论BEGIN "blocks"如何,你可以将其传递给Bison或其他工具。 - Aiden Bell

2
尝试在 [^n] 规则后添加 "+"。我不知道为什么排除状态仍然会在排除状态下匹配“==”,但显然是这样的。Flex通常会匹配最多文本的规则,添加“+”至少会使两个规则的长度相等。将 COMMENT 规则放在首位将导致它在存在平局时被使用。

0

提示是:

问题在于这个“吃掉注释”的规则似乎无法匹配多于一个字符的标记

因此,添加*以匹配零个或多个非换行符。否则,空注释将不匹配。

%x COMMENT

//                    { BEGIN(COMMENT); }
<COMMENT>[^\n]*        ;
<COMMENT>\n           { BEGIN(INITIAL); }

"=="                  { return EQUALEQUAL; }

.                     ;

一个空的注释也不会触发该规则的匹配,也不需要这样做。 - Darryl
正确,没错,下面的那一行就捕获到它了。所以你可以放心把 * 改为 +。 - Simeon Pilgrim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接