Lua lpeg解析一阶逻辑项
正如标题所说,我正在尝试解析例如Lua lpeg解析一阶逻辑项,lua,peg,first-order-logic,lpeg,Lua,Peg,First Order Logic,Lpeg,正如标题所说,我正在尝试解析例如 term(A, b, c(d, "e", 7)) 在一张像Lua一样的桌子上 {term, {A, b, {c, {d, "e", 7}}}} 这是我建立的语法: local pattern = re.compile[=[ term <- variable / function argument <- variable / lowercase /number / string function <- {|lower
term(A, b, c(d, "e", 7))
在一张像Lua一样的桌子上
{term, {A, b, {c, {d, "e", 7}}}}
这是我建立的语法:
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 <- " "*
]=]
local pattern=re.compile[=[
term对不起,我没有LPeg方面的经验,但通常的Lua模式足以轻松解决您的任务:
local str = 'term(A, b, c(d, "e", 7))'
local function convert(expr)
return (expr:gsub('(%w+)(%b())',
function (name, par_expr)
return '{'..name..', {'..convert(par_expr:sub(2, -2))..'}}'
end
))
end
print(convert(str)) -- {term, {A, b, {c, {d, "e", 7}}}}
现在只需load()
转换字符串来创建一个表。在语法中,您有:
argument <- variable / lowercase /number / string
function <- {|lowercase {|(open argument (separator (argument / function))* close)?|}|}
自从您的代码>变量< /> >非终结符被列在代码>函数< /> >之前,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 <- " "*
]=]
这将在我的机器上提供以下输出:
{
{
{
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"
}
仔细查看上面的内容,您会注意到函数参数按照传入的顺序出现在表的索引部分。type
和name
可以以任何顺序出现,因为它位于表的关联部分。您可以包装这些“属性”并将该内部属性表放在外部表的索引部分
编辑:这里有一个修改过的语法,使解析更加统一。我删除了术语
捕获,以帮助修剪一些不必要的分支
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 <- " "*
]=]
非常感谢!Pegs让我有点困惑。我将采用您的语法并从那里继续。有没有办法获得类似->的内容@キキジキ 你的意思是给术语
分支起一个名字?这可能是通过某种方式调整语法来实现的。注意,语法当前的定义方式,fun
被解析为一个函数,因此它是术语
的子项。术语
本身在这里实际上没有名字。术语
应该取什么名字开?它应该偷第一个孩子的名字吗?如果那个孩子没有名字怎么办@キキジキ 另一个想法是将术语
捕获完全去掉。在这种情况下,AST中只剩下函数、变量和其他原始终端,如数字、字符串等。这可能没问题,因为它看起来不像术语
在示例中真正添加了任何其他信息。我希望有更多的uniform元素。在“c”中,“e”和“7”看起来是这样的,但d和f是表。我想做的是,每个元素都表示为相同的。例如,由于“42”是“d”的参数,所以应该有一个带有名称和类型的d表,然后是一个带有参数列表的嵌套表,如{d,{42}。带有类型和名称标签,应该是{name=“d”,type=“fun”,“{{name=“42”,type=“num”}}}。如果type和name位于指定的索引,比如{fun,d{num,42}}},也可以。关于term,我碰巧称它为“term”但它可以是其他的东西。太好了!谢谢你花时间回答我的问题。嗯,你是对的,这是一个非常好的解决方案!如果我找到一种方法使pegs工作,我可以获得更多的数据(比如元素的类型),并最终将其扩展为添加运算符,但如果太复杂,我可能会使用你的解决方案。
{
{
{
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"
}
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 <- " "*
]=]
{
{
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"
}