lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Soni L. once stated:
> As seen in http://stackoverflow.com/q/38664815/3691554
> 
> `Line` and `Data` are the things that when `:match()`ed should return 
> `nil, errmsg` on parsing error. Note that only `Line` decides whether a 
> line is valid or not, so that's where parsing errors happen. `Data` only 
> extracts the data from a (valid) line.

  Make sure Line always matches the entirety of a valid line.  Then you can
modify it to return nil,errmsg, like:

local Line = lpeg.C((wsc + (backslashEscaped + 1 - nl))^0)
           / function(x) return x end 
           * nl 
           * lpeg.Cp()
           + lpeg.Cc(nil) * lpeg.Cc("Invalid parse of a line")


local Data = lpeg.S(" \t")^0
           * lpeg.Cs((ws / " " + inlineComment / "" + backslashEscaped + 1 - (lpeg.S(" \t")^0 * nl))^0) 
           * lpeg.S(" \t")^0 
           * nl
           + lpeg.Cc(nil) * lpeg.Cc("Invalid data")

  If you want more specific errors, then you can do something like this:

local escape = lpeg.P"\\ "  / " "
             + lpeg.P"\\\\" / "\\"
             + lpeg.P"\\#"  / "#"
             + lpeg.P"\\>"  / ">"
             + lpeg.P"\\"  / ""
             + lpeg.P"\\n"  / "\n"
             + lpeg.P"\\" * lpeg.Cmt(lpeg.Carg(1) * lpeg.C(1),
                                      function(subject,pos,e,c)
                                        table.insert(e,"Bad escape " .. c)
                                        return nil
                                      end)
local char    = lpeg.R(" [","]~")
local cleanup = lpeg.Cs((escape + char)^0) * lpeg.P"\n"

local function test(s)
  local e = {}
  local r = cleanup:match(s,1,e)
  if not r then
    print(e[1])
  end
end

test [[Hello\ There\# foob
]]
test [[Hello\aThere\bfoob
]]

  I'm using lpeg.Carg() to pass in a table to accumulate the errors (this
keeps this reentrant).  lpeg.Cmt() does a match-time capture and if this
returns nil, then that particular capture fails.  I've set up this example
such that if cleanup returns nil, then the passed in table will contain the
error.

  -spc