如何用 LPeg 发出解析错误信号?
2016-7-29 23:1:2
收藏:0
阅读:93
评论:1
我正在编写基于 LPeg 的解析器。如何使解析错误返回 nil, errmsg?
我知道可以使用 error(),但据我所知,它创建的只是一个普通的错误,而不是 nil, errmsg。
代码很长,但相关部分如下:
local eof = lpeg.P(-1)
local nl = (lpeg.P "\r")^-1 * lpeg.P "\n" + lpeg.P "\\n" + eof -- \r 用于Windows兼容
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 -- 注释被视为空格
local backslashEscaped
= lpeg.P("\\ ") / " " -- 转义空格
+ lpeg.P("\\\\") / "\\" -- 转义转义字符
+ lpeg.P("\\#") / "#"
+ lpeg.P("\\>") / ">"
+ lpeg.P("\\`") / "`"
+ lpeg.P("\\n") -- \\n 换行符被视为反斜杠转义
+ lpeg.P("\\") * lpeg.P(function(_, i)
error("Unknown backslash escape at position " .. i) -- 这个 error() 是我想去掉的。
end)
local Line = lpeg.C((wsc + (backslashEscaped + 1 - nl))^0) / function(x) return x end * nl * lpeg.Cp()
当出现无效转义时,我希望Line:match(...)返回nil,errmsg。
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
LPeg本身没有提供特定的函数帮助您进行错误报告。解决您的问题的快速方法是以这种方式进行匹配受保护的调用(pcall):
local function parse(text) local ok, result = pcall(function () return Line:match(text) end) if ok then return result else -- `result`将包含所抛出的错误。如果它是一个字符串, --Lua将增加额外的信息(文件名和行号)。 --如果您不想这样做,则应抛出类似于`{msg =“error”}`的表 --并使用`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还允许您通过标记选择(labeled choice)在语法中捕获标签;这对于实现诸如错误恢复之类的事情非常有用。有关标记故障和示例的更多信息,请查阅文档。