2016-07-29 32 views
1

我在写一个基于LPeg的解析器。我怎样才能让它解析错误返回nil, errmsg如何使用LPeg发出解析错误信号?

我知道我可以使用error(),但据我所知,创建一个正常的错误,而不是nil, errmsg

的代码是pretty long,但相关的部分是:

local eof = lpeg.P(-1) 
local nl = (lpeg.P "\r")^-1 * lpeg.P "\n" + lpeg.P "\\n" + eof -- \r for winblows compat 
local nlnoeof = (lpeg.P "\r")^-1 * lpeg.P "\n" + lpeg.P "\\n" 
local ws = lpeg.S(" \t") 
local inlineComment = lpeg.P("`") * (1 - (lpeg.S("`") + nl * nl))^0 * lpeg.P("`") 
local wsc = ws + inlineComment -- comments count as whitespace 
local backslashEscaped 
= lpeg.P("\\ ")/" " -- escaped spaces 
+ lpeg.P("\\\\")/"\\" -- escaped escape character 
+ lpeg.P("\\#")/"#" 
+ lpeg.P("\\>")/">" 
+ lpeg.P("\\`")/"`" 
+ lpeg.P("\\n") -- \\n newlines count as backslash escaped 
+ lpeg.P("\\") * lpeg.P(function(_, i) 
    error("Unknown backslash escape at position " .. i) -- this error() is what I wanna get rid of. 
    end) 
local Line = lpeg.C((wsc + (backslashEscaped + 1 - nl))^0)/function(x) return x end * nl * lpeg.Cp() 

我想Line:match(...)返回nil, errmsg当有一个无效的逃避。

+0

你想达到什么目的?它是最小的例子吗?你尝试“返回”吗? – Jakuje

+0

'error()'产生错误而不是'nil,errmsg'。如果反斜杠转义出现错误,我想'Line:match()'和'Data:match()'返回'nil,errmsg'。 – SoniEx2

+0

@Jakuje实际上,我只需要'Line:match()'在无效转义时返回'nil,errmsg'。 – SoniEx2

回答

0

LPeg本身不提供特定的功能来帮助您进行错误报告。快速解决您的问题将是使一个protected call (pcall)匹配这样的:

local function parse(text) 
    local ok, result = pcall(function() return Line:match(text) end) 
    if ok then 
    return result 
    else 
    -- `result` will contain the error thrown. If it is a string 
    -- Lua will add additional information to it (filename and line number). 
    -- If you do not want this, throw a table instead like `{ msg = "error" }` 
    -- and access the message using `result.msg` 
    return nil, result 
    end 
end 

然而,这也将捕获任何其他错误,你可能不希望。更好的解决方案是使用LPegLabel代替。 LPegLabel是LPeg的扩展,增加了对标记失败的支持。只需将require"lpeg"替换为require"lpeglabel",然后使用lpeg.T(L)来抛出标签,其中L是从1-255的整数(0用于常规PEG失败)。

local unknown_escape = 1 
local backslashEscaped = ... + lpeg.P("\\") * lpeg.T(unknown_escape) 

现在Line:match(...)将返回nil, label, suffix如果抛出一个标签(suffix是剩余未处理的输入,你可以用它来计算通过其长度错误位置)。有了这个,你可以根据标签打印出适当的错误信息。对于更复杂的语法,您可能需要更系统的映射错误标签和消息的方式。请检查LPegLabel存储库自述文件中找到的文档,以查看如何执行此操作的示例。 (通过标签选择);也可以使用LPegLabel来捕获语法中的标签。这对于实现错误恢复等事情很有用。有关标记失败和示例的更多信息,请检查文档。

+0

如果它不是LPeg,它仍然是LPeg吗?我很确定我不能在只有内置标准LPeg的情况下使用LPegLabel。 – SoniEx2

+0

@ SoniEx2 LPegLabel不是LPeg,但它可以作为它的替代品。我的答案的第一部分(使用'pcall')只是标准的Lua,所以你可以在LPeg中使用它。 – undecidabot

+0

让Luvit捆绑LPegLabel,我可能会使用这个答案的第二部分。 (难道你不能重写LPegLabel来使用普通的LPeg吗?) – SoniEx2

相关问题