banner.gif adie's blog
主页 博客 胭脂泪,相留醉,几时重,自是人生长恨水长东
统计
日志总数: 127
评论总数: 123
日志分类
日志归档
最近日志
最近评论
订阅
rss2.gif

atom.gif

google_rss
yc.gif 【技术评论】 阅读 5360 次

C专家编程笔记(二) 分析声明

2007-03-11 17:23:07
    C 语言声明分析规则:
    一 声明从它的名字开始读取,然后按照优先级顺序依次读取。
    二 优先级从高到低依次是:
        1、声明中被括号括起来的部分
        2、后缀操作符号:
            括号 () 表示这是一个函数
            中括号 [] 表示这是一个数组
        3、前缀操作符:
            星号 * 表示“指向…的指针”
    三 如果 const / volatile 关键字的后面紧跟类型说明符,那么它作用于类型说明符。在其他情况下, const / volatile 关键字作用于它左边紧邻的指针星号。


    书中提供了一个分析 C 声明的程序(点此查看该程序)。这是一个非常实用的程序,如果将其嵌入到代码阅读工具中,肯定会为读代码的人提供很大的帮助,因为有些 C 代码中的声明确实够看代码的人喝一壶的了。然而遗憾的是,这个程序并不完美。按照作者的说法,这个程序有以下不完备的地方:
      1、没有错误处理;
      2、处理结构,枚举和联合不到位;
      3、忽略了函数的参数列表;
    实际上这个程序还有一些 BUG, 比如它无法分析书中做为例子的 UNIX signal 函数声明:



    更进一步的,我们希望这个程序能分析 C++ 的声明,能理解成员函数指针,名字空间等内容。再有,作为一个中国人,我希望它能给出中文的描述。

    以上这些理由足够使我重新写一个程序来分析声明了。当然我不想那么原始的去一个字符一个字符分析了。时至今日,我们有更多的工具和库可以使用,正则表达式就是一个不错的选择,但我们还有更好的方法,那就是 boost 的 spirit 库。原来的程序是模拟人分析 C 声明过程来实现的。这次我们从C++ 的语法入手,直接解析语法。

    首先,我们需要得到 C++ 声明的 EBNF 语法表达式,有了 EBNF 表达式就可以直接将其交给 boost::spirit 库去解析了。

    看了一下 C++ 标准的关于声明的语法,太吓人了,放弃吧:

    [gram.dcl.dcl] A.6 Declarations
    declarationseq:
        declaration
        declarationseq
        declaration
    declaration:
        blockdeclaration
        functiondefinition
        templatedeclaration
        explicitinstantiation
        explicitspecialization
        linkagespecification
        namespacedefinition
    blockdeclaration:
        simpledeclaration
        asmdefinition
        namespacealiasdefinition
        usingdeclaration
        usingdirective
    simpledeclaration:
        declspecifierseqopt
        initdeclaratorlistopt
        ;
    declspecifier:
        storageclassspecifier
        typespecifier
        functionspecifier
        friend
        typedef
        declspecifierseq:
        declspecifierseqopt
        declspecifier
    storageclassspecifier:
        auto
        register
        static
        extern
        mutable
    functionspecifier:
        inline
        virtual
        explicit
    typedefname:
        identifier
    typespecifier:
        simpletypespecifier
        classspecifier
        enumspecifier
        elaboratedtypespecifier
        cvqualifier
    simpletypespecifier:
        ::opt nestednamespecifieropt
        typename
        ::opt nestednamespecifier
        template templateid
        char
        wchar_t
        bool
        short
        int
        long
        signed
        unsigned
        float
        double
        void
    typename:
        classname
        enumname
        typedefname
    elaboratedtypespecifier:
        classkey
        ::opt nestednamespecifieropt
        identifier
        enum ::opt nestednamespecifieropt
        identifier
        typename ::opt nestednamespecifier
        identifier
        typename ::opt nestednamespecifier
        templateopt templateid
    enumname:
        identifier
    enumspecifier:
        enum identifieropt { enumeratorlistopt
        }
    enumeratorlist:
        enumeratordefinition
        enumeratorlist
        , enumeratordefinition
    enumeratordefinition:
        enumerator
        enumerator = constantexpression
    enumerator:
        identifier
    namespacename:
        originalnamespacename
        namespacealias
    originalnamespacename:
        identifier
    namespacedefinition:
        namednamespacedefinition
        unnamednamespacedefinition
    namednamespacedefinition:
        originalnamespacedefinition
        extensionnamespacedefinition
    originalnamespacedefinition:
        namespace identifier { namespacebody
        }
    extensionnamespacedefinition:
        namespace originalnamespacename
        { namespacebody
        }
    unnamednamespacedefinition:
        namespace { namespacebody
        }
    namespacebody:
        declarationseqopt
    namespacealias:
        identifier
    namespacealiasdefinition:
        namespace identifier = qualifiednamespacespecifier
        ;
    qualifiednamespacespecifier:
        ::opt nestednamespecifieropt
        namespacename
    usingdeclaration:
        using typenameopt ::opt nestednamespecifier
        unqualifiedid
        ;
        using :: unqualifiedid
        ;
    usingdirective:
        using namespace ::opt nestednamespecifieropt
        namespacename
        ;
    asmdefinition:
        asm ( stringliteral
        ) ;
    linkagespecification:
        extern stringliteral
        { declarationseqopt
        }
        extern stringliteral
        declaration
    [gram.dcl.decl] A.7 Declarators
    initdeclaratorlist:
        initdeclarator
        initdeclaratorlist
        , initdeclarator
    initdeclarator:
        declarator initializeropt
    declarator:
        directdeclarator
        ptroperator
        declarator
    directdeclarator:
        declaratorid
        directdeclarator
        ( parameterdeclarationclause
        ) cvqualifierseqopt
        exceptionspecificationopt
        directdeclarator
        [ constantexpressionopt
        ]
        ( declarator )
    ptroperator:
        * cvqualifierseqopt
        &
        ::opt nestednamespecifier
        * cvqualifierseqopt
    cvqualifierseq:
        cvqualifier
        cvqualifierseqopt
    cvqualifier:
        const
        volatile
    declaratorid:
        idexpression
        ::opt nestednamespecifieropt
        typename
    typeid:
        typespecifierseq
        abstractdeclaratoropt
    typespecifierseq:
        typespecifier
        typespecifierseqopt
    abstractdeclarator:
        ptroperator
        abstractdeclaratoropt
        directabstractdeclarator
    directabstractdeclarator:
        directabstractdeclaratoropt
        ( parameterdeclarationclause
        ) cvqualifierseqopt
        exceptionspecificationopt
        directabstractdeclaratoropt
        [ constantexpressionopt
        ]
        ( abstractdeclarator
        )
    parameterdeclarationclause:
        parameterdeclarationlistopt
        …opt
        parameterdeclarationlist
        , …
    parameterdeclarationlist:
        parameterdeclaration
        parameterdeclarationlist
        , parameterdeclaration
    parameterdeclaration:
        declspecifierseq
        declarator
        declspecifierseq
        declarator = assignmentexpression
        declspecifierseq
        abstractdeclaratoropt
        declspecifierseq
        abstractdeclaratoropt
        = assignmentexpression
    functiondefinition:
        declspecifierseqopt
        declarator ctorinitializeropt
        functionbody
        declspecifierseqopt
        declarator functiontryblock
    functionbody:
        compoundstatement
    initializer:
        = initializerclause
        ( expressionlist
        )
    initializerclause:
        assignmentexpression
        { initializerlist
        ,opt }
        { }
    initializerlist:
        initializerclause
        initializerlist
        , initializerclause

▲评论

› 网友 adie () 于 2007-03-14 09:38:26 发表评论说:
linux 下有 cdecl 程序: http://www.linuxcommand.org/man_pages/cdecl1.html
X 正在回复:
姓 名: 留下更多信息
性 别:
邮 件:
主 页:
Q Q:
来 自:
职 业:
评 论:
验 证:


Valid HTML 4.01 Strict Valid CSS!
Copyleft.A!die Software Studio.ADSS
Power by webmaster@adintr.com