Has*_*yed 6 parsing peg boost-spirit lpeg
所以我正在玩lpeg来取代一个提升精神语法,我必须说boost :: spirit比lpeg更优雅和自然.然而,由于当前C++编译器技术的限制以及C++中的TMP问题,它是一个麻烦.在这种情况下,类型机制是你的敌人,而不是你的朋友.另一方面,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
Run Code Online (Sandbox Code Playgroud)
这个语法(尽管不完整)与以下内容相符namespace foo {}.我想实现以下语义(这是使用boost精神时的常见用例).
namespace IDENTIFIER {匹配后,将名称空间数据结构添加到此局部变量.NAMESPACE_BODY给进一步构建AST ...依此类推.我确信这个用例是可以实现的.没有例子表明它.我不知道语言或图书馆足以弄清楚如何去做.有人可以显示它的语法.
编辑:经过几天尝试与lpeg一起跳舞,并让我的脚步上,我决定回到精神上:D很明显lpeg是用lua函数编织的,而且这种编织非常自由-form(而精神有明确记录的语义).我还没有正确的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
}
Run Code Online (Sandbox Code Playgroud)
lpeg.match( NS, 'namespace foo {}' )会给:
table#1 {
["entries"] = table#2 {
},
["id"] = "foo",
}
Run Code Online (Sandbox Code Playgroud)
lpeg.match( NS, 'namespace foo {AA}' )会给:
table#1 {
["entries"] = table#2 {
"AA"
},
["id"] = "foo",
}
Run Code Online (Sandbox Code Playgroud)
lpeg.match( NS, 'namespace foo {AA, _BB}' )会给:
table#1 {
["entries"] = table#2 {
"AA",
"_BB"
},
["id"] = "foo",
}
Run Code Online (Sandbox Code Playgroud)
lpeg.match( NS, 'namespace foo {AA, _BB, CC1}' )会给:
table#1 {
["entries"] = table#2 {
"AA",
"_BB",
"CC1"
},
["id"] = "foo",
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
906 次 |
| 最近记录: |