存档

‘编译原理’ 分类的存档

一个十分弱的关键词高亮程序

2009年11月22日

Screenshot-zhangxuecheng's editer

功能十分的弱,主要是花了点时间学gtk的hello world,然后分词也折腾了会儿。
不过没关系,很快就会有各种词法的高亮加上的,哈哈

zhangxuecheng 编译原理

How to write a lexer?

2009年10月6日

手头已经有的code里面,除了ucc,还真没有那个编译器是手写lexer的,或许是太简单了。(对了, 好像还有lcc).

不过简单有简单的好处,lexer这种东西毕竟是通用的,不限于compiler,而且手写一个也很能锻炼一下coding能力。

ucc是这样实现的:

  1. 创建一个包含256个函数指针的数组,针对letter,digital和其他的token进行区分,比如所有的letter都是一个处理函数,ditigal是一个,其他的特殊token分别有一个,比如*, – 等;
  2. 每次读进一个byte,这个byte的范围是0~255;
  3. 根据value选择相应的处理函数, 得到具体的返回值;
  4. 最常见的情况之一是各种letter, 分几种情况处理:
    1. ‘L’打头, 那么后面很可能是这样: L’a’ 或者 L”hello world\n”, 要判断一下后一个字符是不是’或者”, 是的话按照char或者string处理(char和string的处理还挺麻烦, 后面再讲);
    2. 继续向后吃掉所有的letter或者digit;
    3. 然后就得到一个identifier了, 先去keyword表里查一下, 看是不是keyword. 这里用了hash表, 按照keyword的首字母排序;
    4. 去symbol里面查一下, 看是否已经有同名的id存在, 如果有的话, 就将已经保存下来的id地址返回; 否则就新allocate一段内存, 然后返回新的内存的指针;
  5. 最常见的情况之二是digit, 也分几种情况处理:
    1. 首先说明一下, ‘-’的处理是不包含在这里面的, 因为有二义性, 而且需要前溯好几步, 放在语法解析比较好, 比如a – 1 和a = -1 你就不好在词法解析这个级别做, 所以lexer只是把minus这个结果返回就可以了;
    2. 然后要考虑浮点数, 包括.和e这些, 还有0x和0X这样的十六进制数, 077这样的八进制数;
    3. 不过有一个疑问, 如果一开始就处理’.', 像10.444这样的数怎么处理?
  6. 后面是一些token的处理:
    1. ‘\’, 后面跟的一般是转义符, 作为char处理;
    2. ‘”‘, 后面跟的是字符串, 作为string处理;
    3. ‘+’, 分三种情况:++, +=, + ;
    4. ‘-’, 分四种情况:–, -=, ->, – ;
    5. ‘*’, 分两种情况:*=, * ;
    6. ‘/’, 分两种情况:/=, / ;
    7. ‘%’, 分两种情况:%=, % ;
    8. ‘<’, 分四种情况:<<, <<=, <=, <;
    9. ‘>’, 分四种情况:>>, >>=, >=, >;
    10. ‘!’, 分两种情况:!=, !;
    11. ‘=’, 分两种情况:==, =;
    12. ‘|’, 分三种情况:||, |=, |;
    13. ‘&’, 分三种情况:&&, &=, &;
    14. ‘^’, 分两种情况:^=, ^;
    15. ‘.’, 分三种情况:
      1. ‘.’后面跟着数字, 则作为float处理;
      2. “…”连在一起, 作为ellipse处理;
      3. 单独的’.';
  7. 其余所有的token都直接返回对应的值.

所以主要的难度在于数字的处理和identifer table的管理上.

zhangxuecheng 编译原理

GCC学习笔记—demystifying gcc

2009年4月11日

在网上搜gcc frontend时偶然发现了这份ppt,绝对是gcc入门的最佳资料,强烈推荐。
主要讲了关于build/debug,front-end,middle-end,back-end,包括c,c++和java.
原文出处在这里:
http://www.cs.wustl.edu/~mdeters/oopsla2006/
本地下载地址(pdf):
http://veryzhang.cn/wp-content/uploads/2009/04/demystifying-gcc.pdf


上面这个是2006年的presentation,有点老了,而且附带的源代码也找不到了,后来给作者发了封邮件,这位大哥给了新的地址:

Hi Xuecheng,

I’ve looked and I can’t find these code examples either at the moment.

If I find them, I’ll let you know.  There are also some more recent
tutorial slides here:

http://www.cs.wustl.edu/~mdeters/pldi2008/

And additional resources (slightly older) here:

http://www.cs.wustl.edu/~mdeters/seminar/fall2005/

that give some information about GCC.  Note that the Java front-end
has changed significantly since the 2005 and 2006 courses (in case
you’re looking at the source for a recent GCC compiler).  Other parts
have changed a lot too.

One of the code resources listed for the 2006 course was of jRate, a
real-time Java implementation, based on GCC’s (ahead-of-time-compiled)
Java implementation, that makes modifications to the GCJ compiler and
the libraries, and also a little to the GCC C++ compiler.  The source
modifications of jRate to GCC are open-source, available through
SourceForge:

http://jrate.sourceforge.net/

Take care, and happy hacking!
Morgan

zhangxuecheng GCC学习, 编译原理

lex和yacc学习笔记

2009年4月10日

1.标准的c语法和词法范式只有输出token功能;

2.lex传递给yyac的是token的索引,需要在lex中自己实现一个符号表管理机制,把token的名称记录下来;

3.treelang是在lex中通过get_string函数来获取token的名称,并且由gcc统一管理;

4.每次遇到一个token,treelang都会创建一个新的tok结构体,将这个token赋值到tok结构体中;每一个token都有对应的tok结构体;

5.treelang_parse_file会调用yyparse,然后yyparse会调用yylex;

6.lex文件第二个%%段开始默认就是yylex吗?

7.先执行token识别过程,再执行yylex;实际运行过程是,在token识别之前,先调用YY_RULE_SETUP,这个宏最终的实际定义是YY_DECL,就是yylex;太乱了!

8.yylex被my_yylex调用,my_yylex有被定义成宏YYLEX,YYLEX被yyparse调用;

zhangxuecheng 编译原理