编译器知识杂记-前段编译器-语法分析-yet another compiler compiler

yet another compiler compiler(yacc)

yet another compiler compiler(yacc)简介:使用说明:yacc语法结构:BNF文法介绍:什么是文法介绍?为什么要学习BNF文法介绍?文法介绍例子:句型和句子:两种主要的分析方法。语法树相关知识点简介:什么是语法树?语法树例子①:yacc Demo实例:定义段:规则段:用户子程序段

简介:

在之前介绍过Lex,他检测代码的规范语法,将我们输入的字符串解析成对应的token

解析完毕以后就该yacc上场了,Lex主要是词法分析,yacc是语法分析

yacc可将语法规则文件转换成C源码文件,编译此源文件可得到一个用于语法分析的程序。

由于语法分析要使用词法分析的结果,所以yacc经常会搭配lex一起工作。

如果说词法分析的作用是从连续的字符中识别出标识符、关键字、数字、运算符并存储为符号(token)流,语法分析的作用就是从词法分析识别出的符号流中识别出符合 C 语言语法的语句。因为计算机无法像人那样同时看多个标识符、关键字、数字、运算符,无法像人那样一眼看出这是一个函数声明,那是一个 if 语句,只能非常笨拙地一个符号一个符号去识别。与词法分析器有些类似,语法分析器也是依据用计算机表示的语法,一个符号一个符号地识别出符合 C 语言语法的语句。语法的计算机表示就是产生式。在语法分析器中把通过产生式产生的 C语言语法映射成一套模板,并把这套模板融汇在语法分析器的程序中。语法分析器的作用就是将词法分析器别出的符号(token)一个一个地与这套模板进行匹配,匹配上这套模板中的某个语法,就可以识别出一句完整的语句,并确定这条语句的语法。 转载自《编译系统透视:图解编译原理》

使用说明:

语法文件详细的规则可以参考我之前的帖子

https://www.jianshu.com/p/7a9476c65672

yacc也需要对应的规则文件配合yacc,可以生产y.tab.c和y.tab.h

( 语法分析就要从这个符号串中识别出符合 C 语言语法的语句。识别的方法是:以 C 语言语法

为模板,将符号串按序逐个匹配,如果能匹配成功,就可以确定匹配成功的符号串是一条符合 C 语言语法的句

子,同时也就确定了这条语句的语法属性(如函数声明语句)及句子的各个语法成分(如返回值类型、函数名、

参数列表)。如果与所有语法类型的模板都无法匹配,说明这个符号串有语法错误。)

流程如下图:

image.png

yacc语法结构:

yacc语法包括三部分:定义段、规则段和用户子例程段

...定义段...

%%

...规则段...

%%

...用户子例程段...

各部分由以两个百分号开头的行分开,尽管某一个部分可以为空,但是前两部分是必须的,第三部分和前面的百分号可以省略。

BNF文法介绍:

语法分析的目的是判断语句是否符合语言所规定的语法要求。所以,语法分析的首要任务是制订相应的语法规则。

语法规则是通过文法来描述的。

什么是文法介绍?

文法有很多描述方法,最常用的一种方法是BNF范式(Backus-Naur Form)。

下面是一个基于中文语法、利用BNF范式来描述的文法示例。

image.png

为什么要学习BNF文法介绍?

当yacc拿到 各种token(具体参考上一章)的时候

需要将token拼成句子,比如 int a = b

很简单的语法,如果直接解析成 = b,这种就是错误的语法,所以在yacc里面也需要通过 “主谓宾” 的方式去

拼够,因为yacc的功能是将token拼成一句代码的 “过程”

yacc可以将各种token进行区分,分成对应的 “主谓宾”。

比如他遇到了 你 我 他 他就会认为这个是主语。

文法介绍例子:

我们还是以邓老师的例子

比如 一句话很简单的 他吃饭

1,先去寻找主语,发现 满足,程序就会变成 主语,吃饭

2,当读取 吃或者喝的时候 认为是谓语,变成 “主语,谓语,饭”

3,当读取到饭的时候,变成 “主语,谓语,宾语”

4,宾语可能是很多种情况,我们成为 子句子子句子 比如不一定吃的是饭 ,可以吃的是菜,我们认为他是自句子,在程序中 ,

比如 int a 我们也可以变成int b。b变量 就可以算成子句子,所以饭属于子句子宾语。

“他吃饭”按照文法规则进行多次迭代,替换非终结符,最终得到句子,所以它符合示例的语法规范,所以认定其语法是正确的。

yacc其实也是如上类似逻辑。

比如 一句 “你水” 没有谓语这种就认为是错误的。

句型和句子:

语法分析的过程中会产生一些包含非终结符的字符串,比如 “主语吃饭” “子句子饭”等。

这些包含非终结符的字符串叫句型(sentential form)

而不包含非终结符的字符串叫句子(sentence)

任何句型都可以由文法开始符经过零次或多次推导得到。而从任何句型出发,经过不断推导,都可以得到一个有效的句子。由上述示例可知,语法分析的大体过程就是不断对输入语句按照文法进行分析,替换其中的非终结符,直到处理完毕。

两种主要的分析方法。

·一种是自顶向下的推导(英文为derivation)法。

以“他吃饭”为例,推导法首先从文法开始符句子的产生式开始:句子被替换成子句子和宾语,子句子被替换成主语和谓语。接着,主语被替换成“他”,谓语被替换成“吃”,宾语被替换成“饭”。最终得到的结果和输入的语句一样,所以输入语句的语法正确。推导法适合手工编码实现。

另一种是自底向上的归约(英文为derivation)法。就比如之前介绍的文法介绍例子。

yacc就是利用向上的归约方式进行生成语法分析器。

语法树相关知识点简介:

什么是语法树?

在语法分析过程中,人们发现使用树形结构来描述整个推导过程会比较直观和方便,该树也被称为语法树(syntax tree,或语法分析树parse tree)。

语法树是句子结构的图形表示,它代表了句子的推导结果,有利于理解句子语法结构的层次。简单说,语法树就是按照某一规则进行推导时所形成的树。

yacc生成的结果便是通过语法树抽象出来的结果。

语法树例子①:

如果我们需要让计算机帮忙算一下 「1加2再乘以3」 的结果,该怎么表达呢? 现在我们大多数的现代编程语言,都是使用「中缀表达式」的方式来编写运算,比如JavaScript:

(1 + 2) * 3

而FORTH语言则使用「后缀表达式」,这基本上与日语中的语序是一致的:

1 2 + 3 *

LISP语言使用的「前缀表达式」:

( * (+ 1 2) 3)

我们再看一下这三种表达式的语法树:

image.png

可以看出,对于这三种简单的语言,它们只是在这个语法树上按不同的规则遍历而已。三者的代码看起来差别很大,但实际上所用的树结构是相同的。

yacc Demo实例:

转自(http://www.quut.com/c/ANSI-C-grammar-y-1998.html

参考自《深入理解Android:Java虚拟机Art》

一个demo主要分为

定义段,规则段,用户子程序段

定义段:


//先定义好需要处理的token信息
%token IDENTIFIER CONSTANT STRING_LITERAL SIZEOF
%token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
%token XOR_ASSIGN OR_ASSIGN TYPE_NAME

%token TYPEDEF EXTERN STATIC AUTO REGISTER INLINE RESTRICT
%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID
%token BOOL COMPLEX IMAGINARY
%token STRUCT UNION ENUM ELLIPSIS

%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN



//文件开始符,每个语法规则文件一定需要有一个文件开始符
%start translation_unit
%%
//和 Lex规则文件一样也需要有一个 yyerror函数,当解析出错的时候调用
void yyerror(char const *s)
{
 fflush(stdout);
 printf("\n%*s\n%*s\n", column, "^", column, s);
}

规则段:

yacc规则段其实就是文法,文法中产生式常见的书写格式为

A:BC|D

规则中目标或非终端符放在左边,后跟一个冒号(:),然后是产生式的右边,之后是对应的动作(用{}包含)

拿个很简单的 printf 举例子如下

 { printf("%d\n", $2); }  ;
expr: INTEGER { $ = $1; }  
 | expr '+' expr { $ = $1 + $3; } 
 | expr '-' expr { $ = $1 - $3; } 
;

1表示右边第一个标记的数值,2表示右边的第二个标记的值,依次类推。$$表示归约后的值。

用户子程序段

yacc 将用户子例程段的内容完全拷贝到C文件中,通常这部分包括从动作调用的例程。 该部分是函数部分。当yacc解析出错时,会调用函数yyerror(),用户可自定义函数的实现。 main函数是调用yacc解析入口函数yyparse()。如:

int main(void) 
{ 
 yyparse(); 
 return 0; 
}

参考:

《深入理解Android:Java虚拟机Art》

《编译系统透视:图解编译原理》

https://www.jianshu.com/p/1fe5a61fd9dc

https://www.cnblogs.com/zhuchengyang/p/7692626.html

安卓逆向百级教程+全网最新js逆向视频+永久小蜜圈+永久售后群=1299

视频下载网盘
http://nas.alienhe.cn:5008/home.html
下载视频账号密码:
账号guest 密码world

Js试看:
http://oss.alienhe.cn/JS%E9%80%86%E5%90%91%E5%85%A5%E9%97%A8-%E5%B8%A6%E6%B0%B4%E5%8D%B0.mp4

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容