Module:SchemaDiagram

local p = {}

function switch(t) t.case = function (self, x)		local f = self[x] or self.default if f then if type(f) == "function" then f(x, self) else error("case " .. tostring(x) .. " not a function", 2) end end end return t end

function p.render( frame ) local legal_states = { root = { create = true, },		create = { create_table_start = true, root = true, },		create_table_start = { create_table_start = true, table_field_start = true, },		table_field_start = { table_field_named = true, },		-- seen "myfield" table_field_named = { -- expect "NOT" table_field_named_not = true, -- expect "," (start next field) table_field_start = true, -- seen "CREATE TABLE … ( … )" -- expect ")" (end of table, continue from "CREATE" statement)			create = true			-- expect " " (no change)		},		-- seen "myfield … NOT"		table_field_named_not = {			-- expect " " (continue in this field)			table_field_named = true,			-- expect "," (unexpected end, start next field)			table_field_start = true,			-- seen "CREATE TABLE … ( … )"			-- expect ")" (unexpected end, continue from "CREATE" statement) create = true }	}	local state = "root"

local parsed_tables = {} local parsed_current = { table_name = nil, table_fields = nil, field_name = nil, field_attribs = nil }

-- Inspired by http://lua-users.org/wiki/SwitchStatement local parser = { -- outer-most state ["root"] = function (token) if token == "CREATE" then return "create" end end, -- seen "CREATE" ["create"] = function (token) -- expect "TABLE" for "CREATE TABLE" if token == "TABLE" then return "create_table_start" end -- expect "INDEX" for "CREATE INDEX" (ignored) -- expect "UNIQUE" for "CREATE UNIQUE INDEX" (ignored) -- expect "/*$wgDBTableOptions*/" (ignored) -- expect ";" (end of statement) if token == ";" then return "root" end end, -- seen "CREATE TABLE" ["create_table_start"] = function (token) -- expect "/*_*/ " if mw.ustring.sub( token, 0, 5 ) == "/*_*/" then parsed_current.table_name = mw.ustring.sub( token, 5 ) return "create_table_start" end

-- expect " " if mw.ustring.match( token, "^%w+$" ) then parsed_current.table_name = token return "create_table_start" end

-- expect "("			if token == "(" then if parsed_current.table_name == nil then error("CREATE TABLE requires a name") end return "table_field_start" end

error("unexpected token after create_table_start: '" .. token .. "'") end, -- seen "CREATE TABLE mytable ("		["table_field_start"] = function (token)			-- expect " "			if mw.ustring.match( token, "^%w+$" ) then				parsed_current.field_name = token				return "table_field_named"			end

error("unexpected token after table_field_start: '" .. token .. "'") end, -- seen " " ["table_field_named"] = function (token) -- TODO: Finish me error("unexpected token after table_field_named: '" .. token .. "'") end, }

local sql = mw.ustring.sub( frame.args.sql, 0, 1000 ) local chunks = mw.text.split( sql, '%s' ) local result = "" for i, v in ipairs( chunks ) do local nextcase = parser[state] or error("undefined case '" .. state .. "' in parser") local nextstate = nextcase( v ) mw.log( "[" .. state .. "] '" .. v .. "' -> " .. ( nextstate or "(no state change)" ) )

if nextstate and legal_states[state][nextstate] == nil then error("illegal state change in parser from '" .. state .. "' to '" .. nextstate .. "'") end

state = nextstate or state end

return result end return p