1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-25 22:53:22 +00:00

Be lazy in reporting errors in the lexer

Instead of reporting an error with `.report(f(...))`, we now do
`.report(f, ...)`. This allows consumers to ignore error messages when
not needed, such as when just doing syntax highlighting.
This commit is contained in:
Jonathan Coates 2023-06-25 15:48:57 +01:00
parent 7ffdbb2316
commit 54ab98473f
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
4 changed files with 24 additions and 19 deletions

View File

@ -21,6 +21,8 @@ local error_printer = require "cc.internal.error_printer"
local error_sentinel = {} local error_sentinel = {}
local function make_context(input) local function make_context(input)
expect(1, input, "string")
local context = {} local context = {}
local lines = { 1 } local lines = { 1 }
@ -73,8 +75,9 @@ local function parse(input, start_symbol)
expect(2, start_symbol, "number") expect(2, start_symbol, "number")
local context = make_context(input) local context = make_context(input)
function context.report(msg) function context.report(msg, ...)
expect(1, msg, "table") expect(1, msg, "table", "function")
if type(msg) == "function" then msg = msg(...) end
error_printer(context, msg) error_printer(context, msg)
error(error_sentinel) error(error_sentinel)
end end
@ -110,8 +113,9 @@ local function parse_repl(input)
local context = make_context(input) local context = make_context(input)
local last_error = nil local last_error = nil
function context.report(msg) function context.report(msg, ...)
expect(1, msg, "table") expect(1, msg, "table", "function")
if type(msg) == "function" then msg = msg(...) end
last_error = msg last_error = msg
error(error_sentinel) error(error_sentinel)
end end

View File

@ -96,7 +96,7 @@ local function lex_number(context, str, start)
local contents = sub(str, start, pos - 1) local contents = sub(str, start, pos - 1)
if not tonumber(contents) then if not tonumber(contents) then
-- TODO: Separate error for "2..3"? -- TODO: Separate error for "2..3"?
context.report(errors.malformed_number(start, pos - 1)) context.report(errors.malformed_number, start, pos - 1)
end end
return tokens.NUMBER, pos - 1 return tokens.NUMBER, pos - 1
@ -118,14 +118,14 @@ local function lex_string(context, str, start_pos, quote)
return tokens.STRING, pos return tokens.STRING, pos
elseif c == "\n" or c == "\r" or c == "" then elseif c == "\n" or c == "\r" or c == "" then
-- We don't call newline here, as that's done for the next token. -- We don't call newline here, as that's done for the next token.
context.report(errors.unfinished_string(start_pos, pos, quote)) context.report(errors.unfinished_string, start_pos, pos, quote)
return tokens.STRING, pos - 1 return tokens.STRING, pos - 1
elseif c == "\\" then elseif c == "\\" then
c = sub(str, pos + 1, pos + 1) c = sub(str, pos + 1, pos + 1)
if c == "\n" or c == "\r" then if c == "\n" or c == "\r" then
pos = newline(context, str, pos + 1, c) pos = newline(context, str, pos + 1, c)
elseif c == "" then elseif c == "" then
context.report(errors.unfinished_string_escape(start_pos, pos, quote)) context.report(errors.unfinished_string_escape, start_pos, pos, quote)
return tokens.STRING, pos return tokens.STRING, pos
elseif c == "z" then elseif c == "z" then
pos = pos + 2 pos = pos + 2
@ -133,7 +133,7 @@ local function lex_string(context, str, start_pos, quote)
local next_pos, _, c = find(str, "([%S\r\n])", pos) local next_pos, _, c = find(str, "([%S\r\n])", pos)
if not next_pos then if not next_pos then
context.report(errors.unfinished_string(start_pos, #str, quote)) context.report(errors.unfinished_string, start_pos, #str, quote)
return tokens.STRING, #str return tokens.STRING, #str
end end
@ -196,7 +196,7 @@ local function lex_long_str(context, str, start, len)
elseif c == "[" then elseif c == "[" then
local ok, boundary_pos = lex_long_str_boundary(str, pos + 1, "[") local ok, boundary_pos = lex_long_str_boundary(str, pos + 1, "[")
if ok and boundary_pos - pos == len and len == 1 then if ok and boundary_pos - pos == len and len == 1 then
context.report(errors.nested_long_str(pos, boundary_pos)) context.report(errors.nested_long_str, pos, boundary_pos)
end end
pos = boundary_pos pos = boundary_pos
@ -238,12 +238,12 @@ local function lex_token(context, str, pos)
local end_pos = lex_long_str(context, str, boundary_pos + 1, boundary_pos - pos) local end_pos = lex_long_str(context, str, boundary_pos + 1, boundary_pos - pos)
if end_pos then return tokens.STRING, end_pos end if end_pos then return tokens.STRING, end_pos end
context.report(errors.unfinished_long_string(pos, boundary_pos, boundary_pos - pos)) context.report(errors.unfinished_long_string, pos, boundary_pos, boundary_pos - pos)
return tokens.ERROR, #str return tokens.ERROR, #str
elseif pos + 1 == boundary_pos then -- Just a "[" elseif pos + 1 == boundary_pos then -- Just a "["
return tokens.OSQUARE, pos return tokens.OSQUARE, pos
else -- Malformed long string, for instance "[=" else -- Malformed long string, for instance "[="
context.report(errors.malformed_long_string(pos, boundary_pos, boundary_pos - pos)) context.report(errors.malformed_long_string, pos, boundary_pos, boundary_pos - pos)
return tokens.ERROR, boundary_pos return tokens.ERROR, boundary_pos
end end
@ -260,7 +260,7 @@ local function lex_token(context, str, pos)
local end_pos = lex_long_str(context, str, boundary_pos + 1, boundary_pos - comment_pos) local end_pos = lex_long_str(context, str, boundary_pos + 1, boundary_pos - comment_pos)
if end_pos then return tokens.COMMENT, end_pos end if end_pos then return tokens.COMMENT, end_pos end
context.report(errors.unfinished_long_comment(pos, boundary_pos, boundary_pos - comment_pos)) context.report(errors.unfinished_long_comment, pos, boundary_pos, boundary_pos - comment_pos)
return tokens.ERROR, #str return tokens.ERROR, #str
end end
end end
@ -317,18 +317,18 @@ local function lex_token(context, str, pos)
if end_pos - pos <= 3 then if end_pos - pos <= 3 then
local contents = sub(str, pos, end_pos) local contents = sub(str, pos, end_pos)
if contents == "&&" then if contents == "&&" then
context.report(errors.wrong_and(pos, end_pos)) context.report(errors.wrong_and, pos, end_pos)
return tokens.AND, end_pos return tokens.AND, end_pos
elseif contents == "||" then elseif contents == "||" then
context.report(errors.wrong_or(pos, end_pos)) context.report(errors.wrong_or, pos, end_pos)
return tokens.OR, end_pos return tokens.OR, end_pos
elseif contents == "!=" or contents == "<>" then elseif contents == "!=" or contents == "<>" then
context.report(errors.wrong_ne(pos, end_pos)) context.report(errors.wrong_ne, pos, end_pos)
return tokens.NE, end_pos return tokens.NE, end_pos
end end
end end
context.report(errors.unexpected_character(pos)) context.report(errors.unexpected_character, pos)
return tokens.ERROR, end_pos return tokens.ERROR, end_pos
end end
end end

View File

@ -244,7 +244,7 @@ local function handle_error(context, stack, stack_n, token, token_start, token_e
end end
end end
context.report(errors.unexpected_token(token, token_start, token_end)) context.report(errors.unexpected_token, token, token_start, token_end)
return false return false
end end

View File

@ -49,8 +49,9 @@ local function capture_parser(input, print_tokens, start)
end end
local context = make_context(input) local context = make_context(input)
function context.report(message) function context.report(message, ...)
expect(3, message, "table") expect(3, message, "table", "function")
if type(message) == "function" then message = message(...) end
for _, msg in ipairs(message) do for _, msg in ipairs(message) do
if type(msg) == "table" and msg.tag == "annotate" then if type(msg) == "table" and msg.tag == "annotate" then