然而,一个问题是,当编译器完成并且汇编器开始运行(GNU汇编器(GNU Binutils)2.23.52.20130604)时,它崩溃了;
as: build/src/ast_generate.o: too many sections (33098) /tmp/cc0ZyvKK.s: Assembler messages: /tmp/cc0ZyvKK.s: Fatal error: can't write build/src/ast_generate.o: File too big as: build/src/ast_generate.o: too many sections (33098) /tmp/cc0ZyvKK.s: Fatal error: can't close build/src/ast_generate.o: File too big scons: *** [build/src/ast_generate.o] Error 1
将“-Os”添加到我的编译器标志中,允许汇编程序处理编译器输出,但正如我所看到的,这只是一个时间问题,直到我遇到同样的问题,即使使用小的优化标志.
检查大小优化的对象文件(ast_generate.o)使用objdump,告诉我,我正在生成pe-x86-64,这是我期望在Windows上.
2358生成的部分,对我来说是震惊的.大多数情况下,似乎已经为boost :: spirit的每个部分生成了一个部分;
CONTENTS,ALLOC,LOAD,READONLY,DATA,LINK_ONCE_DISCARD ... 60 .pdata$_ZNK5boost5lexer6detail8end_node9unique_idEv 0000000c 0000000000000000 0000000000000000 00030750 2**2 61 .text$_ZNK5boost5lexer6detail8end_node11lexer_stateEv 00000010 0000000000000000 0000000000000000 0003075c 2**4 ...
所以我的问题是
>错误中的数字(太多的部分(X)),要生成的部分数,还是错误代码?
>为什么为每个数据类型生成一个段?
>我可以做什么,以避免将’-Os’传递给我的编译器.也就是说,如何解决问题,而不是解决问题?
>将词法分析和分析阶段分成两个不同的阶段(和编译单元),只有通过词法迭代器连接才能帮助我?
注意;我正在使用cygwin64进行编译.
解决方法
> https://bitbucket.org/sehe/joos2compiler-refactor(根据你的12d01e5提交).
我希望它不会增加编译次数:)(我没有实际分解语法,但它变小).
特征:
>没有更多的堆分配AST节点(甚至对于树,如表达式和/或语句);因此没有更明确的克隆和/或伪造成员.
>我已经用Maybe.hpp替换了
#pragma once #include <boost/optional.hpp> template <typename T> using Maybe = boost::optional<T>;
它是快速和脏,但它都编译
>我用我自己的小小的努力取代了开放类型切换(我无法得到它的工作;还有boost-variant它全部内置):
namespace visitor_galore // this is my make-shift replacement for typeswitch (I couldn't find it/make it work) { template<typename T,class...Fs> struct visitor_t; template<typename T,class F1,class...Fs> struct visitor_t<T,F1,Fs...> : F1,visitor_t<T,Fs...>::type { typedef visitor_t type; visitor_t(F1 head,Fs...tail) : F1(head),Fs...>::type(tail...) {} using F1::operator(); using visitor_t<T,Fs...>::type::operator(); }; template<typename T,class F> struct visitor_t<T,F> : F,boost::static_visitor<T> { typedef visitor_t type; visitor_t(F f) : F(f) {} using F::operator(); }; template<typename T=void,class...Fs> typename visitor_t<T,Fs...>::type make_visitor(Fs...x) { return {x...}; } } using visitor_galore::make_visitor;
要了解如何使用,请查看ast_pp.cpp:
void pretty_print(expression_incdec const& exp) { boost::apply_visitor( make_visitor( [&exp](inc_dec_op_preinc const& op) { std::cout << "++"; pretty_print(exp.variable); },[&exp](inc_dec_op_predec const& op) { std::cout << "--"; pretty_print(exp.variable); },[&exp](inc_dec_op_postinc const& op) { pretty_print(exp.variable); std::cout << "++"; },[&exp](inc_dec_op_postdec const& op) { pretty_print(exp.variable); std::cout << "--"; } ),exp.operatur); }
奖金如果您不在意分列列表中的所有类型,例如因为它们都默认调用相同的自由函数(或重载),您可以使用多态访问器:
static const struct pretty_print_visitor_ : boost::static_visitor<> { template<typename T> void operator ()(T const& v) const { pretty_print(v); } } pretty_print_visitor;
例如.现在你可以用24个分支替换表达式
boost::apply_visitor( make_visitor( [](expression_binop const& exp) { pretty_print(exp); },[](expression_unop const& exp) { pretty_print(exp); },[](expression_integer_constant const& exp) { pretty_print(exp); },[](expression_character_constant const& exp) { pretty_print(exp); },[](expression_string_constant const& exp) { pretty_print(exp); },[](expression_boolean_constant const& exp) { pretty_print(exp); },[](expression_null const& exp) { pretty_print(exp); },[](expression_this const& exp) { pretty_print(exp); },[](expression_static_invoke const& exp) { pretty_print(exp); },[](expression_non_static_invoke const& exp) { pretty_print(exp); },[](expression_simple_invoke const& exp) { pretty_print(exp); },[](expression_ambiguous_invoke const& exp) { pretty_print(exp); },[](expression_new const& exp) { pretty_print(exp); },[](expression_new_array const& exp) { pretty_print(exp); },[](expression_lvalue const& exp) { pretty_print(exp); },[](expression_assignment const& exp) { pretty_print(exp); },[](expression_incdec const& exp) { pretty_print(exp); },[](expression_cast const& exp) { pretty_print(exp); },[](expression_ambiguous_cast const& exp) { pretty_print(exp); },[](expression_instance_of const& exp) { pretty_print(exp); },[](expression_parentheses const& exp) { pretty_print(exp); },[](lvalue_non_static_field const& exp) { pretty_print(exp); },[](lvalue_array const& exp) { pretty_print(exp); },[](lvalue_ambiguous_name const& exp) { pretty_print(exp); } ),exp);
一个简单的
boost::apply_visitor(pretty_print_visitor,exp);
>注意几次,我已经把// TODO或// FIXME注释(值得注意的是concat,不太想为我编译).
>请注意,Ast类明显更简单(特别是内存分配更为正确)
>请注意,Parser本身由于对语义动作和Phoenix适应功能的需求减少而缩小
>请注意,我现在选择忘记了LexerPosition信息(以前在基类中是“隐藏”的,现在已经消失).有一个编译器教程示例,显示如何使用qi :: on_error(qi :: success,…)非常优雅地将源位置信息附加到所选的Ast节点(非侵入式).
>而不是在ast_helpers中的各种谓词,我预计可能会有一些有用的基于特征的谓词(例如is_lvalue或is_true_const).我选择“保持”帮助者或多或少的原样(这可能是完全错误的,我没有测试任何东西).
>我经常尝试将参数传递值替换为通过const& (compare e.g. the ast_pp.hpp),但我知道我已经留下了一些地方,因为任务足够大,因为它是.
巨额免责声明:我可能以各种方式破解了解析器.我没有试图用它解析任何东西.编辑是按原样提供的,没有任何声明的有用性.我以不同的方式解决了类似的问题(一旦traits :: tranform_attribute>专业化,一次大规模的语义动作和一些其他方法):
我的目标是告诉你,当我提到可能的时候,我在想什么
>显着降低动态多态性,>避免语义行为>在可能的情况下拥抱增强构架,以获得更多的“自动化”与精神融合>显示各种想法,你可以从以下选择你最喜欢的: