首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用LPEG (Lua Parser表达式语法),如boost::spirit

使用LPEG (Lua Parser表达式语法),如boost::spirit
EN

Stack Overflow用户
提问于 2011-11-01 15:20:52
回答 1查看 1.1K关注 0票数 6

所以我用lpeg来代替一种促进精神的语法,我必须说:精神远比lpeg更优雅和自然。然而,由于当前C++编译器技术的限制和C++中的TMP问题,这是一个很难解决的问题。在这种情况下,类型机制是你的敌人而不是你的朋友。另一方面,在丑陋和基本的结果,更多的生产力。

总之,我在离题,我的lpeg语法的一部分看起来如下:

代码语言:javascript
复制
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精神时)。

  1. 为名称空间规则创建一个局部变量。
  2. 在匹配namespace IDENTIFIER {时向该局部变量添加名称空间数据结构。
  3. 将新创建的名称空间数据结构传递给NAMESPACE_BODY以进一步构造
  4. .等等。

我相信这个用例是可以实现的。没有任何例子表明这一点。我不太懂语言或图书馆,不知道该怎么做。有人能展示一下它的语法吗。

编辑:在尝试与lpeg共舞几天之后,我决定回到精神:D很明显,lpeg是要与lua函数编织的,这种编织是非常自由的形式(而灵性有非常清晰的文档化的语义)。我只是还没有正确的lua心理模型。

EN

回答 1

Stack Overflow用户

发布于 2020-09-22 00:23:33

虽然“为命名空间规则创建一个局部变量”听起来像“上下文敏感语法”(这并不真正适用于LPEG ),但我将假设您希望构建一个抽象语法树。

在Lua中,AST可以表示为嵌套表(带有命名字段和索引字段)或闭包,可以执行树要执行的任何任务。

两者都可以通过嵌套LPEG捕获的组合产生。

我将把这个答案限制在AST作为Lua表。

最有用的,在这种情况下,LPEG捕获将是:

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

以下基于代码的示例将生成一个简单的语法树作为Lua表:

代码语言:javascript
复制
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 {“条目”= table#2 { },"id“= "foo",}

  • lpeg.match( NS, 'namespace foo {AA}' )将给出: table#1 {“条目”= table#2 { "AA“},"id”= "foo",}

  • lpeg.match( NS, 'namespace foo {AA, _BB}' )将给出: table#1 {“条目”= table#2 { "AA“、"_BB”}、"id“= "foo”、}

  • lpeg.match( NS, 'namespace foo {AA, _BB, CC1}' )将给出: table#1 {“条目”= table#2 { "AA“、"_BB”、"CC1“}、"id”= "foo“、}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7968688

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档