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

扩展Boost Spirit计算器示例:添加字符串相等比较遇问题求助

修复Boost Spirit Calc示例以支持字符串相等比较

以下是修改后可编译运行的完整代码,支持带引号的字符串字面量及==相等比较:

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/variant.hpp>
#include <string>
#include <iostream>
#include <stdexcept>

namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace ascii = boost::spirit::ascii;

// 定义支持多种类型的值变体
struct eval;
typedef boost::variant<int, std::string, bool> value_type;

// 求值访问器
struct eval : boost::static_visitor<value_type> {
    value_type operator()(int lhs, qi::tag::equal_to, int rhs) const {
        return lhs == rhs;
    }

    value_type operator()(const std::string& lhs, qi::tag::equal_to, const std::string& rhs) const {
        return lhs == rhs;
    }

    // 处理不同类型比较的情况(可选:抛出异常或返回false)
    template <typename T, typename U>
    value_type operator()(const T&, qi::tag::equal_to, const U&) const {
        throw std::runtime_error("类型不匹配,无法执行比较");
        // 若不需要异常,可替换为:return false;
    }

    // 基础值直接返回
    value_type operator()(int n) const { return n; }
    value_type operator()(const std::string& s) const { return s; }
    value_type operator()(bool b) const { return b; }
};

// 辅助求值函数
value_type evaluate(const value_type& v) {
    return boost::apply_visitor(eval(), v);
}

template <typename Iterator>
struct calc_grammar : qi::grammar<Iterator, value_type(), ascii::space_type> {
    calc_grammar() : calc_grammar::base_type(expr) {
        using qi::int_;
        using qi::char_;
        using qi::_val;
        using qi::_1;
        using qi::_2;
        using phoenix::bind;

        // 字符串字面量规则:匹配双引号包裹的任意非引号字符
        string_lit = '"' >> *(char_ - '"') >> '"';

        // 基础值:整数或字符串
        value = int_ | string_lit;

        // 相等表达式:支持value == value
        equal_expr = value[ _val = _1 ]
                    >> (   ('==' >> value[ _val = bind(eval(), _val, qi::tag::equal_to(), _1) ])
                       )*;

        // 表达式入口:若需添加其他运算符,需按优先级调整规则顺序
        expr = equal_expr;
    }

    qi::rule<Iterator, std::string(), ascii::space_type> string_lit;
    qi::rule<Iterator, value_type(), ascii::space_type> value;
    qi::rule<Iterator, value_type(), ascii::space_type> equal_expr;
    qi::rule<Iterator, value_type(), ascii::space_type> expr;
};

int main() {
    typedef std::string::iterator iterator_type;
    calc_grammar<iterator_type> calc;

    std::string input;
    std::cout << "输入表达式(如\"abc\" == \"abc\"): ";
    std::getline(std::cin, input);

    iterator_type iter = input.begin();
    iterator_type end = input.end();

    value_type result;
    bool r = phrase_parse(iter, end, calc, ascii::space, result);

    if (r && iter == end) {
        std::cout << "解析成功,结果: ";
        // 输出结果
        try {
            auto evaluated = evaluate(result);
            boost::apply_visitor([](const auto& v) {
                using namespace std;
                if (holds_alternative<bool>(v)) {
                    cout << boolalpha << get<bool>(v);
                } else if (holds_alternative<int>(v)) {
                    cout << get<int>(v);
                } else if (holds_alternative<string>(v)) {
                    cout << "\"" << get<string>(v) << "\"";
                }
            }, evaluated);
        } catch (const std::exception& e) {
            std::cout << "错误:" << e.what();
        }
        std::cout << std::endl;
    } else {
        std::cout << "解析失败" << std::endl;
    }

    return 0;
}

关键修改说明

  • 扩展值类型:用boost::variant<int, std::string, bool>替代原有的单一数值类型,支持整数、字符串和布尔结果存储。
  • 添加字符串解析规则:string_lit规则匹配双引号包裹的字符串,确保正确提取无引号的字符串内容。
  • 新增相等运算符规则:equal_expr处理==比较逻辑,通过语义动作调用求值访问器完成类型安全的比较。
  • 类型安全的求值访问器:eval结构体重载operator(),分别处理同类型(整数-整数、字符串-字符串)的相等比较,对跨类型比较可选择抛出异常或返回默认值。
  • 规则优先级调整:将相等比较规则作为表达式入口,若后续需添加!=、加减乘除等运算符,需按运算符优先级调整规则定义顺序。

常见编译错误及修复

  1. 类型不匹配错误

    • 原因:原Calc示例的表达式规则仅返回数值类型,扩展后未更新规则的属性类型为value_type。
    • 修复:确保所有规则(如value、equal_expr、expr)的属性都声明为value_type()。
  2. 语义动作中类型提取失败

    • 原因:未用boost::static_visitor正确提取variant中的值,或尝试直接强制转换跨类型值。
    • 修复:使用boost::apply_visitor实现类型安全的访问,避免直接强制转换操作。
  3. 规则定义顺序错误

    • 原因:Spirit要求规则在使用前必须声明,若string_lit在value之后定义会导致编译失败。
    • 修复:按依赖顺序定义规则,先定义基础规则(如string_lit),再定义组合规则(如value)。
  4. 缺少必要头文件

    • 原因:未包含boost/variant.hpp或boost/spirit/include/phoenix.hpp等依赖头文件。
    • 修复:确保代码顶部包含所有所需的Boost Spirit和Variant头文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 10:45:28