我需要从抽象语法树生成C代码。类型声明很棘手。是否在任何地方写下了相关的算法?
这里以前有几个关于反向发展的问题。我不是要解析C声明,而是要生成它们。
我已经尝试检查cdecl
的代码,这是我所知道的唯一相当简短的程序,但是当我删除所有明显是not生成C声明的代码的代码时,我结束了带有一个空文件,因此我显然在那里丢失了一些内容。
抽象语法树对C类型的语义进行编码,其中节点的类型为:
基本类型(int
,char
等)
指向类型的指针
一种类型的数组(有或没有大小)
函数获取参数类型列表并返回类型
所以问题只是将其呈现为C语法。
如果您能够用C ++实现AST,则STL提供std::type_info::name()
,它返回类型为T
的名称。在包括MSVC在内的某些编译器上,这将返回人类可读的名称。在其他位置,包括gcc
,它返回错误的名称。 GCC提供了一个内置的abi::__cxa_demangle
来对其进行拆解,并为此提供了Boost provides a more portable function,boost::core::demangle
。
要实现运行时多态,可以使用typeid
运算符在运行时获取std::type_info
对象,也可以让每种类型的AST节点都从抽象基类继承。那可能有一个纯虚函数::name()
,其实现可能类似于
#include <boost/core/demangle.hpp>
template<class T>
const char* AST<T>::name() {
return boost::core::demangle( typeid(T).name() );
}
或者使用一堆#ifdef
块来支持不同的编译器的东西。
[如果您想自己动手,these answers提供了一些使用模板元编程在编译时连接常量字符串的方法。会有一些小问题,例如:将限定符(如const
,volatile
和signed
)规范化,将指向T(Args...)
的指针表示为(*T)(Args...)
,并等同于指向数组的指针。如果要通过模板元编程消除所有运行时开销,则可以定义自己的type_name<T>
模板,使用std::enable_if
和<type_traits>
库分别对其进行专门化,并为连接了类型名称的复合类型提供覆盖*
,(
,)
,[
和]
的组件以适当的方式。
用C语言做起来会困难得多。