代码改变世界

Lex写得人都快死了

2008-09-29 01:06  JimLiu  阅读(890)  评论(7编辑  收藏  举报

编译原理课程的“小”作业,十一期间主要任务——Lex

我选择C#写,主要是为了做到后期语法分析和语义分析的时候能应用上面向对象的优势,C++那个面向对象系统我太不熟悉了。

经过2天艰苦卓绝的编码,一天艰苦卓绝的Debug,在无数次把apple123认为是Numeric、把_sl2Jd_3JK认为是保留字后,今天在我手动追踪调试高达65个有向图结点的构造过程中,终于发现了一个相当隐晦的BUG,二话不说改之。整个程序豁然开朗,一下子就可以识别很多符号了。

目前支持的正则运算符有

  1. 或、连接,括号优先级
  2. *闭包,+闭包,?表达式
  3. []内用A-Z表范围的写法
  4. .通配符(除回车、换行以为所有非控制字符)

其他好像还有一两个小的,我忘了,汗一个

再看看我的“处女LEX输出”

int main(){
    
int a, b;
    
char* s="sdfj2098;";
    scanf(
"%d%d"&a, &b);
    printf(
"%d\n", a+b);
    
return 0;
}

上面是源程序

下面是Lex生成的词法分析器的输出

int          ReservedWord
main         Identifier
(            Symbol
)            Symbol
{            Symbol
int          ReservedWord
a            Identifier
,            None
b            Identifier
;            Symbol
char         ReservedWord
*            Symbol
s            Identifier
=            Symbol
"sdfj2098;"  String
;            Symbol
scanf        Identifier
(            Symbol
"%d%d"       String
,            None
&            Symbol
a            Identifier
,            None
&            Symbol
b            Identifier
)            Symbol
;            Symbol
printf       Identifier
(            Symbol
"%d\n"       String
,            None
a            Identifier
+            Symbol
b            Identifier
)            Symbol
;            Symbol
return       ReservedWord
0            Numeric
;            Symbol
}            Symbol

基本上还算正确

还有个大点的,但是不恶心的代码,有两三百行的,基本正确。

这玩意——不怕代码大,就怕代码恶心->_<-

目前最大的缺陷是字符串和注释的屏蔽,还有很多问题要解决。字符串一猥琐点就出问题了,比如"apple\""我就解析不正常了,因为我无法得知那个\"被转义了,我就天真地以为那个"是真的引号……而且一开始没考虑到字符串和注释,以为空格和换行全部都可以用来做定界用,其实在注释和字符串中的空格是完全没有定界作用的,Block Comment里的换行也是无意义的,所以我那个匹配策略就有问题了,因为我把空格和换行全当定界符用了

有个很大的缺点,就是算的慢,一方面和我算法有莫大联系,同时因为用C#,方便是方便了,但是运算量一大起来速度就比C++慢了不止一点两点,从NFA生成DFA的过程中2900个结点用了12秒,还不包括DFA优化的过程——那可是我想了巨久都只能想到O(n^3)的啊。

程序写得奇烂无比,解析正则表达式用了很多巨猥琐的手段,自己都快看不下去了。

到时候要是真要出后端,我就弄个把小型C语言编译成IL代码的,给弄个printf用Console.Write()来耍耍,给它安个class Main一套着,管它面向对象还是面向过程呢,反正纯恶搞, 哈哈 !

明天继续,坚决把那个恶心的匹配策略改了,争取搞定字符串……被编程迷失心智了……