有没有办法将spirit::lex字符串标记的内容匹配为spirit::qi语法中的文字

2024-01-08

我正在编写 DSL 并使用 Boost Spirit 词法分析器来标记我的输入。在我的语法中,我想要一个与此类似的规则(其中tok是词法分析器):

header_block =
    tok.name >> ':' >> tok.stringval > ';' >>
    tok.description >> ':' >> tok.stringval > ';'
  ;

我不想为语言指定保留字(例如“名称”、“描述”)并处理词法分析器和语法之间的同步,我只想标记所有匹配的内容[a-zA-Z_]\w*作为单一令牌类型(例如tok.symbol),然后让语法来解决它。如果我weren't使用词法分析器,我可能会这样做:

stringval = lexeme['"' >> *(char_ - '"') >> '"'];
header_block =
    lit("name") >> ':' >> stringval > ';' >>
    lit("description") >> ':' >> stringval > ';'
  ;

通过混合词法分析器,我可以编译以下规则,但当然它比我想要的匹配更多 - 它不关心特定的符号值“名称”和“描述”:

header_block =
    tok.symbol >> ':' >> tok.stringval > ';' >>
    tok.symbol >> ':' >> tok.stringval > ';'
  ;

我正在寻找的是这样的:

header_block =
    specific_symbol_matcher("name") >> ':' >> tok.stringval > ';' >>
    specific_symbol_matcher("description") >> ':' >> tok.stringval > ';'
  ;

Qi 是否提供任何我可以使用的东西来代替我的specific_symbol_matcher挥手,有吗?如果我可以使用提供的东西来接近,我宁愿不编写自己的匹配器。如果我必须编写自己的匹配器,任何人都可以建议如何做到这一点吗?


如果令牌公开 std::string,您应该能够执行以下操作:

 statement =
      ( tok.keyword [ qi::_pass = (_1 == "if")   ] >> if_stmt )
    | ( tok.keyword [ qi::_pass = (_1 == "while) ] >> while_stmt );

如果我理解正确的话,这或多或少就是你所问的。

当你在看的时候,一定要看看qi::symbol<> http://www.boost.org/doc/libs/1_50_0/libs/spirit/doc/html/spirit/qi/reference/string/symbols.html以及它的一个特别巧妙的应用,称为纳比亚莱克把戏 http://boost-spirit.com/home/articles/qi-example/nabialek-trick/.


奖励材料

如果您只是在努力使现有语法与词法分析器一起工作,这就是我刚刚对calc_utree_ast.cpp http://www.boost.org/doc/libs/1_50_0/libs/spirit/example/qi/calc_utree_ast.cpp使其与词法分析器一起使用的示例。

It shows

  • 如何直接使用暴露的属性
  • 只要这些 char 文字注册为(匿名)标记,您仍然可以如何基于 char 文字进行解析
  • 如何对(简单)表达式 gammar 进行最小程度的更改
  • 如何将跳过行为移至词法分析器中
///////////////////////////////////////////////////////////////////////////////
//
//  Plain calculator example demonstrating the grammar. The parser is a
//  syntax checker only and does not do any semantic evaluation.
//
//  [ JDG May 10, 2002 ]        spirit1
//  [ JDG March 4, 2007 ]       spirit2
//  [ HK November 30, 2010 ]    spirit2/utree
//  [ SH July 17, 2012 ]        use a lexer
//
///////////////////////////////////////////////////////////////////////////////

#define BOOST_SPIRIT_DEBUG

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/support_utree.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>

#include <iostream>
#include <string>

namespace lex    = boost::spirit::lex;
namespace qi     = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace phx    = boost::phoenix;

// base iterator type
typedef std::string::const_iterator BaseIteratorT;

// token type
typedef lex::lexertl::token<BaseIteratorT, boost::mpl::vector<char, uint32_t> > TokenT;

// lexer type
typedef lex::lexertl::actor_lexer<TokenT> LexerT;

template <typename LexerT_>
struct Tokens: public lex::lexer<LexerT_> {
   Tokens() {
      // literals
      uint_ = "[0-9]+";
      space = " \t\r\n";

      // literal rules
      this->self += uint_;
      this->self += '+';
      this->self += '-';
      this->self += '*';
      this->self += '/';
      this->self += '(';
      this->self += ')';

      using lex::_pass;
      using lex::pass_flags;
      this->self += space [ _pass = pass_flags::pass_ignore ];
   }

   lex::token_def<uint32_t> uint_;
   lex::token_def<lex::omit> space;
};

namespace client
{
    namespace qi     = boost::spirit::qi;
    namespace ascii  = boost::spirit::ascii;
    namespace spirit = boost::spirit;

    struct expr
    {
        template <typename T1, typename T2 = void>
        struct result { typedef void type; };

        expr(char op) : op(op) {}

        void operator()(spirit::utree& expr, spirit::utree const& rhs) const
        {
            spirit::utree lhs;
            lhs.swap(expr);
            expr.push_back(spirit::utf8_symbol_range_type(&op, &op+1));
            expr.push_back(lhs);
            expr.push_back(rhs);
        }

        char const op;
    };
    boost::phoenix::function<expr> const plus   = expr('+');
    boost::phoenix::function<expr> const minus  = expr('-');
    boost::phoenix::function<expr> const times  = expr('*');
    boost::phoenix::function<expr> const divide = expr('/');

    struct negate_expr
    {
        template <typename T1, typename T2 = void>
        struct result { typedef void type; };

        void operator()(spirit::utree& expr, spirit::utree const& rhs) const
        {
            char const op = '-';
            expr.clear();
            expr.push_back(spirit::utf8_symbol_range_type(&op, &op+1));
            expr.push_back(rhs);
        }
    };
    boost::phoenix::function<negate_expr> neg;

    ///////////////////////////////////////////////////////////////////////////////
    //  Our calculator grammar
    ///////////////////////////////////////////////////////////////////////////////
    template <typename Iterator>
    struct calculator : qi::grammar<Iterator, spirit::utree()>
    {
        template <typename Tokens>
        calculator(Tokens const& toks) : calculator::base_type(expression)
        {
            using qi::_val;
            using qi::_1;

            expression =
                term                            [_val = _1]
                >> *(   ('+' >> term            [plus(_val, _1)])
                    |   ('-' >> term            [minus(_val, _1)])
                    )
                ;

            term =
                factor                          [_val = _1]
                >> *(   ('*' >> factor          [times(_val, _1)])
                    |   ('/' >> factor          [divide(_val, _1)])
                    )
                ;

            factor =
                    toks.uint_                  [_val = _1]
                |   '(' >> expression           [_val = _1] >> ')'
                |   ('-' >> factor              [neg(_val, _1)])
                |   ('+' >> factor              [_val = _1])
                ;

            BOOST_SPIRIT_DEBUG_NODE(expression);
            BOOST_SPIRIT_DEBUG_NODE(term);
            BOOST_SPIRIT_DEBUG_NODE(factor);
        }

        qi::rule<Iterator, spirit::utree()> expression, term, factor;
    };
}

///////////////////////////////////////////////////////////////////////////////
//  Main program
///////////////////////////////////////////////////////////////////////////////
int main()
{
    std::cout << "/////////////////////////////////////////////////////////\n\n";
    std::cout << "Expression parser...\n\n";
    std::cout << "/////////////////////////////////////////////////////////\n\n";
    std::cout << "Type an expression...or [q or Q] to quit\n\n";

    using boost::spirit::utree;
    typedef std::string::const_iterator iterator_type;
    typedef Tokens<LexerT>::iterator_type IteratorT;
    typedef client::calculator<IteratorT> calculator;

    Tokens<LexerT> l;
    calculator calc(l); // Our grammar

    std::string str;
    while (std::getline(std::cin, str))
    {
        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
            break;

        std::string::const_iterator iter = str.begin();
        std::string::const_iterator end  = str.end();
        utree ut;
        bool r = lex::tokenize_and_parse(iter, end, l, calc, ut);

        if (r && iter == end)
        {
            std::cout << "-------------------------\n";
            std::cout << "Parsing succeeded: " << ut << "\n";
            std::cout << "-------------------------\n";
        }
        else
        {
            std::string rest(iter, end);
            std::cout << "-------------------------\n";
            std::cout << "Parsing failed\n";
            std::cout << "stopped at: \"" << rest << "\"\n";
            std::cout << "-------------------------\n";
        }
    }

    std::cout << "Bye... :-) \n\n";
    return 0;
}

对于输入

8*12312*(4+5)

它打印(没有调试信息)

Parsing succeeded: ( * ( * 8 12312 ) ( + 4 5 ) )
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有没有办法将spirit::lex字符串标记的内容匹配为spirit::qi语法中的文字 的相关文章

  • 通过 SocketCAN 进行 boost::asio

    我正在考虑利用升压阿西奥 http www boost org doc libs 1 49 0 doc html boost asio html从a读取数据套接字CAN http en wikipedia org wiki SocketCA
  • 在实体框架拦截器中向 DbScanExpression 添加内部联接

    我正在尝试使用实体框架 CommandTree 拦截器通过 DbContext 向每个查询添加过滤器 为了简单起见 我有两个表 一个称为 User 有两列 UserId 和 EmailAddress 另一个称为 TenantUser 有两列
  • FileStream 构造函数和默认缓冲区大小

    我们有一个使用 NET 4 用 C 编写的日志记录类 我想添加一个构造函数参数 该参数可以选择设置文件选项 WriteThrough http msdn microsoft com en us library system io fileo
  • 更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3

    我正在尝试更改 Qt OpenGL 示例以使用更现代的 opengl 版本 330 似乎合适 所以我做了 在 main cpp 上设置版本和配置文件 设置着色器版本 更改着色器以使用统一 它现在构建没有任何错误 但我只看到一个空白窗口 我错
  • 我如何在 C# .NET(win7 手机)中使用“DataContractJsonSerializer”读入“嵌套”Json 文件?

    我有一个问题 如果我的 json 文件看起来像这样 Numbers 45387 Words 空间桶 我可以很好地阅读它 但是如果它看起来像这样 Main Numbers 45387 Words 空间桶 某事 数字 12345 单词 克兰斯基
  • ASP.NET Web API 客户端 ProgressMessageHandler Post 任务卡在 WinForm 应用程序中

    我在用着HttpClient and ProgressMessageHandler来自MS ASP NET Web API 客户端库 http nuget org packages Microsoft AspNet WebApi Clien
  • 信号处理程序有单独的堆栈吗?

    信号处理程序是否有单独的堆栈 就像每个线程都有单独的堆栈一样 这是在 Linux C 环境中 来自 Linux 手册页signal 7 http kernel org doc man pages online pages man7 sign
  • 如何在 SqlDataReader.Read() 期间从死锁异常中恢复

    我的 NET 应用程序的事件日志显示 它在从 Sql Server 读取数据时偶尔会出现死锁 这种情况通常非常罕见 因为我们已经优化了查询以避免死锁 但有时仍然会发生 过去 我们在调用ExecuteReader函数在我们的SqlComman
  • GCC 和 ld 找不到导出的符号...但它们在那里

    我有一个 C 库和一个 C 应用程序 尝试使用从该库导出的函数和类 该库构建良好 应用程序可以编译 但无法链接 我得到的错误遵循以下形式 app source file cpp text 0x2fdb 对 lib namespace Get
  • 检查 RoutedEvent 是否有任何处理程序

    我有一个自定义 Button 类 当单击它时 打开特定窗口 它总是执行相同的操作 我添加了一个可以在按钮的 XAML 中分配的 Click 事件 就像常规按钮一样 当它被单击时 我想执行 Click 事件处理程序 如果已分配 否则我想执行默
  • 如何在c的case语句中使用省略号?

    CASE expr no commas ELLIPSIS expr no commas 我在c的语法规则中看到了这样的规则 但是当我尝试重现它时 int test float i switch i case 1 3 printf hi 它失
  • cout 和字符串连接

    我刚刚复习了我的 C 我尝试这样做 include
  • 跨多个域的 ASP.NET 会话

    是否有合适的 NET 解决方案来在多个域上提供持久服务器会话 即 如果该网站的用户在 www site1 com 下登录 他们也将在 www site2 com 下登录 安全是我们正在开发的程序的一个问题 Thanks 它是否需要在会话中
  • C++ Streambuf 方法可以抛出异常吗?

    我正在尝试找到一种方法来获取读取或写入流的字符数 即使存在错误并且读 写结束时间较短 该方法也是可靠的 我正在做这样的事情 return stream rdbuf gt sputn buffer buffer size 但如果streamb
  • 矩阵到数组 C#

    这将是转换方阵的最有效方法 例如 1 2 3 4 5 6 7 8 9 into 1 2 3 4 5 6 7 8 9 in c 我在做 int array2D new int 1 2 3 4 5 6 7 8 9 int array1D new
  • 在简单注入器中解析具有自定义参数的类

    我正在使用以下命令创建 WPF MVVM 应用程序简易注射器作为 DI 容器 现在 当我尝试从简单注入器解析视图时遇到一些问题 因为我需要在构造时将参数传递到构造函数中 而不是在将视图注册到容器时 因此这不是适用的 简单注入器将值传递到构造
  • 将 char[][] 转换为 char** 会导致段错误吗?

    好吧 我的 C 有点生疏了 但我想我应该用 C 来做我的下一个 小 项目 这样我就可以对其进行抛光 并且我已经有不到 20 行的段错误了 这是我的完整代码 define ROWS 4 define COLS 4 char main map
  • C++0x中disable_if在哪里?

    Boost 两者都有enable if and disable if 但 C 0x 似乎缺少后者 为什么它被排除在外 C 0x 中是否有元编程工具允许我构建disable if按照enable if 哦 我刚刚注意到std enable i
  • 使我的 COM 程序集调用异步

    我刚刚 赢得 了在当前工作中维护用 C 编码的遗留库的特权 这个dll 公开使用 Uniface 构建的大型遗留系统的方法 除了调用 COM 对象之外别无选择 充当此遗留系统与另一个系统的 API 之间的链接 在某些情况下 使用 WinFo
  • 使用 QtWebEngine 将 C++ 对象暴露给 Qt 中的 Javascript

    使用 QtWebkit 可以通过以下方式将 C 对象公开给 JavascriptQWebFrame addToJavaScriptWindowObject如中所述https stackoverflow com a 20685002 5959

随机推荐

  • 单击时添加 div,然后在每次单击时切换它

    我尝试点击添加 添加的内容将第一次出现 添加后 我想单击 添加 它只会切换 已添加 而不是每次单击时添加 已添加 Jquery function var NewContent div class added Added div add cl
  • 在 Velocity 模板中调用宏函数

    我试图弄清楚如何从速度宏调用返回一个值并将其分配给一个变量 我的宏函数看起来像这样 它曾经是常见的共享宏文件 macro getBookListLink readingTrackerResult readingTrackerResult g
  • Spring Boot + Batch:注入/自动装配的 bean 在 ItemReader 中为 null

    当我尝试自动装配 ItemReader 中的任何 bean 时 我收到 NPE 有人可以帮我解决我哪里出错了吗 谢谢 要求是我想在 ItemReader 中注入 DAO 以从多个源获取数据并创建单个对象 这是我的配置类 Configurat
  • PHP 保护目录不被直接 URL 访问

    我有一个管理员脚本 admin index php 所有的活动都是通过这个完成的index php file 用户在获得程序功能的访问权限之前先登录 SESSION user authenticated 创建并设置为true admin t
  • 扩展 Magic Mouse 的功能:我需要 kext 吗?

    我最近购买了一个妙控鼠标 它非常棒并且充满潜力 不幸的是 它受到软件支持的严重阻碍 我想解决这个问题 我做了很多研究 这些是迄今为止我对事件链的发现 Magic Mouse 向系统发送完整的多点触控事件 多点触控事件在 Multitouch
  • 使用 ExpandableListView/SimpleCursorTreeAdapter 在 UI 线程上运行 SQLite 查询

    我正在开发一个用于显示大量 RSS 源的 Android 应用程序 是的 我知道已经有很多这样的应用程序 要显示的数据由内容提供商支持 我希望向后兼容 API 级别 4 我正在使用一个ExpandableListView显示三个不同 RSS
  • 检查日期约束

    我需要对日期进行检查约束 以便在今天 该日期之后无法输入数据 请指教谢谢大家 尝试这个 ALTER TABLE yourTable ADD CONSTRAINT yourDateTimeColumn CHECK yourDateTimeCo
  • 阻止 mp3 文件在浏览器中流式传输

    我在 apache 服务器上有一个 mp3 我希望当用户访问链接时将其作为文件下载 相反 quicktime 或 google chrome 媒体播放器将尝试传输它 有没有解决这个问题的标题 或者是唯一的选项 右键另存为 Edit这是我的标
  • 在 VS2017 中将依赖程序集包含到 NuGet 包中

    我有一个包含 2 个项目 NET Core 的解决方案 第一个项目 库 包含主程序集 另一个项目 库 包含包含资源 接口和其他内容的程序集 主项目引用了第二个项目 我使用的是 Visual Studio 2017 当我从主项目创建 NuGe
  • 无法让 mysqldump 连接到本地 mysql 实例(错误 2003 / 10061)

    我在 Windows XP 机器上安装了 mysql 5 1 它正在侦听端口 3308 我正在尝试使用 mysqldump gt mysqldump u root pmypassword dbname gt out sql 出现错误 mys
  • 如何使用 Gradle 在 IntelliJ 中设置 SLF4J

    我很难在 IntelliJ 中使用 Gradle 配置 SLF4J 无论我做什么 我都会收到以下消息 SLF4J 无法加载类 org slf4j impl StaticLoggerBinder SLF4J 默认为无操作 NOP 记录器实现
  • 有没有可以重新格式化 C# 代码的工具? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个 最好是 命令行工具 可以在目录树上重新格式化 C 源代码 理想情况下 我应该能够自定义格
  • 如何按日期范围查询Cassandra

    我有一个 Cassandra ColumnFamily 0 6 4 它将包含来自用户的新条目 我想向 Cassandra 查询这些新条目 以便我可以在另一个系统中处理该数据 我的感觉是 我可以使用 TimeUUIDType 作为条目的键 然
  • 世博相机变焦

    这是我第一次在 React Native 中使用捏合手势处理程序 我正在尝试使用 Expo 创建一个可缩放相机 我正在做的是 const handlePinch nativeEvent gt const scale velocity nat
  • 调试帮助 - 交换双向链表的 2 个节点

    您能帮我调试这段代码以交换双链表的两个节点吗 我无法弄清楚我做错了什么 这是代码 dll swap node dll head dll node1 dll node2 dll tmp int flag 0 if node1 gt prev
  • 从每组中选择前 1 行

    我有一个表格列出了已安装的软件版本 id userid version datetime 111 75 10075 2013 03 12 13 40 58 770 112 75 10079 2013 03 12 13 41 01 583 1
  • 没有Mac就无法使用Xamarin吗?

    我在 Windows 10 上使用 Visual Studio 2017 根本没有使用 Mac 当我尝试调试新的 Xamarin 跨平台项目时 VS 尝试找到 Mac 通过 Xamarin 创建跨平台应用程序几乎需要 Mac 吗 是的 您需
  • TypeScript 类型混淆(TypeError:无法读取未定义的属性“切片”)

    我有以下数据csv我的 Angular 项目中的文件也导入了D3 js图书馆 group Nitrogen normal stress banana 12 1 13 poacee 6 6 33 sorgho 11 28 12 triticu
  • 如何使用基于 PHP/MySQL 的脚本来禁止网站的 IP 封锁?

    我有一个相当大的 IP 和 IP 块列表 我想禁止它们 我的列表是分块完成的 目前的格式如下 1 2 3 4 1 2 3 54 5 6 7 8 5 6 7 8 2 3 4 5 2 3 4 116 我正在尝试找到最有效的方法来阻止这些 IP
  • 有没有办法将spirit::lex字符串标记的内容匹配为spirit::qi语法中的文字

    我正在编写 DSL 并使用 Boost Spirit 词法分析器来标记我的输入 在我的语法中 我想要一个与此类似的规则 其中tok是词法分析器 header block tok name gt gt gt gt tok stringval