@encode指令返回一个const char*,它是传入的数据类型的各种元素的编码类型描述符.示例如下:
struct test { int ti ; char tc ; } ; printf( "%s", @encode(struct test) ) ; // returns "{test=ic}"
我可以看到使用sizeof()来确定原始类型 - 如果它是一个完整的对象,我可以使用类方法进行内省.
但是,它如何确定不透明结构的每个元素?
@Lothars的答案可能是"玩世不恭",但不幸的是,它非常接近标记.为了实现类似的东西@encode()
,你需要一个完整的解析器来提取类型信息.好吧,至少除了"琐碎"的@encode()
陈述之外的任何事情(即@encode(char *)
).现代编译器通常有两个或三个主要组件:
前端.
中间端(对于某些编译器).
后端.
前端必须解析所有源代码,并基本上将源代码文本转换为内部的"机器可用"形式.
后端将内部的"机器可用"表单转换为可执行代码.
具有"中间端"的编译器通常会因为某些需要而这样做:它们支持多个"前端",可能由完全不同的语言组成.另一个原因是简化优化:所有优化过程都在相同的中间表示上工作.所述gcc
编译器套件是一个"三个阶段"的编译器的一个例子. llvm
可以被认为是"中间和后端"阶段编译器:"低级虚拟机"是中间表示,所有优化都以这种形式进行. llvm
也能够将它保持在这个中间表示中直到最后一秒 - 这允许"链接时间优化".所述clang
编译器是一个真正的"前端"的是(有效地)输出llvm
的中间表示.
因此,如果要向@encode()
"现有"编译器添加功能,则可能必须将其作为"源到源""编译器/预处理器".这就是原始Objective-C和C++编译器的编写方式 - 他们解析了输入源文本并将其转换为"plain C",然后将其输入到标准C编译器中.有几种方法可以做到这一点:
使用yacc
和lex
组合ANSI-C解析器.你需要一个语法 - ANSI C语法(Yacc)是一个好的开始.实际上,要说清楚,当我说yacc
,我真的是指 野牛和flex
.而且,松散的,其他各种yacc
与lex
像基于C语言的工具:柠檬,的DParser,等...
使用perl
与亚普或EYapp,这是假yacc
的克隆perl
.对比起基于C语言的快速原型设计的想法可能是更好的yacc
和lex
它的- perl
正则表达式,关联数组,没有内存管理等:毕竟
使用Antlr构建解析器.我对这个工具链没有任何经验,但它是另一个"编译器编译器"工具(似乎)更适合Java开发人员.似乎有免费提供的C和Objective-C语法.
注意:我没有使用任何这些工具做任何添加的个人经验@encode()
,但我怀疑它们会有很大的帮助.
CIL - 没有使用此工具的个人经验,但设计用于解析C源代码,然后用它"做事".从我可以从文档中收集到的内容,此工具应该允许您提取您需要的类型信息.
稀疏 - 值得看,但不确定.
铿锵 - 没有用它来达到这个目的,但据称其中一个目标就是让这种东西"容易被黑客攻击".特别是(再次,没有个人经验)在做所有解析的"繁重",让你专注于"有趣"部分,在这种情况下将提取上下文和语法敏感类型信息,然后转换为到一个普通的C字符串.
gcc插件 - 插件是gcc 4.5(编译器的当前alpha/beta版本)功能,"可能"允许您轻松地连接到编译器以提取您需要的类型信息.不知道插件架构是否允许这种事情.
Coccinelle - 最近将其标记为"稍后再看".这"可能"能够做你想做的事情,并且"可能"能够付出很多努力.
MetaC - 最近也将此书加入了书签.不知道这会有多大用处.
mygcc - "可能"做你想做的事.这是一个有趣的想法,但它不能直接适用于你想要的东西.从网页:"Mygcc允许程序员添加自己的检查,考虑语法,控制流和数据流信息."
CocoaDev Objective-C解析 - 值得关注.有一些词法和词法的链接.
@Lothar在他的评论中提出了一个很好的观点.我实际上打算包括lcc
,但看起来它在途中迷路了.
lcc - lcc
C编译器.这是一个特别小的C编译器,至少在源代码大小方面.它还有一本书,我强烈推荐.
tcc - tcc
C编译器.不像教学那样lcc
,但绝对值得一看.
poc - poc
Objective-C编译器.这是一个"源到源"Objective-C编译器.它解析Objective-C源代码并发出C源代码,然后传递给它gcc
(通常gcc
).有许多不可用的Objective-C扩展/功能gcc
.绝对值得一看.