2012-02-17 29 views
2

我试图使用lpeg lua解析器将字符串'a?(b?c:d):e'转换为另一个字符串'ifthenelse(a,ifthenelse(b,c,d),e)'。我正在慢慢学习如何使用lpeg,但仍无法找到合适的解决方案来实现捕获。有任何想法吗?用lpeg转换(cond,then,else)到ifthnel(cond,then,else)

这是我到目前为止所做的。

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 -- Is it needed? 
print(lpeg.match(parser,"a?(b?c:d):e")) 
print(lpeg.match(parser,"a")) 
+0

起初我不喜欢你的缩写(S,P,R,...,V),后来我意识到,这种做法实际上使语法规则更容易阅读! – Stomp 2012-12-06 13:24:17

回答

2

下面是另一个由William Ahern在lua-list上给出的问题的解决方案。

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")) 
2

我改了一下语法,但是还是一样,我认为:

S = E "?" E ":" E | E 
E = "(" S ")" | T 
T = (L | D) + 
L = [a-z] | [A-Z] 
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(变量”(lpeg.Cs(lpeg.V"E")/"ifthenelse(%1")
  • 和 “?” “:” 与 “” (lpeg.P"?"/","lpeg.P":"/","
  • 最后一个变量匹配 “变量)”(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)) 

我希望你能从这里继续。

+0

谢谢胡安,它像一个魅力。 – cjorssen 2012-02-21 10:42:53

+0

虽然我在我的现实生活中使用威廉提供的解决方案,但我接受你的答案,因为1)它有效2)你详细描述了你的思维方式。再次感谢。 – cjorssen 2012-02-21 20:44:45