From 6ce32bdd25694d71dc232c50a008f8824f8a75ce Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sat, 26 May 2018 19:24:22 -0700 Subject: Cleaned up lpeg matching stuff to use lpeg.Carg(1) instead of lpeg.userdata, and switched indent/dedent/nodent to use a number to track indentation instead of a stack. --- nomsu.lua | 57 +++++++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 32 deletions(-) (limited to 'nomsu.lua') diff --git a/nomsu.lua b/nomsu.lua index 4841a7e..cc95de4 100644 --- a/nomsu.lua +++ b/nomsu.lua @@ -28,8 +28,8 @@ end re = require('re') lpeg = require('lpeg') lpeg.setmaxstack(10000) -local P, R, V, S, Cg, C, Cp, B -P, R, V, S, Cg, C, Cp, B = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.Cg, lpeg.C, lpeg.Cp, lpeg.B +local P, R, V, S, Cg, C, Cp, B, Cmt, Carg +P, R, V, S, Cg, C, Cp, B, Cmt, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.Cg, lpeg.C, lpeg.Cp, lpeg.B, lpeg.Cmt, lpeg.Carg local utils = require('utils') local new_uuid = require('uuid') local immutable = require('immutable') @@ -183,42 +183,38 @@ do _with_0.operator = _with_0.operator_char ^ 1 _with_0.utf8_char = (R("\194\223") * R("\128\191") + R("\224\239") * R("\128\191") * R("\128\191") + R("\240\244") * R("\128\191") * R("\128\191") * R("\128\191")) _with_0.ident_char = R("az", "AZ", "09") + P("_") + _with_0.utf8_char - _with_0.indent = P(function(self, start) - local nodent = lpeg.userdata.indent_stack[#lpeg.userdata.indent_stack] - local indented = nodent .. " " - if self:sub(start, start + #indented - 1) == indented then - insert(lpeg.userdata.indent_stack, indented) - return start + #indented + _with_0.indent = Cmt(Carg(1), function(self, start, userdata) + if #self:match("^[ ]*", start) == userdata.indent + 4 then + userdata.indent = userdata.indent + 4 + return start + userdata.indent end end) - _with_0.dedent = P(function(self, start) - local nodent = lpeg.userdata.indent_stack[#lpeg.userdata.indent_stack] - local spaces = self:match("^[ ]*", start) - if #spaces <= #nodent - 4 then - remove(lpeg.userdata.indent_stack) + _with_0.dedent = Cmt(Carg(1), function(self, start, userdata) + if #self:match("^[ ]*", start) <= userdata.indent - 4 then + userdata.indent = userdata.indent - 4 return start end end) - _with_0.nodent = P(function(self, start) - local nodent = lpeg.userdata.indent_stack[#lpeg.userdata.indent_stack] - if self:sub(start, start + #nodent - 1) == nodent then - return start + #nodent + _with_0.nodent = Cmt(Carg(1), function(self, start, userdata) + if #self:match("^[ ]*", start) >= userdata.indent then + return start + userdata.indent end end) - _with_0.error = function(src, end_pos, start_pos, err_msg) - local seen_errors = lpeg.userdata.errors + _with_0.userdata = Carg(1) + _with_0.error = function(src, end_pos, start_pos, err_msg, userdata) + local seen_errors = userdata.errors if seen_errors[start_pos] then return true end local err_pos = start_pos - local text_loc = lpeg.userdata.source:sub(err_pos, err_pos) + local text_loc = userdata.source:sub(err_pos, err_pos) local line_no = text_loc:get_line_number() src = FILE_CACHE[text_loc.filename] local prev_line = line_no == 1 and "" or src:sub(LINE_STARTS[src][line_no - 1] or 1, LINE_STARTS[src][line_no] - 2) local err_line = src:sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no + 1] or 0) - 2) local next_line = src:sub(LINE_STARTS[src][line_no + 1] or -1, (LINE_STARTS[src][line_no + 2] or 0) - 2) local pointer = ("-"):rep(err_pos - LINE_STARTS[src][line_no]) .. "^" - err_msg = (err_msg or "Parse error") .. " at " .. tostring(lpeg.userdata.source.filename) .. ":" .. tostring(line_no) .. ":\n" + err_msg = (err_msg or "Parse error") .. " at " .. tostring(userdata.source.filename) .. ":" .. tostring(line_no) .. ":\n" if #prev_line > 0 then err_msg = err_msg .. ("\n" .. prev_line) end @@ -234,8 +230,8 @@ end setmetatable(NOMSU_DEFS, { __index = function(self, key) local make_node - make_node = function(start, value, stop) - local source = lpeg.userdata.source:sub(start, stop) + make_node = function(start, value, stop, userdata) + local source = userdata.source:sub(start, stop) local tree if Types[key].is_multi then tree = Types[key](Tuple(unpack(value)), source) @@ -255,7 +251,7 @@ do anon_def <- ({ident} (" "*) ":" {((%nl " "+ [^%nl]*)+) / ([^%nl]*)}) -> "%1 <- %2" captured_def <- ({ident} (" "*) "(" {ident} ")" (" "*) ":" - {((%nl " "+ [^%nl]*)+) / ([^%nl]*)}) -> "%1 <- (({} %3 {}) -> %2)" + {((%nl " "+ [^%nl]*)+) / ([^%nl]*)}) -> "%1 <- (({} %3 {} %%userdata) -> %2)" ident <- [a-zA-Z_][a-zA-Z0-9_]* comment <- "--" [^%nl]* ]]) @@ -322,17 +318,14 @@ do end local userdata = { source_code = nomsu_code, - indent_stack = { - "" - }, + indent = 0, errors = { }, source = nomsu_code.source } - local old_userdata - old_userdata, lpeg.userdata = lpeg.userdata, userdata - local tree = NOMSU_PATTERN:match(tostring(nomsu_code)) - lpeg.userdata = old_userdata - assert(tree, "In file " .. tostring(colored.blue(filename)) .. " failed to parse:\n" .. tostring(colored.onyellow(colored.black(nomsu_code)))) + local tree = NOMSU_PATTERN:match(tostring(nomsu_code), nil, userdata) + if not (tree) then + error("In file " .. tostring(colored.blue(filename)) .. " failed to parse:\n" .. tostring(colored.onyellow(colored.black(nomsu_code)))) + end if next(userdata.errors) then local keys = utils.keys(userdata.errors) table.sort(keys) -- cgit v1.2.3