版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_35390390/article/details/74453485
举个栗子:
if(a > b && c < d)
{
}
假如需要分析上面的if语句
lex的模式规则定义如下:
"if" {return IF;}
"(" {return BOL;}
")" {return BOR;}
"&&" {return AND;}
"{" {return BEL;}
"}" {return BER;}
">" {return MOT;}
"<" {return LET;}
[a-zA-Z]* {return VALSTR;}
(\n|\r)+ {}
其中,BOL BOR等是一些枚举值
则,lex打标记之后,变成如下形式:
IF BOL VALSTR MOT VALSTR AND VALSTR LET VALSTR BOR BEL BER
lex是对输入文本进行模式匹配的过程
之后yacc对标记进行语法分析
yacc的语法规则定义如下:
root: conditon trunk {do something...}
condition: IF BOL expr BOR {do something...}
trunk: BEL BER | BEL action BER {do something...}
expr: BOL expr BOR{} | expr AND expr{} | expr MOT expr{} | expr LET expr{} | VALSTR{}
语法分析会按照设定的语法规则,生成一棵语法树,并且从底向上执行每个规则对应的动作
可以看到,上面的语法规则和lex分析的结果一一对应,而规则对应的动作则可以自定义,这样就可以实现自定义的语法了
lex:
词法分析器,和c是强耦合简单地讲,lex做的是一个字符串匹配的工作,它从待匹配的文本字符串中寻找预设的表达式,如果寻找到一个特定的表达式,则执行相应的动作
支持的表达式类似正则表达式
使用方式:
1 按照lex的规则,指定表达式及其相应的动作
2 根据上一步配置的表达式和动作,生成扫描器的c代码
lex的规则配置:
共分为三个段
1 c和lex的全局声明
这部分放置c变量声明、include文件、lex的标记声明等,语法如
%{
int wordCount = 0;
%}
chars [A-za-z\_\'\.\"]
numbers ([0-9])+
delim [" "\n\t]
whitespace {delim}+
words {chars}+
%%
其中,c变量声明、include文件放在%{%}中, %%是段的分隔符,表示该段的结束和下一段的开始
如上chars、numbers 等被声明为一个标记,其后是对应的匹配表达式。即当匹配上相应表达式的时候,该文本会被打上对应的标记
2 模式
语法如下:
{words} { wordCount++; /* increase the word count by one*/ }
{whitespace} { /* do nothing*/ }
{numbers} { /* one may want to add some processing here*/ }
%%
如上定义的规则,遇到words的时候,wordCount自增,遇到空格,则跳过,其他未定义
冲突解决规则:
1) 总是选择最长的前缀
2) 如果最长的可能前缀与多个模式匹配,总是选择Lex中先被列出的模式。
3 补充的c函数,此部分可以省略
void main()
{
yylex(); /* start the
analysis*/
printf(" No of words:
%d\n", wordCount);
}
int yywrap()
{
return 1;
}
yacc:
语法分析器终端和非终端符号
终端符号 : 代表一类在语法结构上等效的标记。 终端符号有三种类型:
命名标记: 这些由 %token 标识符来定义。 按照惯例,它们都是大写。
字符标记 : 字符常量的写法与 C 相同。例如, -- 就是一个字符标记。
字符串标记 : 写法与 C 的字符串常量相同。例如,"<<" 就是一个字符串标记。
lexer 返回命名标记。
非终端符号 : 是一组非终端符号和终端符号组成的符号。 按照惯例,它们都是小写。 在例子中,file 是一个非终端标记而 NAME 是一个终端标记。
规则编写也分为三部分
1 声明
2 语法规则
3 c代码(可省略)
lex 和 yacc一起使用
lex和yacc共享标记的声明lex来做词法分析,根据配置的规则,返回对应的标记
yacc 根据lex返回的标记定义语法规则,并根据规则进行相应的动作
参考https://www.ibm.com/developerworks/cn/linux/sdk/lex