码迷,mamicode.com
首页 > 其他好文 > 详细

Lex中有趣问题

时间:2015-04-13 19:00:00      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:正则   lex   词法分析   注释   

技术分享

Lex和Yacc是Unix下不错的词法分析器和语法分析器,在linux下,这两个工具被成为flex和bison,也是C++经常用来构建字符分析程序的工具。

本文不是一篇入门文章,我们假设您已经了解了Lex和Yacc的基本语法
入门文章请参考IBM的:【Yacc 与 Lex 快速入门】

我们这里讨论一些其有趣的用法和注意的事项

字符串的识别

常规的正则式和匹配问题都难不倒大家,那么下面来想一个问题,C语言中字符串如何识别?

我们知道,字符串一般是这样的

"some \"string\" problem.\n"

但我们会发现其中包含有转移符和引号,如何只是简单的如下书写正则式:

\"[^"]*\"

则会导致引号表达能力不全,不能满足C语言的要求。

所以我们考虑将里面的表达部分拆开,首先,虽然不能有引号,但可以让其有\",所以我们的正则式改完如下:

\"(\\"|[^"])*\"

好的,那么我们可以用这个\"转义引号了,但如何你认为就这样就可以了,那未免有点心急,因为还有很重要的情况,那就是后一半中其实也可以含有\,但其实我们的\实际上是转义符,要成对配套使用,单独用\是不正确的,所以我们应该加上对其的限制,不让\随意出现,那么我们的正则变成了这样:

\"(\\.|[^"\\])*\"

好,这就是我们的C语言字符串识别的正则式了。

注释的识别

恩,解决了棘手的字符串识别难题,那么,又发现了另外的情况,C语言有两种注释,如何正确的识别他们呢?

// hello world

/**
 * hello world
 */

首先第一种较为容易实现,类似上面的方法,只要让注释中不存在换行符就好:

//[^\n]*

但下面一种较为复杂,当然也有简单实现的方式

"/*"([^\*]|(\*)*[^\*/])*(\*)*"*/" 

这个正则式十分复杂,我们分解讲解一下

"/*"   ( [^\*]  |  (\*)*  [^\*/] )*  (\*)*   "*/"

( [^\*] | (\*)* [^\*/] )*这一段是在找所以的非*内容,或者是*后面不是*/的部分,这是被允许的,有人问,为何里面*不能跟*呢?

这是由于一旦可以跟*,下一次匹配就限制不住匹配/开头的了,为了避免这一情况,做出限制,但又由于可能存在末尾连续的*的情况,所以在后面又补充了连续的*

这里,其实使用别的正则引擎,还有简单的解决方案,具体可以参考这篇英文博客:【Finding Comments in Source Code Using Regular Expressions】

另外在Lex的实际使用中,还有一种简便的方式,那就是利用固定的C代码,处理注释的丢弃,方法如下:

"/*"                    comment();

%%

comment()
{
    char c, c1;

loop:
    while ((c = input()) != ‘*‘ && c != 0)
        putchar(c);

    if ((c1 = input()) != ‘/‘ && c != 0)
    {
        unput(c1);
        goto loop;
    }

    if (c != 0)
        putchar(c1);
}

Lex中有趣问题

标签:正则   lex   词法分析   注释   

原文地址:http://blog.csdn.net/xfxyy_sxfancy/article/details/45024573

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!