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 Parke once stated:
> On Sat, Jun 24, 2017 at 9:22 PM, Sean Conner <sean@conman.org> wrote:
> >> Why?  What are you trying to do?
> >
> >   I have LPeg code to decode JSON data [1].  I received email from a person
> > about the handling of 'null'---that is, I return a Lua nil value, but this
> > person wanted a custom value.  I'm not completely swayed by the arguments
> > for a custom JSON null value, but I would like to provide the option for
> > such.  I thought a good way to handle a situation would be with Carg()---if
> > you want a custom null value, one could be provided, but it's optional.
> 
> Why not use lpeg.Cc(values)?

  Given how I've implemented the module, I return an LPeg userdata, not a
table (following the other parsing modules [1]).  I'd like to keep that
format if at all possible (and it's seeming like I can't).  If require()
passed along any additional paramters to the module, then that could be used
to pass along a custom JSON null value, but alas, require() doesn't work
that way.

  So the only way to pass along an alternative null is through additional
arguments to lpeg.match(), which doesn't work the way I would like.

> You would have to rebuild the pattern to change the value that would
> represent null.

  Yes, I'm aware of that.

> >   I'm just curious about the rational for the current behavior.
> 
> I find the current behavior to be consistent with other parts of Lua
> that raise an error when the arguments provided to a function are
> obviously wrong.

  A) there is no obvious value for additional arguments---they can be
anything, including nil (as I've shown) and B) it's the value meant to be
used as a capture.  And I can see two interpretations:

	1) pattern * Carg(1) returning the first additional argument, or nil
	   if one isn't given.  

	2) pattern * Carg(1) failing (even if pattern does match) because
	   the actual capture, the first additional argument, doesn't exist.

  What is happening though, is:

	pattern * Carg(1) crashing [2] because the additional argument
	doesn't exist.

  I can even see that being valid as a method of debugging (an incorrect
number of parameters were given to lpeg.match()) but the documentation
doesn't state that the parameter *has* to exist.  The description for
lpeg.match() doesn't even bring up that additional parameters are even
possible (only documenting the pattern, string and optional (note) initial
position).  And lpeg.Cc(nil) is a valid capture!

> > -spc (Still pondering how to deal with this)
> 
> Use lpeg.Cc(values).  Or, if you don't want to rebuild the pattern,
> use patt/function with a closure and with a monkey-patch a wrapper
> around the match function to update the value in the closure.

  I already use the patt/function to return nil, so ... 

	local json = require "org.conman.parsers.json"
	
	local customjsonnullvalue = function() end

	do
	  local env = debug.getuservalue(json)
	  for i,item in ipairs(env) do
	    if type(item) == 'function' then
	      local info = debug.getinfo(item)
	      if info.linedefined == 139 then
	        env[i] = function(_,position)
	          return position,customjsonnullvalue
	        end
	        break
	      end
	    end
	  end
	end
	
	test = '[{"list": [1], "array":{"utf8": "\\u00e9\\u00ea", "next": null}}]'
	data = json:match(test)
	print(data[1].array.next)

	function: 0x9c2fd50

  -spc (So yes, monkeypatching does work, but ... )

[1]	https://github.com/spc476/LPeg-Parsers

[2]	Well, not a "crash" crash, but a catchable Lua error.