lua-users home
lua-l archive

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


On 26 September 2010 18:10, steve donovan <steve.j.donovan@gmail.com> wrote:
> On Sun, Sep 26, 2010 at 9:47 AM, Quae Quack <quae@daurnimator.com> wrote:
>> On that point, I'm trying to write an ini file reader in lpeg now; the
>> lack of specifications of the ini file format makes things hard. Will
>> post when I finish.
>
> I'd be interested in what the solution looks like; I have been trying
> to 'think' in lpeg recently.
>
> steve d.
>
>

Right, got something going. I'm not really sure what the format of an
ini file is... but this should be close :P
It doesn't do quoted values like it mentions on wikipedia.... which I
only checked now....
It does do an error with line numbers, with a demonstration of how you
can do it with lpeg.

Use is:
---------------------------------------------------------------
local ini = require "ini"

str=[[
foo=baz is a good bloke ; In the default section
[another section]
foo=bar;lol comments

#that was an empty line!
lol:wtf
wow_no_value_I_must_be_true
]]
for k ,v in pairs ( ini.decode(str) ) do
	print(k)
	for kk,vv in pairs(v) do
		print("\t",kk,vv)
	end
end

----------------------------------------------------------------------
ini.lua
----------------------------------------------------------------------

require "lpeg"
local P , R , S , V = lpeg.P , lpeg.R , lpeg.S , lpeg.V
local C , Cb , Cc , Cg , Ct , Cmt = lpeg.C , lpeg.Cb , lpeg.Cc ,
lpeg.Cg , lpeg.Ct , lpeg.Cmt
local locale = lpeg.locale ( )

local newtable = function ( ) return true , {} end -- for use as a
match time capture
local concatcaptures = function ( patt ) return Ct ( patt )/ table.concat end
local incrementline = Cg ( Cb"linenum" / function ( a ) return a + 1
end , "linenum" )

local eof = P(-1)
local space = S" \t"
local newline = P"\r"^-1 * "\n"
local inlinecomment = ";" * (P(1)-newline)^0

local emptyline = space^0
local linecomment = S"#;" * (P(1)-newline)^0

local sectionheader = P"[" * Cg ( ( locale.print - S";]" )^1 ,
"section" ) * "]" * space^0 * inlinecomment^-1

local parameter = Cb"results" * Cb"section" * P {
	V"name" * space^0 * ( S"=:" * space^0 * V"value" + Cc ( true ) ) *
space^0 * inlinecomment^-1 ;

	name = C ( (locale.print-S"=:;" ) ^1 ) ;

	continuation = newline * incrementline * space^1 ;
	valmatch = ( locale.print - S";#" )^1 ;
	value = concatcaptures ( C ( V"valmatch" ) * ( V"continuation" * C (
V"valmatch" ) )^0 ) ;
} / function ( tbl , section , name , value )
		local st = tbl [ section ]
		if not st then
			st = { }
			tbl [ section ] = st
		end
		st [ name ] = value
	end

local setup = Cg ( P(newtable) , "results" ) * -- new table to store values in
	Cg ( Cc ( 1 ) , "linenum" ) * -- initiate line number
	Cg ( Cc ( "DEFAULT" ) , "section" ) -- default section is "DEFAULT"

local line = ( linecomment + sectionheader + parameter + emptyline ) *
newline * incrementline
	+ Cmt ( Cb"linenum" , function(str,i,linenum) if #str >= i then
error("bad line " .. linenum ) end end )

local patt = setup * line^1 * eof * Cb"results"

return {
	decode = function ( str ) return patt:match ( str ) end
}
-----------------------------------------------------------
Daurn.