thriftpy+ply源码分析
Posted golang算法架构leetcode技术php
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了thriftpy+ply源码分析相关的知识,希望对你有一定的参考价值。
thrift 使用ply做编译和解析器,ply是编译原理入门比较方便的源码,代码量少,且python文本就是代码,解析方便
ex把每个扫面出来的单词叫统统叫做token,token可以有很多类。对比自然语言的话,英语中的每个单词都是token,token有很多类,比如non(名词)就是一个类token,apple就是属于这个类型的一个具体token。对于某个编程语言来说,token的个数是很有限的,不像英语这种自然语言中有几十万个单词。
lex工具会帮我们生成一个yylex函数,yacc通过调用这个函数来得知拿到的token是什么类型的,但是token的类型是在yacc中定义的。
lex的输入文件一般会被命名成 .l文件,通过lex XX.l 我们得到输出的文件是lex.yy.c
yacc是什么呢?
刚才说完lex了,那么yacc呢,教科书上把yacc做的工作叫做syntactic analysis。这次我们翻译没有直译做句法分析,而是叫语法分析,这个翻译能好一点,意思也基本上比较清楚。
其实我们最开始学习英语的时候老师都会告诉我们英语其实就是“单词+语法”,这个观点放到编程语言中很合适,lex提取了单词,那么是剩下的部分就是如何表达语法。那么yacc做的事情就是这一部分(实际应该说是BNF来做的)。
yacc会帮我们生成一个yyparse函数,这个函数会不断调用上面的yylex函数来得到token的类型。
yacc的输入文件一般会被命名成 .y文件,通过yacc -d XX.y我们得到的输出文件是y.tab.h y.tab.c,前者包含了lex需要的token类型定义,需要被include进 .l文件中
lex和yacc的输入文件格式
Definition section
%%
Rules section
%%
C code section
.l和.y的文件格式都是分成三段,用%%来分割,三个section的含义是:
Definition Section
这块可以放C语言的各种各种include,define等声明语句,但是要用%{ %}括起来。
如果是.l文件,可以放预定义的正则表达式:minus "-" 还要放token的定义,方法是:代号 正则表达式。然后到了,Rules Section就可以通过{符号} 来引用正则表达式
如果是.y文件,可以放token的定义,如:%token INTEGER PLUS ,这里的定一个的每个token都可以在y.tab.h中看到
Rules section
.l文件在这里放置的rules就是每个正则表达式要对应的动作,一般是返回一个token
.y文件在这里放置的rules就是满足一个语法描述时要执行的动作
不论是.l文件还是.y文件这里的动作都是用{}扩起来的,用C语言来描述,这些代码可以做你任何想要做的事情
C code Section
main函数,yyerror函数等的定义
lex和yacc能帮我们做什么?
一句话:解释执行自定义语言。有几点要注意:
自定义语言的要做的事情必须可以能通过C语言来实现。其实任何计算机能做的事情都可以用C语言来实现,lex和yacc存在的意义在于简化语言,让使用者能够以一种用比较简单的语言来实现复杂的操作。比如:对于数据库的查询肯定有现成的库可以来完成,但是使用起来比较麻烦,要自己写成语调用API,编译才行。如果我们想实自定义一个简单的语言(比如SQL)来实现操作,这个时候就可以用lex和yacc。
lex和yacc 做的事情只是:用C语言来实现另外一种语言。所以,他没办法实现C语言自己,但是可以实现java、python等。当然你可以通过Antlr来实现C语言的解析和执行,如果你这么做的话,C语言程序首先是通过java来执行,然后java又变成了本地语言(C语言)来执行,谁叫我们的操作系统都是C语言实现的呢。
使用lex和yacc我们要做那几件事情?
定义各种token类型。他们在.y中定义,这些token既会被lex使用到,也会被.y文件中的BNF使用到。
写词汇分析代码。这部分代码在.l文件(就是lex的输入文件)中。这块的定义方式是:正则表达式-->对应操作。如果和yacc一起来使用的话,对应的操作通常是返回一个token类型,这个token的类型要在yacc中提前定义好。
写BNF。这些东西定义了语言的规约方式。
关于BNF
是一种context-free grammars,请参考:http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form 摘录:
<symbol> ::= __expression__
<symbol> is a nonterminal
__expression__ consists of one or more sequences of symbols
more sequences are separated by the vertical bar, '|'
Symbols that never appear on a left side are terminals. On the other hand
symbols that appear on a left side are non-terminals and are always enclosed between the pair <>.
在yacc中定义的方式其实是:
<symbol> : __expression__ {operation}
| __expression__ {operation}
operation 是 满足语法时要执行的C语言代码,这里的C语言代码可以使用一些变量,他们是:$$ $1 $2等等。$$代表规约的结果,就是表达式__expression__的值,$1代表的是前面 __expression__ 中出现的各个word。举个例子:
expr2:
expr3 { $$ == $1; }
| expr2 PLUS expr3 { $$ = plus($1, $3); }
| expr2 MINUS expr3 { $$ = minus($1, $3); }
;
以上是关于thriftpy+ply源码分析的主要内容,如果未能解决你的问题,请参考以下文章