You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Boost.Spirit X3解析器‘no type named type’错误排查求助

Boost.Spirit X3: Compilation Error with Custom AST for Semicolon-Separated Statements

Let's break down what's causing your compilation error and fix it step by step.

The Root Cause

Your error stems from how Spirit X3 handles attribute mapping for your custom ast::program struct. Here's the issue:

  • Your program_def rule uses a Kleene star (*) to parse zero or more statements (each being *char_ > ';'), which naturally produces a std::list<std::string> attribute.
  • But you've bound this rule to a x3::rule targeting ast::program—a fusion-adapted struct containing a std::list<std::string> member, not a container itself.
  • X3 sees the outer * and tries to treat ast::program like a directly fillable container (looking for a value_type trait), which it isn't—hence the error about missing value_type in client::ast::program.

The Fixes

We need to explicitly tell X3 how to map the parsed std::list<std::string> to your ast::program struct. Here are two clean ways to do this:

Option 1: Use x3::attr_cast to Bridge the Attribute Types

Modify your grammar definition to cast the parsed list into your AST struct:

namespace client { namespace grammar {
x3::rule<class program, ast::program> const program("program");
// Explicitly cast the list<string> result to ast::program
auto const program_def = x3::attr_cast<ast::program>(*((*char_) > ';'));
BOOST_SPIRIT_DEFINE( program );
auto calculator = program;
} using grammar::calculator; }

Option 2: Split Rules for Clarity

If you prefer more explicit separation, split the parsing into a rule for the statement list and another to wrap it into your AST:

namespace client { namespace grammar {
// First, a rule that parses the list of statements (returns list<string>)
x3::rule<class stmt_list, std::list<std::string>> const stmt_list("stmt_list");
auto const stmt_list_def = *((*char_) > ';');
BOOST_SPIRIT_DEFINE(stmt_list);

// Then, a rule that wraps the list into your AST struct
x3::rule<class program, ast::program> const program("program");
auto const program_def = x3::attr_cast<ast::program>(stmt_list);
BOOST_SPIRIT_DEFINE(program);

auto calculator = program;
} using grammar::calculator; }

Bonus: Fix Statement Parsing to Preserve Spaces

Right now, your *char_ will skip spaces (because you're using phrase_parse with a space skipper), meaning input like hello world; test; will be parsed as helloworld and test instead of preserving the space. To fix this, wrap the character parser in x3::lexeme to disable the skipper for the statement content:

// Parse a single statement (preserves internal spaces)
auto const stmt = x3::lexeme[*x3::char_];
// Update the statement list rule to use this
auto const stmt_list_def = *(stmt > ';');

Why This Works

The x3::attr_cast tells X3 how to convert the attribute produced by the inner parser (std::list<std::string>) into your target ast::program type. Since you've already adapted the struct with BOOST_FUSION_ADAPT_STRUCT, X3 knows to assign the list to the stmts member automatically.

Modified Full Grammar Example

Putting it all together, your grammar would look like this:

namespace client { namespace grammar {
x3::rule<class stmt_list, std::list<std::string>> const stmt_list("stmt_list");
auto const stmt = x3::lexeme[*x3::char_];
auto const stmt_list_def = *(stmt > ';');
BOOST_SPIRIT_DEFINE(stmt_list);

x3::rule<class program, ast::program> const program("program");
auto const program_def = x3::attr_cast<ast::program>(stmt_list);
BOOST_SPIRIT_DEFINE(program);

auto calculator = program;
} using grammar::calculator; }

内容的提问来源于stack exchange,提问作者rav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:39:39