Random Posts
Tags
Categories
Recent Comments
- 小肥 on GDB 从裸奔到穿戴整齐
- flandre on 异步事件模型的 Self-pipe trick
- inv on 异步事件模型的 Self-pipe trick
- skywind on 异步事件模型的 Self-pipe trick
- skywind on 异步事件模型的 Self-pipe trick
Links
Meta
Category Archives: 编译原理
56 行代码用 Python 实现一个 Flex/Lex
作为 Yacc/Bison 的好搭档 Lex/Flex 是一个很方便的工具,可以通过写几行规则就能生成一个新的词法分析器,大到给你的 parser 提供 token 流,小到解析一个配置文件,都很有帮助;而用 Python 实现一个支持自定义规则的类 Flex/Lex 词法分析器只需要短短 56 行代码,简单拷贝粘贴到你的代码里,让你的代码具备基于可定制规则的词法分析功能。 原理很简单,熟读 Python 文档的同学应该看过 regex module 帮助页面最下面有段程序: def tokenize(code): keywords = {‘IF’, ‘THEN’, ‘ENDIF’, ‘FOR’, ‘NEXT’, ‘GOSUB’, ‘RETURN’} token_specification = [ (‘NUMBER’, r’\d+(\.\d*)?’), # Integer or … Continue reading
使用 LIBLR 解析带注释的 JSON
前文《基于 LR(1) 和 LALR 的 Parser Generator》里介绍了春节期间开发的小玩具 LIBLR ,今天春节最后一天,用它跑一个小例子,解析带注释的 json 文件。由于 python 自带 json 库不支持带注释的 json 解析,而 vscode 里大量带注释的 json 没法解析,所以我们先写个文法,保存为 json.txt: # 定义两个终结符 %token NUMBER %token STRING start: value {get1} ; value: object {get1} | array {get1} | STRING … Continue reading
基于 LR(1) 和 LALR 的 Parser Generator
最近处理文本比较多,先前想增强下正则,看来不够用了,有同学推荐了我 Pyl 和 Lark,看了两眼,初看还行,但细看有一些不太喜欢的地方,于是刚好春节几天有空,从头写了一个 LR(1) / LALR 的 Generator,只有一个 LIBLR.py 的单文件,没有其它依赖: GitHub – skywind3000/LIBLR: Parser Generator for LR(1) and LALR 用法很简单,给定文法,返回 Parser: import LIBLR # 注意这里是 r 字符串,方便后面写正则 # 所有词法规则用 @ 开头,从上到下依次匹配 grammar = r”’ start: WORD ‘,’ WORD ‘!’; … Continue reading
Python 中使用组合方式构建复杂正则
正则写复杂了很麻烦,难写难调试,只需要两个函数,就能用简单正则组合构建复杂正则: 比如输入一个字符串规则,可以使用 {name} 引用前面定义的规则: # rules definition rules = r”’ protocol = http|https login_name = [^:@\r\n\t ]+ login_pass = [^@\r\n\t ]+ login = {login_name}(:{login_pass})? host = [^:/@\r\n\t ]+ port = \d+ optional_port = (?:[:]{port})? path = /[^\r\n\t ]* url = … Continue reading
什么时候用C而不用C++?
知乎问题《什么时候用C而不用C++?》: 前两天不是有一个问题是“什么时候用C++而不用C”,我一直觉得问错了,难道不是“能用C++就不用C”么?那么当然就要讨论什么时候用C而不用C++啦。 一直以来都严格遵循OO的原则来进行开发(用的工具是C#和Qt),直到最近,开始接手某同事的代码,整个项目20多个小工程(代码量并不多),除了界面部分用了MFC这种不伦不类的OO以外,所有的代码都是C写的。但是模块化做的非常好。后来跟他讨论为何不用C++,他说其实没有什么特别的,就是习惯和爱好而已,后又补充: 如果不用多态的话,其实不管怎么写,不管用那种语言写,都算不上真正的OO 忽然觉得很有道理…… 其实这是一个好问题, 题主开始欣赏到纯 C代码所带来的 “美感” 了,即简单性和可拆分性。代码是自底向上构造,一个模块只做好一个模块的事情,任意拆分组合。对于有参考的 OOP系统建模,自顶向下的构造代码抽象方法是有效率的,是方便的,对于新领域,没有任何参考时,刻意抽象会带来额外负担,并进一步增加系统耦合性,设计调整,往往需要大面积修改代码。 有兴趣你可以读读《Unix编程艺术》,OOP的思维模式,是大一统的;C的思维模式,是分离的。前者方便但容易造成高耦合,后者灵活但开发开发太累。用 C开发,应该刻意强调 “简单” 和 “可拆分”。一个个象搭积木一样的把基础系统搭建出来,哪个模块出问题,局部替换即可。 自底向上的开发模式,并不是从不站在大局考虑问题,而是从某个子系统具体实现开始,从局部迭代,逐步反思全局设计,刻意保持低偶合,一个模块一个模块的来,再逐步尝试组合。 自底向上强调先有实践,再总结理论,理论反过来指导实践,又从实践中迭代修正理论。这和人类认识世界的顺序是一样的,先捕猎筑巢,反思自然是怎么回事,又发现可以生火,又思考自然到底怎么回事情。 它的反面,是指大一统设计,你一开始用 UML画出整套系统的类结构,然后再开工设计。这种思维习惯,如果是参考已有系统做一个类似的设计,问题不大,全新设计的话,他总有一个前提,就是 “你能完整认识整个大自然”,就像人类一开始就要认识捕猎和筑巢还有取火一样。否则每次对世界有了新认识,OOP的自顶向下设计方法都能给你带来巨大的负担。 所以有些人才会说:OOP设计习惯会依赖一系列设计灵巧的 BaseObject,然而过段时间后再来看你的项目,当其中某个基础抽象类出现问题是,往往面临大范围的代码调整。这其实就是他们使用自顶向下思维方法,在逐步进入新世界时候,所带来的困惑。 当然也有人批判这种强调简单性和可拆分性的 Unix思维。认为世界不是总能保持简单和可拆分的,他们之间是有各种千丝万缕联系的,你一味的保持简单性和可拆分性,你会让别人很累。这里给你个药方,底层系统,基础组建,尽量用 C的方法,很好的设计成模块,随着你编程的积累,这些模块象积木一样越来越多,而彼此都无太大关系,甚至不少 .c文件都能独立运行,并没有一个一统天下的 common.h让大家去 include,接口其他语言也方便。 然后在你做到具体应用时根据不同的需求,用C++或者其他语言,将他们象胶水一样粘合起来。这时候,再把你的 common.h,写到你的 C++或者其他语言里面去。当然,作为胶水的语言不一定非要是 C++了,也可以是其他语言。 ————- PS: 这里主要在探讨 OOP存在的问题,并没有讨论嵌入式这种资源限制的情况,以及操作系统和底层等需要精确控制硬件和内存的情况,更没有讨论 C++在语言设计层面的事情。 ————- 转部分答疑:(点击more展开)
转换 Intel汇编格式到 AT&T汇编风格
常用 MSVC写内嵌汇编需要兼容 GCC是一件头疼的事情,不是说你不会写 GCC的 AT&T风格汇编,而是说同一份代码写两遍,还要调试两遍,是一件头疼的事情,特别是汇编写了上百行的时候。于是五年前写过一个小工具,可以方便的进行转换,能把 MSVC/MASM的汇编转成纯 AT&T风格汇编,或者 GCC Inline风格汇编,自动识别寄存器和变量,还有跳转地址,并且自动导出。今天把他放上来,或许有用到的人吧。
[业余土制] Build工具 EasyMake
用最简单的方法描述工程信息,简化gnumake的繁琐操作,让不会用gnumake的同学们彻底解脱: 项目地址:http://code.google.com/p/easymake/
[业余土制] 实时汇编编译器
实时动态在内存中编译汇编代码,并返回函数调用指针,可用于JIT系统的后端: 项目地址:http://code.google.com/p/asmpure/ 例子: const char *AlphaBlendAsm = “PROC C1:DWORD, C2:DWORD, A:DWORD\n” ” movd mm0, A\n” ” punpcklwd mm0, mm0\n” ” punpckldq mm0, mm0\n” ” pcmpeqb mm7, mm7\n” ” psubw mm7, mm0\n” ” \n” ” punpcklbw mm1, C1\n” ” psrlw mm1, … Continue reading