gpt4 book ai didi

parsing - 使用 LPEG (Lua Parser Expression Grammars) 像 boost::spirit

转载 作者:行者123 更新时间:2023-12-03 14:51:44 28 4
gpt4 key购买 nike

所以我在玩 lpeg 来代替 boost 精神语法,我必须说 boost::spirit 比 lpeg 更优雅和自然。然而,由于当前 C++ 编译器技术的限制和 C++ 中的 TMP 问题,它很难使用。在这种情况下,类型机制是你的敌人而不是你的 friend 。另一方面,Lpeg 虽然丑陋和基本,但可以提高生产力。

无论如何,我离题了,我的 lpeg 语法的一部分如下所示:

function get_namespace_parser()
local P, R, S, C, V =
lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.V

namespace_parser =
lpeg.P{
"NAMESPACE";
NAMESPACE = V("WS") * P("namespace") * V("SPACE_WS") * V("NAMESPACE_IDENTIFIER")
* V("WS") * V("NAMESPACE_BODY") * V("WS"),

NAMESPACE_IDENTIFIER = V("IDENTIFIER") / print_string ,
NAMESPACE_BODY = "{" * V("WS") *
V("ENTRIES")^0 * V("WS") * "}",


WS = S(" \t\n")^0,
SPACE_WS = P(" ") * V("WS")
}
return namespace_parser
end

这个语法(虽然不完整)匹配以下 namespace foo {} .我想实现以下语义(这是使用 boost 精神时的常见用例)。
  • 为命名空间规则创建一个局部变量。
  • namespace IDENTIFIER { 时向这个局部变量添加命名空间数据结构已匹配。
  • 将新创建的命名空间数据结构传递给 NAMESPACE_BODY用于进一步构建 AST ......等等。

  • 我确信这个用例是可以实现的。没有例子显示它。我不太了解语言或图书馆,无法弄清楚如何去做。有人可以展示它的语法吗?

    编辑:在尝试与 lpeg 共舞几天后,我决定重新振作起来 :D 很明显 lpeg 是用 lua 函数编织的,这种编织是非常自由的形式(而精神有明确的、有据可查的语义)。我只是还没有正确的 lua 心智模型。

    最佳答案

    尽管“为命名空间规则创建一个局部变量”听起来很像“上下文相关语法”,但这并不真正适用于 LPEG,但我会假设您想要构建一个抽象语法树。
    在 Lua 中,AST 可以表示为嵌套表(具有命名和索引字段)或闭包,执行该树打算执行的任何任务。
    两者都可以通过嵌套 LPEG 捕获的组合产生。
    我将把这个答案限制为 AST 作为 Lua 表。
    在这种情况下,最有用的 LPEG 捕获将是:

  • lpeg.C( pattern ) -- 简单捕获,
  • lpeg.Ct( pattern ) -- 表格捕获,
  • lpeg.Cg( pattern, name ) -- 命名组捕获。

  • 以下基于您的代码的示例将生成一个简单的语法树作为 Lua 表:
    local lpeg = require'lpeg'
    local P, V = lpeg.P, lpeg.V
    local C, Ct, Cg = lpeg.C, lpeg.Ct, lpeg.Cg
    local locale = lpeg.locale()
    local blank = locale.space ^ 0
    local space = P' ' * blank
    local id = P'_' ^ 0 * locale.alpha * (locale.alnum + '_') ^ 0

    local NS = P{ 'ns',
    -- The upper level table with two fields: 'id' and 'entries':
    ns = Ct( blank * 'namespace' * space * Cg( V'ns_id', 'id' )
    * blank * Cg( V'ns_body', 'entries' ) * blank ),
    ns_id = id,
    ns_body = P'{' * blank
    -- The field 'entries' is, in turn, an indexed table:
    * Ct( (C( V'ns_entry' )
    * (blank * P',' * blank * C( V'ns_entry') ) ^ 0) ^ -1 )
    * blank * P'}',
    ns_entry = id
    }
  • lpeg.match( NS, 'namespace foo {}' )会给:
    table#1 {
    ["entries"] = table#2 {
    },
    ["id"] = "foo",
    }
  • lpeg.match( NS, 'namespace foo {AA}' )会给:
    table#1 {
    ["entries"] = table#2 {
    "AA"
    },
    ["id"] = "foo",
    }
  • lpeg.match( NS, 'namespace foo {AA, _BB}' )会给:
    table#1 {
    ["entries"] = table#2 {
    "AA",
    "_BB"
    },
    ["id"] = "foo",
    }
  • lpeg.match( NS, 'namespace foo {AA, _BB, CC1}' )会给:
    table#1 {
    ["entries"] = table#2 {
    "AA",
    "_BB",
    "CC1"
    },
    ["id"] = "foo",
    }
  • 关于parsing - 使用 LPEG (Lua Parser Expression Grammars) 像 boost::spirit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7968688/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com