%%
[ \t]+$ ;
[ \t]+ printf(" ");
%%
main() {
return yylex();
}
int yywrap() {
return 1;
}
%%是分隔符,第一个%%下面是正则表达式规则,第二个%%下面是主程序部分[ \t]是匹配空格或tab+是匹配1至多个$是end of line行尾- 动作
;分号,表示该匹配不做任何操作,对应的字符也不会回显 printf(" ")则是自定义回显方式,这一行代码把非行尾的空格或tab显示为1个空格main()默认取stdin标准输入流,通过调用yylex开始词法解析yywrap()则是告诉程序,当流结束时,如何处理- 返回
1说明结束程序扫描 - 返回
0则继续扫描
- 返回
./test 然后从终端输入字符串即可
%{
int num_lines;
int num_chars;
%}
%%
\n ++num_lines; ++num_chars;
. ++num_chars;
%%
main() {
yylex();
printf("# of lines = %d, # of chars = %d\n", num_lines, num_chars);
}
int yywrap() {
return 1;
}
%%之上,是定义区,需要用%{和%}包住\n是匹配换行,匹配成功时执行num_lines++以及num_chars++\.点号是匹配除\n之外的所有字符,匹配成功时执行num_chars++main()在yylex()解析完成后,打印num_lines和num_chars
./test 然后从终端输入多行字符串,回车, ctrl + D 即可看到输出
" \ [ ] ^ - ? . * + | ( ) $ / { } % < >
关键字可以通过 " 双引号或 \ 反斜杠转义,例如:
abc"++" 及 abc\+\+ 表示匹配 abc++ 字符串
\t \n \b 分别是tab newline backspace
反斜杠\本身则是\\
[abc]表示匹配a或b或c\-^是[]中可解析的符号-表示范围,例如[a-z]匹配a到z的字符-若要转义,则需要放在[]的最前和最后,例如[-+0-9],第一个-就解析为-符号本身^表示取反,必须在[]的开头,例如[^abc]表示所有的不是abc的字符,[^a-zA-Z]表示所有的非字母\表示八进制字符,[\40-\176]表示匹配八进制40(blank) 到176(tilde) 的字符
?匹配0或1个对应字符,ab?c匹配abc或aca*匹配0到多个aa+匹配1到多个a|匹配左右之一,ab|cd匹配ab或cd(ab|cd+)?(ef)*匹配abefefefefefcdefcddd而不匹配abcabcdabcdef^匹配行的开头$匹配行的结尾/条件匹配,ab/cd匹配ab,但必须在cd之前,ab$也就是ab/\n{digit}匹配指定的多个,例如a{1,5}匹配1到5个a,a{2}匹配2个a<>是用来处理上下文前导状态,参考Left Context Sensitivity
- 有多个代码需要执行时,需要用大括号包住
- 当匹配了正则表达式后,会执行对应的
action - 默认
action是把标准输入直接传到标准输出,因此,当没有匹配时,也会有默认输出 - 直接
;表示无操作 - 当用户想知道正则表达式到底匹配的是什么值,可以使用
yytext, 如下:
[a-z]+ printf("%s", yytext); - 为了方便,也有宏可以表示同样的含义:
[a-z]+ ECHO; yyleng可以得到匹配的长度,例如:
[a-zA-Z]+ {words++; chars += yyleng;}yytext[yyleng-1]则可以得到最后匹配到的1个字符|表示当前action使用下一个正则匹配的action- 如果当前词法解析不符合要求时,可以通过
yymore()追加到当前的input中 yyless(n)则表示当前词法不需要这么多input,仅保留n个字符在yytext中,剩下的返回到input
\"[^"]* {
if (yytext[yyleng-1] == '\\')
yymore();
else
... normal user processing
}
这里说明遇到 \ 时,保留 yytext 中的数据,需要继续执行解析
例如, "abc\"def" 先匹配 "abc\,执行 yymore(),然后匹配 "def,并连接为 "abc\"def,最后匹配 "
=-[a-zA-Z] {
printf("Op (=-) ambiguous\n");
yyless(yyleng-1);
... action for =- ...
}
这里说明遇到 =-a 时,语法是多义的,需要减少一个字符去解析,也就是解析为 =- 符号,等价于: =-/[A-Za-z]
若 =-a 要解析为 = -a 这个意思,对应的正则表达式等价于: =/-[A-Za-z]
如果不想处理多义,只解析 =-3,另一种更简单的方法,可以表示为: =-/[^ \t\n]
input()返回下一个输入字符output(c)输出c到输出unput(c)返回c到input以供下次读取- 输入流必须以
NULL结尾 input和uninput必须保留原有做法,因为lookahead要用到,比如?+*$/都会用到lookaheadyywrap()返回1时,是直接退出,返回0时,则允许程序继续读取输入流