adie's blog |
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
|