Flex
二义性
大多数flex程序都具有二义性,相同的输入可能被不同的模式匹配,flex通过两个简单的规则来解决它
- 词法分析器匹配输入时匹配尽可能多的字符串
- 如果两个模式都可以匹配的话,匹配在程序中更早出现的模式
内置的功能
%x 用于标记一个独占的起始状态
%s 用于标记一个包含的起始状态,它允许未标记的模式也参与匹配。
- 起始状态定义了一个不同的词法分析器,拥有它自己的规则。当一个模式 xxx 则表示只有在state起始状态下才会进行xxx规则匹配。
- flex本身会定义起始状态INITIAL
切换状态
BEGIN 状态;
上下文相关
左上下文相关:三种方式 行首模式字符 ^ ; 起始状态以及显示代码。
右上下文相关:三种方式 行尾模式字符 $ ; 斜线符 / 以及 yyless()
- 斜线符 / 让abc/de 只匹配后面紧跟de的abc,yytext是abc,yyleng为3.
- yyless 让lex推回刚刚读取到的字符, abcde: { yyless(3);} 与 abc/de效果一致,表示仅保留3个字符,推回2个字符。但是yytext会包含5个字符,yyleng也是5。
bison
优先级规则
%left %right %noassoc 出现在规则中的顺序决定优先级的高低,低的出现在高的前面。
bison把规则右部最右边记号的优先级赋给规则本身,如果这个记号没有被赋予任何优先级,规则也将没有优先级。当bison遇到移进/规约冲突时,它将查询优先级表,如果冲突中的所有规则都具有优先级的话,它将使用优先级来解决冲突;bison会比较移进的符号和可能规约规则的优先级(最右记号的优先级);如果两者具有相同的优先级,bison将检查结合性,如果它们是左结合则归约,如果它们是右结合那么就移进。
%prec 记号,可以让他bison把记号优先级赋给这个规则。如下:
exp: '-' exp %prec UMINUS
上述表达式的优先级则同记号UMINUS级别
%Code块
bison在定义部门总是可以接受形如%{%}的C代码,有时这些代码必须放置在程序中的特定位置,通常是标准分析器框架代码特定部分的前或者后,%Code可以实现这一点。
%code [place] {
}
place限定符目前包括top、providers和requires
冲突
归约/归约冲突
存在两个指针,分别位于规则x、y的尾部,它们都希望做规约,这就会导致一个归约/归约冲突。bison通过选择更早出现的规则来解决归约/归约冲突。
start: x
| y
;
x : A
y : A
指针在扫过A后,归约/归约冲突,因为x、y规则都希望做归约。
bison可以预读一个记号,如下情况不会冲突
start: x B
| y C
;
x : A
y : A
由于bison只可以预读一个记号,如下情况则会冲突
start: x B C
| y B D
;
x : A
y : A
移进/归约冲突
存在两个指针,一个指针正要归约到另一个情况,而另外一个指针正在移进。bison总是选择移进来解决移进/归约冲突。
start: x
| y R
;
x : A R
y : A
指针在扫过A后,移动/归约冲突,因为y归约到start可以接收R,而规则x也能接收R。
排查移进/归约冲突关键步骤
- 确定归约规则
- 确定相关的移进归约
- 理解归约规则在归约后的状态
- 归约会产生冲突的记号流