lua-users home
lua-l archive

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


On Mon, 30 Nov 2009, spir wrote:
>
> Thank you. I think this may be a solution, a kind of table factory.
>
> The use case is to build parsers/grammars as tables of (named) patterns.
> This seems to me rather an obvious solution in Lua. However,
> higher-level patterns need to reference lower-level ones, eg integer =
> OneOrMore(digit).

I do this when writing LPEG grammars.

The basic pattern is below. Sometimes I return the whole pattern
environment, in which case match operations look like
parser.thing:match(str), or I just return the start symbol so match
operations are parser:match(str)

Note this code uses my LPEG patch so % operators are not necessary to
access the pattern environment, and I've also used a pythonic % operator.

	local function make_parser()
		-- environment for non-terminals
		local env = {}
		local function p(pat)
			return re.compile(pat, env)
		end
		setfenv(1,env)

		-- define grammar here

		CRLF = lpeg.S"\r\n"
		INL = 1 - CRLF
		comment = p[[ "#" INL* CRLF+ ]]
		EOL = p[[ CRLF+ comment* / !. ]]
		BEGIN = p[[ CRLF* comment*  ]]

		name = p[[ {[a-z]+} ]]
		num  = p[[ {[0-9]+} ]] / tonumber
		hex  = p[[ {[0-9a-fA-F]+} ]] /
			function (n) return tonumber(n,16) end

		ipv4 = p[[ num "." num "." num "." num ]] /
			function (a,b,c,d)
				return a * 16777216 + b * 65536 + c * 256 + d
			end

		ipv6 = p[[ (hex ":")+ ":" ]] /
			function (a,b,c,d)
				return "%4x:%4x:%4x:%4x::" %
					{ a or 0, b or 0, c or 0, d or 0 }
			end

		asn = p[[ num ("." num)? ]] /
			function (a,b)
				if b then return a * 65536 + b else return a end
			end

		-- ... other grammar definitions

		return env
	end
	local parser = make_parser()

Tony.
-- 
f.anthony.n.finch  <dot@dotat.at>  http://dotat.at/
GERMAN BIGHT HUMBER: SOUTHWEST 5 TO 7. MODERATE OR ROUGH. SQUALLY SHOWERS.
MODERATE OR GOOD.