Flex-lexer:后面的规则优先于前面的规则
Flex-lexer: later rule get priority over prior rule
我正在尝试从 c/c++ 源文件中提取信息。
我正在尝试提取宏的内容。
例如:
- 从
MYMACRO(random content)
random content
应该提取出来。
- 应从
MYMACRO (random content)
random content
中提取。
问题:
Bison 不会将 MYMACRO
识别为标记。
此代码只是第一步,只需要宏本身作为输入
Lex 文件:parser.l
%{
#include <iostream>
#include "parser.tab.h"
using namespace std;
extern int yylex();
%}
%option noyywrap
%%
"MYMACRO" {
return EXTRACT_CONTENT_START;
}
[(] {
return BRACE_OPEN;
}
[)] {
return BRACE_CLOSE;
}
.* {
yylval.sval = strdup(yytext);
return ANY_TEXT;
}
%%
野牛文件:parser.y:
%{
#include <iostream>
#include <string.h>
using namespace std;
extern int yylex();
extern int yyparse();
extern int yy_scan_string(char const *);
void yyerror(const char *s);
%}
%union {
int ival;
char * sval;
char cval;
}
%error-verbose
%token EXTRACT_CONTENT_START
%token <cval> BRACE_OPEN
%token <cval> BRACE_CLOSE
%token <sval> ANY_TEXT
%%
program:
EXTRACT_CONTENT_START
BRACE_OPEN
ANY_TEXT
BRACE_CLOSE
;
%%
int main(int ,char**){
yy_scan_string("MYMACRO(random content)");
yyparse();
}
void yyerror(const char *s) {
cout << endl << s << endl;
exit(-1);
}
- 预期:
random content
- 实际:
unexpected ANY_TEXT, expecting EXTRACT_CONTENT_START
(所以@Flex:不是发送第一个出现的规则,而是实际使用最后一个规则)
我也试过使用状态并将 flex 文件中的最后一条规则更改为
<STATE_CONTENT> .* {
yylval.sval = strdup(yytext);
return ANY_TEXT;
}
但这会导致包含 %%
.
行出现 unrecognized rule
错误
为什么优先考虑最后一条规则:
lex 使用最长匹配。并且 .* 比其他任何东西都适合更多的字符。因此 ANY_TEXT 总是被采纳的选择。
要解决它,请像这样更改它:
parser.l:
删除 .*
-规则并添加此规则:
. {
yylval.cval = *yytext;
return ANY_CHAR;
}
这条规则的最长匹配只有一个个字符。因此,与其他规则相比,它的优先级最低。
parser.y:
添加新令牌:
%token <cval> ANY_CHAR
要作用于整个字符串,添加:
anyText:
anyText ANY_CHAR { cout << ; }
|
;
@状态问题: rici的回答:
You cannot put whitespace before the pattern, whether or not it is preceded by a state. Another way of saying that, which is technically more accurate, is that patterns cannot contain unquoted whitespace, and the prefix is part of the pattern
我正在尝试从 c/c++ 源文件中提取信息。 我正在尝试提取宏的内容。
例如:
- 从
MYMACRO(random content)
random content
应该提取出来。 - 应从
MYMACRO (random content)
random content
中提取。
问题:
Bison 不会将 MYMACRO
识别为标记。
此代码只是第一步,只需要宏本身作为输入
Lex 文件:parser.l
%{
#include <iostream>
#include "parser.tab.h"
using namespace std;
extern int yylex();
%}
%option noyywrap
%%
"MYMACRO" {
return EXTRACT_CONTENT_START;
}
[(] {
return BRACE_OPEN;
}
[)] {
return BRACE_CLOSE;
}
.* {
yylval.sval = strdup(yytext);
return ANY_TEXT;
}
%%
野牛文件:parser.y:
%{
#include <iostream>
#include <string.h>
using namespace std;
extern int yylex();
extern int yyparse();
extern int yy_scan_string(char const *);
void yyerror(const char *s);
%}
%union {
int ival;
char * sval;
char cval;
}
%error-verbose
%token EXTRACT_CONTENT_START
%token <cval> BRACE_OPEN
%token <cval> BRACE_CLOSE
%token <sval> ANY_TEXT
%%
program:
EXTRACT_CONTENT_START
BRACE_OPEN
ANY_TEXT
BRACE_CLOSE
;
%%
int main(int ,char**){
yy_scan_string("MYMACRO(random content)");
yyparse();
}
void yyerror(const char *s) {
cout << endl << s << endl;
exit(-1);
}
- 预期:
random content
- 实际:
unexpected ANY_TEXT, expecting EXTRACT_CONTENT_START
(所以@Flex:不是发送第一个出现的规则,而是实际使用最后一个规则)
我也试过使用状态并将 flex 文件中的最后一条规则更改为
<STATE_CONTENT> .* {
yylval.sval = strdup(yytext);
return ANY_TEXT;
}
但这会导致包含 %%
.
unrecognized rule
错误
为什么优先考虑最后一条规则:
lex 使用最长匹配。并且 .* 比其他任何东西都适合更多的字符。因此 ANY_TEXT 总是被采纳的选择。
要解决它,请像这样更改它:
parser.l:
删除 .*
-规则并添加此规则:
. {
yylval.cval = *yytext;
return ANY_CHAR;
}
这条规则的最长匹配只有一个个字符。因此,与其他规则相比,它的优先级最低。
parser.y:
添加新令牌:
%token <cval> ANY_CHAR
要作用于整个字符串,添加:
anyText:
anyText ANY_CHAR { cout << ; }
|
;
@状态问题: rici的回答:
You cannot put whitespace before the pattern, whether or not it is preceded by a state. Another way of saying that, which is technically more accurate, is that patterns cannot contain unquoted whitespace, and the prefix is part of the pattern