使用lpeg将Transform(cond ? then : else)转换成ifthenelse(cond,then,else)。

我正在尝试使用lpeglua解析器将类似 'a?(b?c:d):e' 的字符串转换为另一个字符串'ifthenelse(a,ifthenelse(b,c,d),e)'。我正在慢慢学习如何使用lpeg,但我仍然找不到使用捕获来完成此操作的合适解决方案。有任何想法吗?

到目前为止,我所做的是:

local lpeg = require("lpeg")

local S,P,R = lpeg.S,lpeg.P,lpeg.R
local C,Cc,Ct = lpeg.C,lpeg.Cc,lpeg.Ct
local Cf,Cg,Cs = lpeg.Cf,lpeg.Cg,lpeg.Cs
local V = lpeg.V

local thenop = P("?")
local elseop = P(":")
local openpar = P("(")
local closepar = P(")")
local digit = R("09")
local letter = R("az")+R("AZ")

local parser =
     P({
     "F",
     F = V("E")*(thenop * V("E")* elseop * V("E"))^0,
     E =(letter + digit)^1 +(openpar * V("F")* closepar)
 })--* -1--是否需要?

print(lpeg.match(parser,“a?(b?c:d):e”))
print(lpeg.match(parser,“a”))

原文链接 https://stackoverflow.com/questions/9330477

点赞
stackoverflow用户1209430
stackoverflow用户1209430
S = E "?" E ":" E | E  // 定义表达式 S,具有三元操作符的情况和不带三元操作符的情况
E = "(" S ")" | T  // 定义表达式 E,可以是括号内的 S 也可以是 T
T = (L | D) +  // 定义项 T,可以是一个或多个字母或数字
L = [a-z] | [A-Z]  // 定义字母 L,可以是小写字母或大写字母
D = [0-9]  // 定义数字 D,可以是0至9之间的数字

不带捕获的语法:

local grammar = lpeg.P{
  "S";
  S = (lpeg.V"E" * lpeg.P"?" * lpeg.V"E" * lpeg.P":" * lpeg.V"E") + lpeg.V"E",
  E = (lpeg.P"(" * lpeg.V"S" * lpeg.P")") + lpeg.V"T",
  T = (lpeg.V"L" + lpeg.V"D")^1,
  L = lpeg.R("az") + lpeg.R("AZ"),
  D = lpeg.R("09")
}

带捕获的语法:

local grammar2 = lpeg.P{
  "S";
  S = (lpeg.Cs(lpeg.V"E") / "ifthenelse(%1") * (lpeg.P"?" / ",") * lpeg.V"E" * (lpeg.P":" / ",") * (lpeg.Cs(lpeg.V"E") / "%1)") + lpeg.V"E",
  E = (lpeg.P"(" / "") * lpeg.V"S" * (lpeg.P")" / "") + lpeg.V"T",
  T = (lpeg.V"L" + lpeg.V"D")^1,
  L = lpeg.R("az") + lpeg.R("AZ"),
  D = lpeg.R("09")
}

捕获规则:

  • 将 "(" 和 ")" 替换为空字符串 (lpeg.P"(" / ""lpeg.P")" / ""))
  • 将第一个变量匹配替换为 "ifthenelse(variable" (lpeg.Cs(lpeg.V"E") / "ifthenelse(%1"))
  • 将 "?" 和 ":" 替换为 "," (lpeg.P"?" / ","lpeg.P":" / ",")
  • 将最后一个变量匹配替换为 "variable)" (lpeg.Cs(lpeg.V"E") / "%1)")

一些随机测试 (注释中为输出结果):

print( lpeg.match( lpeg.Cs(grammar2), "a") )  // a
print( lpeg.match( lpeg.Cs(grammar2), "a?b:c") )  // ifthenelse(a,b,c)
print( lpeg.match( lpeg.Cs(grammar2), "a?(i?j:k):c") )  // ifthenelse(a,ifthenelse(i,j,k),c)
print( lpeg.match( lpeg.Cs(grammar2), "(a?(i?j:(x?y:z)):b)?c:(u?v:w)") )  // ifthenelse(ifthenelse(a,ifthenelse(i,j,ifthenelse(x,y,z)),b),c,ifthenelse(u,v,w))

希望这些能对您有所帮助。

2012-02-20 23:14:52
stackoverflow用户1195799
stackoverflow用户1195799

以下是对 lua-list 上 William Ahern 所提出问题的另一种解决方案。

local lpeg = require("lpeg")

lpeg.locale(lpeg)

local function tr(a, b, c)
   if not b then
       return a
   else
       return string.format("ifthenelse(%s,%s,%s)", a, b, c)
   end
end

local var = lpeg.C(lpeg.alpha * (lpeg.alnum^0))

local E, G = lpeg.V"E", lpeg.V"G"

local grammar = lpeg.P{ "E",
   E = ((var + G) * (lpeg.P"?" * E * lpeg.P":" * E)^-1) / tr,
   G = lpeg.P"(" * E * lpeg.P")",
}

print(lpeg.match(grammar, "a?(b?c:d):e"))
2012-02-21 20:42:43