定义段 (definitions) %% 规则段 (rules) %% 用户代码段 (user code)
/*定义段*/
%{
#include<iostream>
#include<string>
extern "C" {
int yywrap();
}
std::string str;
std::string num;
%}
/*规则段*/
%%
[a-zA-Z]+ { str += yytext; return 1; }
[0-9]+ { num += yytext; return 1; }
\n { return 0; }
%%
/*用户代码段*/
int yywrap() { return 1; }
int main() {
while( yylex() );
std::cout<<"Number: " << num <<std::endl;
std::cout<<"String: " << str <<std::endl;
return 0;
}
但我直接使用
g++ lex.yy.c -lfl
时出现找不到-lfl的错误,解决方案g++ lex.yy.c -lfl -Llib/
-L后面接静态链接库 libfl.a 所在的路径
还有一种解决方案:https://blog.csdn.net/linuxheik/article/details/79557023,但比较麻烦,他用到使VS来链接 libfl.a 而不是gcc或g++
需要回溯的情况:
表达式 | 匹配 | 例子 |
---|---|---|
r1r2 | 连接 | |
r1|r2 | 或 | |
(r) | 不改变r表示,主要是用于确定运算优先关系 | |
r* | 零个或多个实例 | |
r+ | 一个或多个实例 | |
r? | 零个或多个实例 | |
[a-c] | 等价于a|b|c,或 [abc] | |
. | 除了换行符以外的任意字符 | |
^ | 一行的开始 | |
$ | 行的结尾 | |
[^abc] | 除了abc以外的任何字符 | |
r{m,n} | 重复出现次数m-n | |
r1/r2 | 后面有r2时的r1 | abc/123 |
\c | 运算类字符的字面值 | \*,\$,\| |
<S>r | r, but in start condition S | |
<<EOF>> | the end-of-file |
int yylex();
yylex() 对输入流(默认stdin)进行分析,当匹配到一个正则表达式,有两种情况
[0-9]+ { num += yytext; return 1; }
动作有返回, yylex()立即返回,在下次调用时从此处继续读取[ \t\] {}
动作无返回, yylex 继续往后分析%oiption noyywrap
来要求它不使用yywrap变量 | 说明 |
---|---|
yy_c_buf_p | 缓冲区指针,相当于读头 |
static yyconst int yy_ec[256] | 状态转移矩阵 |
extern FILE *yyin; | yylex()所扫描的文件 |
extern FILE *yyout; | yylex()所输出的文件 |
extern int yyleng; | yylex()当前所识别词形的长度 |
extern char *yytext; | yylex()当前所识别的词形 |
#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) | 打印当前识别的词形到yyout |
#define REJECT reject_used_but_not_detected | 识别下一个最佳词形 |
yymore() | 模式对应的action完成之后yytext不清空 |
yyless(n) | 当前模式匹配后,缓冲区指针回到当前词形的第n+1个字符 |
input() | 从缓冲区读入一个字符,并将指针后移一位 |
unput© | 回退字符c到输入流,即追加c到缓冲区当前扫描字符之前 |
BEGIN(s) | |
int yywrap(); | 当yylex遇到EOF时调用此函数,此函数返回1,yylex()扫描结束,否则继续扫描 |
名称功能 | 声明 | |
---|---|---|
atoi | 字符串转换为10进制数 | int atoi(const char *str) |
strtol | 字符串转换成任意进制数字(2~36) | long int strtol(const char *str, char **endptr, int base) |
选项 | 说明 |
---|---|
-b | 输出回溯到lex.backup文件中 |
-C | 对输出状态转移矩阵进行不同程度的压缩,强弱次序为:-Cem(缺省),-C,-C{f, F}e, -C{f, F}, -C{f, F}a |
-f | 状态转移矩阵不压缩 |
-d | 每个模式匹配后输出调试信息 |
-v | verbose mode, 输出生成的扫描程序DFA等状态信息 |
-T | trace mode, 跟踪扫描程序的生成的每个过程 |
例:
extern FILE* yyin;
...
int main(int argc, char **argv)
{
if(argc>1){
if(!(yyin = fopen(argv[1], "r"))){
perror(argv[1]);
return 1;
}
}
...
return 0;
}
注意优先级
如bar* === ba(r*)
%{一定要顶行书写
要匹配空格,需要出现在“ ”或 [ ]中
规则段也要顶行书写。
{}要平衡,如果少了一个,flex将把后面的代码全部当作action