キキジ*_*キジキ 4 lua peg first-order-logic lpeg
正如标题所说,我正在尝试解析例如
term(A, b, c(d, "e", 7))
Run Code Online (Sandbox Code Playgroud)
在Lua表中
{term, {A, b, {c, {d, "e", 7}}}}
Run Code Online (Sandbox Code Playgroud)
这是我建立的语法:
local pattern = re.compile[=[
term <- variable / function
argument <- variable / lowercase /number / string
function <- {|lowercase {|(open argument (separator (argument / function))* close)?|}|}
variable <- uppercase
lowercase <- {[a-z][A-Za-z0-9]*}
uppercase <- {[A-Z][A-Za-z0-9]*}
string <- '"' {~ [^"]* ~} '"'
number <- {[0-9]+}
close <- blank ")"
open <- "(" blank
separator <- blank "," blank
blank <- " "*
]=]
Run Code Online (Sandbox Code Playgroud)
我遇到以下问题:
{term, {} }(虽然它没有问题term(A, b, c)).{~ ~},但因为我不得不将所有捕获的移动argument和term在下面的行.有办法避免这种情况吗?A像{value = "A", type = "variable"}.我发现了一种与要做到这一点{:name: :},但是,在表中元素的顺序丢失(因为它不创建一个新表,但只是增加了一个关键,在这种情况下variable="A",该元素的顺序不是固定的).如何标记维护订单的商品?在你的语法中你有:
argument <- variable / lowercase /number / string
function <- {|lowercase {|(open argument (separator (argument / function))* close)?|}|}
Run Code Online (Sandbox Code Playgroud)
请记住,lpeg会按照您拥有的顺序尝试匹配规则中的模式/谓词.一旦找到匹配,即使稍后可能存在"更好"的匹配,lpeg也不会考虑该语法规则中的其他可能匹配.
这里它无法匹配嵌套函数调用,因为它看到它c可以匹配
`argument <- variable`
Run Code Online (Sandbox Code Playgroud)
由于variable之前列出了非终端function,lpeg不考虑后者,因此它会停止解析之后的令牌.
作为一个实验,我稍微修改了你的语法,并为你感兴趣的大多数非终端添加了一些表和命名的捕获.
local pattern = re.compile
[=[
term <- {| {:type: '' -> "term" :} term_t |}
term_t <- func / var
func <- {| {:type: '' -> "func":} {:name: func_id:} "(" arg(separator arg)* ")" |}
func_id <- lower / upper
arg <- number / string / term_t
var <- {| {:type: '' -> "var" :} {:name: lower / upper:} |}
string <- '"' {~ [^"]* ~} '"'
lower <- {%l%w*}
upper <- {%u%w*}
number <- {%d+}
separator <- blank "," blank
blank <- " "*
]=]
Run Code Online (Sandbox Code Playgroud)
通过快速模式测试:
local test = [[fun(A, b, c(d(42), "e", f, 7))]]
dump( pattern:match(test) )
Run Code Online (Sandbox Code Playgroud)
这在我的机器上提供以下输出:
{
{
{
type = "var",
name = "A"
},
{
type = "var",
name = "b"
},
{
{
"42",
type = "func",
name = "d"
},
"e",
{
type = "var",
name = "f"
},
"7",
type = "func",
name = "c"
},
type = "func",
name = "fun"
},
type = "term"
}
Run Code Online (Sandbox Code Playgroud)
在上面仔细看,你会发现,函数的参数出现在他们在获得通过的顺序表的索引的一部分.OTOH的type和name,因为它是在表中的关联部分可以以任意顺序出现.您可以将这些"属性"包装在另一个表中,并将该内部属性表放在外部表的索引部分中.
编辑:这是一个修改后的语法,使解析更加统一.我删除了term捕获以帮助修剪一些不必要的分支.
local pattern2 = re.compile
[=[
term <- term_t
term_t <- func / var
func <- {| {:type: '' -> "func":} {:name: func_id:} "(" args? ")" |}
func_id <- lower / upper
arg <- number / string / term_t
args <- arg (separator args)?
var <- {| {:type: '' -> "var" :} {:name: lower / upper:} |}
string <- {| {:type: '' -> "string" :}'"' {:value: [^"]* :} '"' |}
lower <- {%l%w*}
upper <- {%u%w*}
number <- {| {:type: '' -> "number":} {:value: %d+:} |}
separator <- blank "," blank
blank <- " "*
]=]
Run Code Online (Sandbox Code Playgroud)
产生以下结果:
{
{
type = "var",
name = "A"
},
{
type = "var",
name = "b"
},
{
{
{
type = "number",
value = "42"
},
type = "func",
name = "d"
},
{
type = "string",
value = "e"
},
{
type = "var",
name = "f"
},
{
type = "number",
value = "7"
},
type = "func",
name = "c"
},
type = "func",
name = "fun"
}
Run Code Online (Sandbox Code Playgroud)