C++ 莱克斯项目赢得';当使用或陈述时,不要识别单词
我正在运行以下lex程序,该程序可以很好地识别关于猫的句子:C++ 莱克斯项目赢得';当使用或陈述时,不要识别单词,c++,c,yacc,lex,C++,C,Yacc,Lex,我正在运行以下lex程序,该程序可以很好地识别关于猫的句子: %{ #include <iostream> #include <cstdio> #include <cstdlib> using namespace std; extern "C" int yylex(); %} SP [ ]+ ARTICLE "le" /* Lin
%{
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
extern "C" int yylex();
%}
SP [ ]+
ARTICLE "le" /* Line I am trying to change */
COMMUN "chat"
VERBE "est"
NOIR "noir"
PHRASE {ARTICLE}{SP}{COMMUN}{SP}{VERBE}{SP}{NOIR}
%%
^{PHRASE}\n { cout << "Une phrase : " << yytext << '\n'; }
\n { cout << '\n'; }
^.*\n { cout << "Ligne inconnue : " << yytext << '\n'; }
%%
int main(int argc, char *argv[])
{
++argv, --argc;
if(argc > 0)
yyin = fopen(argv[0], "r");
else
yyin = stdin;
yylex();
} /* main() */
但是,当我尝试向程序中添加OR语句时(针对本文),cat语句不再被识别:
输入文件只是一个包含以下行的文本文件:
有人能告诉我为什么这行不通吗?我在网上找到的每一个版本或声明都试过了,但仍然没有任何效果
谢谢 实现了flex
-l
标志,这样就可以继续处理真正旧的lex规范,否则这些规范将无法工作。对于任何新编写的扫描仪,您都不需要该标志。这一特殊问题是一个常见的原因
问题来自于宏扩展的处理:flex做了常识性的事情,避免了许多常见错误;然而,lex(和flex-l
)使您可以更轻松地使用宏定义射击您的脚
以防万一,莱克斯所谓的“定义”实际上是一个宏。就像C预处理器宏一样,lex宏也会引入一些潜在的误解
我想几乎每一个使用过预处理器的C程序员都会偶然发现这个问题:
#define SUM(a,b) a+b // DON'T DO THIS, EVER
虽然您可能会在某些上下文中成功地使用此宏,但最终会发现
int c = SUM(a,b) * 2;
计算a+b*2
而不是预期的(a+b)*2
。这是因为宏替换只是符号替换;如果宏中没有括号,则不会生成括号
这也是lex的工作方式,也是Posix标准所说的工作方式。但许多年前,《flex》的作者们意识到,没有人期望下面这样的定义会像它们那样起作用:
ARTICLE "le"|"la"
%%
{ARTICLE}" chat" { /* Matches either "le" or "la chat" */ }
因此flex(通常)会自动插入所需的括号,就好像您正确地将文章定义为:
ARTICLE ("le"|"la")
然而,这与原来的lex不兼容,它可能会破坏依赖于原始的恼人的文本语义的旧lex程序
因此flex提供了-l
(“Lex兼容性”)选项,可用于处理这些旧的Lex程序。但是,正如我所说的,它不应该用于任何新的lex程序
如果上面的说法不足以令人信服,那么这并不是原始lex做出的唯一错误选择,它由-l
标志保留。另一个是计数重复运算符{m,n}
的奇异运算符优先级。在flex中
ab* ab+ ab? ab{0,3}
平均值,分别为:
- “一个
a
后跟零个或多个b
s”
- “一个
a
后跟一个或多个b
s”
- “一个
a
后跟一个可选的b
”
- “从零到三次重复
ab
”
Flex通过使括号重复的运算符优先级与任何其他重复运算符的运算符优先级相同来修复这种不一致性,这无疑是每个人所期望的。同样,-l
标志恢复为原始的lex规范
最后,-l
选项使默认的yytext
声明成为数组而不是指针。虽然这可以使一些事情变得更容易,但总的来说,它带来了一些重要的缺点,包括:
- 要慢得多
- 它防止扫描程序调整其缓冲区的大小以处理长令牌
底线是:不要使用flex-l
选项(在本主题中,也不要使用bison-y
选项),除非您需要它来编译遗留代码。您在调用(f)lex时是否使用-l
选项?如果是的话,不要。我是,把它拿走就解决了问题。非常感谢。好的,在这个基础上我会回答你的问题。当然,如果你在其他用户之前回答,那么我会接受你的问题。谢谢!你不知道我在哪里可以找到关于-l选项的任何参考资料吗?@lewis:在中,还有很多关于使用(f)lex的有用信息。谢谢。我想我太习惯于依赖搜索引擎结果了。你应该在你的机器上以info flex
的形式提供该手册,但这当然取决于你的发行版/回购版。
int c = SUM(a,b) * 2;
ARTICLE "le"|"la"
%%
{ARTICLE}" chat" { /* Matches either "le" or "la chat" */ }
ARTICLE ("le"|"la")
ab* ab+ ab? ab{0,3}