这两个函数可以轻松地帮我们将词法分析器改为LALR(n)的词法分析器。
-
yymore()
yymore函数是指,将下次分析的结果词汇,接在当前yytext的后面,而不是替换已有内容。(当前已有内容并不会影响下次分析)
比如如下代码:%x xdquote \" { BEGIN(xdquote); } <xdquote>[^"]+ { yymore(); } <xdquote>\"\" { yymore(); } <xdquote>\" { yylval->str = yytext; BEGIN(INITIAL); return STRING; }
那么对于字符串
"a""b"
,首先根据第一条规则匹配引号,进入xdquote模式。然后a匹配第二条规则,此时使用了yymore,因此接下来的两个引号匹配到第三条规则之后,此时的yytext不是""
,而是a""
,即匹配到的两个引号不是替换原有的a,而是接在了后面。同样,接下来匹配到的b
以及最后的"
同样接在了原本的yytext后面。所以最后返回时yytext中为a""b"
(这里有个问题,那就是最后的引号会匹配进来,可以使用接下来的yyless或者其他方法来去掉最后的引号)。 -
yyless(n)
这个函数是将yytext中除了前n个字符以外的字符,重新放回输入流里进行重新匹配。说起来比较拗口,但是看一下代码应该就能明白了。
比如PGSQL中,对于WTIH关键词,有不同的解析(这里不是源代码,而是另一种实现):%x xwith [Tt][Ii][Mm][Ee] { yylval->str = yytext; return TIME; } [Ww][Ii][Tt][Hh] { BEGIN(xwith); yymore(); } <xwith>[ \t\n\r\f]+ { yymore(); } <xwith>[Tt][Ii][Mm][Ee] { yyless(yyleng - 4); BEGIN(INITIAL); return WITH_LA; } <xwith>. { yyless(4); yylval->str = yytext; BEGIN(INITIAL); return WITH; }
这里匹配到WITH关键词后,并不直接返回,而是往后看,看看下一个词是什么。如果是TIME,那么就返回一个WITH_LA的token。同时将最后的四个字符time放回输入流中重新进行匹配。如果是其他的,那么只保留最开始的四个字符,也就是WITH,将其他的全部放回输入流中重新进行匹配。并将字符串WITH以及一个WITH token返回。
这样,对于字符串
WITH TIME
,这个词法分析器就会返回WITH_LA和TIME两个token。另外这里需要注意的是,yymore()和yyless(0)配合,很容易产生死循环。一定要注意。