内部编译错误,而使用增强精神x3
Internal compiler error, while using boost spirit x3
我目前正在为我的DSL实现表达式和操作符层次结构,使用boost spirit X3。
我认为我的解析器在语义上是正确的,但是当我尝试编译它时,在编译时,gcc和clang有巨大的内存占用,编译无限的时间,然后退出"g++:内部编译器错误:Killed (program cc1plus)"。
我试图最小化表达式解析器周围的代码,但它不知何故不是琐碎的
这是一个演示。
谁能告诉我我在这里做错了什么,或者这是一个bug?
编辑:我认为问题出在这里:
auto const idx = as<ast::Operation>(helper::idxaccess_op > expression > ']');
auto const func = as<ast::Operation>(helper::func_call_op > expression%',' > ')');
auto const data = as<ast::Operation>(helper::access_op > expression);
auto const func_call_expr_def =
primary_expr >> *(idx|func|data);
如果我将(idx|func|data)
更改为(idx|func)
,它也会永远编译并使用多达16GB的ram,但是gcc能够编译它,并且解析器应该如何工作。
编辑二:请看看上面的链接,这是我的例子,导致错误。
我已经在你的源文件上做了一堆更改。请在http://melpon.org/wandbox/permlink/sY2CQkXiMiLoS1BM查看
变化如下:
- 更改AST。它似乎不正确。主要是在变体中加入'Unary'的部分。
- 更正语法。这是基于我对你考试中语法的理解。我可能错了,我只试过让第一个测试用例工作。最好运行一个diff工具来比较我的修改和你的,特别是在'parser.hpp'
注意:如果我的更改不符合您的要求,我建议您启用调试'BOOstrongPIRIT_X3_DEBUG'并跟踪它。BOOstrongPIRIT_X3_DEBUG在这种情况下非常有用。
parser.hpp
#include <boost/spirit/home/x3.hpp>
#include "ast.hpp"
#include "operators.hpp"
namespace parser{
namespace x3 = boost::spirit::x3;
template<typename T>
auto as = [](auto p) { return x3::rule<struct _, T>{} = as_parser(p); };
typedef x3::rule<struct multiplicative_expr_class, ast::Expression> multiplicative_expr_type;
typedef x3::rule<struct expression_class, ast::Expression> expression_type;
typedef x3::rule<struct primary_expr_class, ast::Operand> primary_expr_type;
typedef x3::rule<struct func_call_call_class, ast::Expression> func_call_expr_type;
typedef x3::rule<struct unary_expr_class, ast::Operand> unary_expr_type;
const primary_expr_type primary_expr = "primary_expr";
const func_call_expr_type func_call_expr = "func_call_expr";
const expression_type expression = "expression";
const multiplicative_expr_type multiplicative_expr = "multiplicative_expr";
const unary_expr_type unary_expr = "unary_expr";
auto const primary_expr_def =
+(x3::alpha | x3::char_('.'))
| ( "(" > expression > ")" );
auto const idx = as<ast::Operation>(helper::idxaccess_op > primary_expr > ']');
auto const func = as<ast::Operation>(helper::func_call_op > primary_expr%',' > ')');
auto const data = as<ast::Operation>(helper::access_op > expression);
auto const func_call_expr_def =
primary_expr >> *( idx | func | data );
auto const unary_expr_def =
func_call_expr
| as<ast::Operation>(helper::unary_op > func_call_expr);
auto const multiplicative_expr_def =
primary_expr >> *(idx | func);
auto const expression_def = multiplicative_expr_def;
BOOST_SPIRIT_DEFINE(primary_expr,
func_call_expr,
multiplicative_expr,
unary_expr,
expression);
}
ast.hpp
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <vector>
namespace ast{
namespace x3 = boost::spirit::x3;
enum class operator_t
{
_eq_, // ==
_ne_, // !=
_lt_, // <
_gt_, // >
_le_, // <=
_ge_, // >=
_add_, // +
_sub_, // -
_mul_, // *
_div_, // /
_mod_, // %
_pos_, // unary +
_neg_, // unary -
_not_, // unary !
_size_, // unary #
_bitnot_, // unary ~
_bitand_, // &
_bitor_, // |
_bitxor_, // ^
_shl_, // <<
_shr_, // >>
_and_, // &&
_or_, // ||
_idx_, // []
_apply_, // ()
_access_ // .
};
struct nil{};
struct Expression;
typedef x3::variant<
nil,
std::string,
x3::forward_ast<Expression>
//std::vector<Expression> //adding this as an operand for function parameter
> Operand;
struct Operation {
operator_t operator_;
Operand operand_;
};
struct Expression {
Operand first_;
std::vector<Operation> rest_;
};
}
BOOST_FUSION_ADAPT_STRUCT(ast::Operation, operator_, operand_)
BOOST_FUSION_ADAPT_STRUCT(ast::Expression, first_, rest_)
这个问题与模板实例化深度有关。为了避免internal compiler error
,并获得可接受的编译时间,对于我的解析器,我必须实现类似模板防火墙的东西,这是作为自定义解析器实现的,它在解析表达式中调用非模板化函数。
struct OptimizedExpressionParser : x3::parser<OptimizedExpressionParser> {
using attribute_type = ast::Expression;
static bool const has_attribute = true;
//parse fnction, which calls "non-templated"-firewall function
template <typename Iter, typename Ctx, typename Attribute>
bool parse(Iter& iFirst, const Iter& iLast, const Ctx& iCtx, x3::unused_type, Attribute& oAttr) const {
ast::Expression a;
return parse(iFirst, iLast, iCtx, x3::unused, a);
}
//parse fnction, which calls "non-templated"-firewall function
template <typename Iter, typename Ctx>
bool parse(Iter& iFirst, const Iter& iLast, const Ctx& iCtx, x3::unused_type, ast::Expression& oAttr) const {
if (iFirst != iLast) {
return parse_expression(iFirst, iLast, oAttr);
}
return false;
}
private:
//"non-template"- parse function
//of cause this is a template function, but the parser isnt a template argument
template <typename Iter>
bool parse_expression(Iter& iFirst, const Iter& iLast, ast::Expression& oAst) const {
return x3::parse(iFirst, iLast, expression_impl, oAst);
}
};
在此代码expression_impl
是旧的"重"表达式解析器,新的"防火墙"表达式解析器如下:
auto const expression = OptimizedExpressionParser{};
当我想在另一个解析器中使用表达式时,或者进行解析时,我现在使用OptimizedExpressionParser
解析器中的expression
对象。这减少了内存使用、编译时间和生成的二进制文件的大小(没有模板防火墙的时候大约是1.6 Gb)。要查看我的示例是如何工作的,请查看这里。
老实说,我自己从来没有解决过这个问题,这个想法和大部分代码都来自这里,我只是改变了一点,以解决我给出的例子。
- 无法将结构注册为增强几何体3D点
- 增强基于 XML class_id的反序列化
- 增强精神解析器规则以检测语句中的特殊结尾
- C++ 使用增强正则表达式库时断言崩溃
- 提升精神 x3 - 懒惰解析器
- boost::spirit::x3 中的通用解析器生成器
- 增强精神 X3:错误:在"..."中没有名为"大小"的类型
- 如何包装(撰写)增强 hana 地图并访问括号运算符(运算符 [])?
- 有没有办法在C ++中检测汉字?(使用增强)
- 如何将增强MSM与增强信号结合使用?
- 提升精神 x3 解析为结构,如果它为空,则跳过成员
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- Boost Spirit X3:将(一些)空格解析为枚举
- Boost Spirit x3 条件(三元)运算符解析器
- 你如何从 Boost Spirit X3 词法解析器中获取字符串?
- 如何使用增强::几何计算多边形的旋转固体体积?
- 增强精神X3不编译
- 使用增强精神 X3 解析特征矩阵
- 使用增强精神 X3 解析变体地图
- 内部编译错误,而使用增强精神x3