diff options
author | SoniEx2 <endermoneymod@gmail.com> | 2019-03-31 11:02:57 -0300 |
---|---|---|
committer | SoniEx2 <endermoneymod@gmail.com> | 2019-03-31 11:02:57 -0300 |
commit | d03d77d28b812244be66763356f24659da769f05 (patch) | |
tree | cef5cff3fc7dcfc1f0794633d7c835c8938c3a6b /parser.lua |
Parser seems to work?
Diffstat (limited to 'parser.lua')
-rw-r--r-- | parser.lua | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/parser.lua b/parser.lua new file mode 100644 index 0000000..479d80a --- /dev/null +++ b/parser.lua @@ -0,0 +1,119 @@ +--[[ + parser.lua - table based parsing + Copyright (C) 2019 Soni L. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +--]] + +-- key for STATE +local STATE = {} +-- key for DATA +local DATA = {} +-- key for GENERATOR +local GEN = {} +-- key for DATA OFFSET +local OFFDATA = {} + +local type, tostring + = type, tostring + +local function get_next_common(state, in_pos, token) + -- note: must preserve "token" - do not call recursively with a different token + local transition + if state[STATE] ~= nil then + transition = state[STATE][token] + if not transition then + transition = state[STATE][""] + end + local recheck = true + while recheck do + recheck = false + local tytrans = type(transition) + if tytrans == "string" then + transition = state[STATE][transition] + recheck = true + elseif tytrans == "function" then + transition = transition(state, token) + recheck = true + end + end + state[STATE] = transition -- may be nil + end + -- must NOT use elseif here - the above may set state to nil! + if state[STATE] == nil then + -- unexpected token. stream consumer may attempt to recover, + -- but we do this mostly to differentiate it from "end of stream" condition. + return in_pos - 1, nil, "unexpected token", token, state + end + return in_pos, state, transition -- TODO is this what we should be returning? +end + +local function get_next_table(state, in_pos) + if state[DATA] == nil or #state[DATA] == 0 then return in_pos, state end + in_pos = in_pos + 1 + local token = state[DATA][in_pos - state[OFFDATA]] + if token == nil then + state[OFFDATA] = in_pos - 1 + state[DATA] = state[GEN]() + return get_next_table(state, state[OFFDATA]) + end + return get_next_common(state, in_pos, token) +end + +local function get_next_string(state, in_pos) + if state[DATA] == nil or #state[DATA] == 0 then return in_pos, state end + in_pos = in_pos + 1 + local token = state[DATA]:sub(in_pos - state[OFFDATA], in_pos - state[OFFDATA]) + if token == "" then + state[OFFDATA] = in_pos - 1 + state[DATA] = state[GEN]() + return get_next_string(state, state[OFFDATA]) + end + return get_next_common(state, in_pos, token) +end + +local function stream(defs, data) + local state = {} + local fn + state[STATE] = defs + if type(data) == "string" then + state[DATA] = data + state[GEN] = function() end + fn = get_next_string + else + state[DATA] = data() + state[GEN] = data + fn = type(state[DATA]) == "string" and get_next_string or get_next_table + end + state[OFFDATA] = 0 + return fn, state, state[OFFDATA] +end + +local function parse(defs, data) + for pos, state, transemsg, etoken, estate in stream(defs, data) do + if not state then + -- parse error + return nil, transemsg, etoken, estate + elseif not transemsg then + -- parse success (maybe) - caller needs to check state[STATE] against what it considers a successful state + return state + end + end +end + +return { + STATE = STATE, + stream = stream, + parse = parse, +} |