2016-07-29 33 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

相關問題