Created
July 7, 2017 01:54
-
-
Save cloudwu/e879a8c99eed8fa03c0fd02e33880443 to your computer and use it in GitHub Desktop.
paradox file parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local pdx = {} | |
do | |
local lpeg = require "lpeg" | |
local P = lpeg.P | |
local S = lpeg.S | |
local R = lpeg.R | |
local C = lpeg.C | |
local Ct = lpeg.Ct | |
local Cg = lpeg.Cg | |
local Cc = lpeg.Cc | |
local V = lpeg.V | |
local function count_lines(_,pos, parser_state) | |
if parser_state.pos < pos then | |
parser_state.line = parser_state.line + 1 | |
parser_state.pos = pos | |
end | |
return pos | |
end | |
local exception = lpeg.Cmt( lpeg.Carg(1) , function ( _ , pos, parser_state) | |
error(string.format("syntax error at [%s] line (%d)", parser_state.file or "", parser_state.line)) | |
return pos | |
end) | |
local pattern = {} | |
pattern.eof = P(-1) | |
-- blanks | |
do | |
local newline = lpeg.Cmt((P"\n" + "\r\n") * lpeg.Carg(1) ,count_lines) | |
local line_comment = "#" * (1 - newline) ^0 * (newline + pattern.eof) | |
local blank = S" \t" + newline + line_comment | |
pattern.blank0 = blank ^ 0 | |
pattern.blanks = blank ^ 1 | |
end | |
--number | |
do | |
local num = P "-" ^ 0 * R"09" * P "." ^ 0 * R"09" ^ 0 | |
local percent = num / function(v) return tonumber(v) / 100 end * "%" | |
local number = percent + num / tonumber | |
local alpha = R"az" + R"AZ" + "_" | |
local alnum = alpha + R"09" | |
local word = alpha * alnum ^ 0 | |
local const = P "@" * C(word) * pattern.blank0 * "=" * pattern.blank0 * number | |
pattern.word = word | |
pattern.const_define = lpeg.Cmt(const * lpeg.Carg(1), | |
function(_, pos, key, value, state) | |
if state.const[key] then | |
error (string.format("Const %s is redefined, at [%s] line (%d)", key, state.file or "", state.line)) | |
end | |
state.const[key] = value | |
return true | |
end | |
) | |
local const_reference = lpeg.Cmt(P "@" * C(word) * lpeg.Carg(1), | |
function(_, pos, key, state) | |
local v = state.const[key] | |
if v == nil then | |
error (string.format("Const %s is undefined, at [%s] line (%d)", key, state.file or "", state.line)) | |
end | |
return true, v | |
end | |
) | |
pattern.number = number + const_reference | |
local dotname = ("." * alnum ^ 0) ^ 0 | |
pattern.ident = C(alpha * alnum ^ 0 * dotname) | |
end | |
pattern.key = C(pattern.word + R "09" ^ 1 / tonumber) * pattern.blank0 * "=" * pattern.blank0 | |
local function item(t, pat) | |
return Cc(t) * pattern.key * pat | |
end | |
local function multipat(pat) | |
return Ct((pat * pattern.blanks) ^ 0 * pat^0) | |
end | |
do | |
local str_c = (1 - S("\\\"")) + P("\\") * 1 | |
pattern.string = P '"' * C(str_c^0) * '"' | |
end | |
local function multi(pat) | |
return (Ct(pat) * pattern.blanks) ^ 0 * Ct(pat) ^ 0 | |
end | |
local items = P { | |
"ALL", | |
NUMBER = item("number", pattern.number), | |
TABLE = item("table", P "{" * pattern.blank0 * Ct(V "ALL") * pattern.blank0 * "}" ), | |
ARRAY = item("array", P "{" * pattern.blank0 * Ct(V "VALUES") * pattern.blank0 * "}" ), | |
STRING = item("string", pattern.string), | |
IDENT = item("ident", pattern.ident), | |
CONDITION = Cc "cond" * C(pattern.word) * pattern.blank0 * C(S "<>") * pattern.blank0 * pattern.number, | |
DEFINE = pattern.const_define, | |
ITEM = V "NUMBER" + V "TABLE" + V "ARRAY" + V "STRING" + V "IDENT" + V "CONDITION" + V "DEFINE", | |
VALUE = C(pattern.number) + C(pattern.string), | |
VALUES = multi(V "VALUE"), | |
ALL = multi(V "ITEM"), | |
} | |
local proto = pattern.blank0 * Ct(items) | |
function pdx.parser(text,filename) | |
local state = { file = filename, pos = 0, line = 1 , const = {}} | |
local r = lpeg.match(proto * -1 + exception , text , 1, state ) | |
return r | |
end | |
end | |
function pdx.load(filename) | |
local f = assert(io.open(filename)) | |
local text = f:read "a" | |
f:close() | |
local tmp = pdx.parser(text, filename) | |
return tmp | |
end | |
return pdx |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment