mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-13 02:40:28 +00:00
Distinguish between all parsers passing and failing
Given an input like f(x), which is both a valid statement and expression, both parsers would accept the whole input. However, this was treated the same as both parsers rejecting the input, resulting in a crash when trying to print the error. We now return immediately when any parser accepts the input. Fixes #1354
This commit is contained in:
parent
111f971ed0
commit
1c120982a7
@ -120,22 +120,35 @@ local function parse_repl(input)
|
||||
assert(coroutine.resume(parsers[i], context, coroutine.yield, start_code))
|
||||
end
|
||||
|
||||
-- Run all parsers together in parallel, feeding them one token at a time.
|
||||
-- Once all parsers have failed, report the last failure (corresponding to
|
||||
-- the longest parse).
|
||||
local ok, err = pcall(function()
|
||||
local parsers_n = #parsers
|
||||
while true do
|
||||
local token, start, finish = lexer()
|
||||
|
||||
local stop = true
|
||||
local all_failed = true
|
||||
for i = 1, parsers_n do
|
||||
local parser = parsers[i]
|
||||
if coroutine.status(parser) ~= "dead" then
|
||||
stop = false
|
||||
if parser then
|
||||
local ok, err = coroutine.resume(parser, token, start, finish)
|
||||
if not ok and err ~= error_sentinel then error(err, 0) end
|
||||
if ok then
|
||||
-- This parser accepted our input, succeed immediately.
|
||||
if coroutine.status(parser) == "dead" then return end
|
||||
|
||||
all_failed = false -- Otherwise continue parsing.
|
||||
elseif err ~= error_sentinel then
|
||||
-- An internal error occurred: propagate it.
|
||||
error(err, 0)
|
||||
else
|
||||
-- The parser failed, stub it out so we don't try to continue using it.
|
||||
parsers[i] = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if stop then error(error_sentinel) end
|
||||
if all_failed then error(error_sentinel) end
|
||||
end
|
||||
end)
|
||||
|
||||
|
@ -49,4 +49,18 @@ describe("cc.internal.syntax", function()
|
||||
describe_golden("the lexer", "lexer_spec.md", true)
|
||||
describe_golden("the parser", "parser_spec.md", false)
|
||||
describe_golden("the parser (all states)", "parser_exhaustive_spec.md", false)
|
||||
|
||||
describe("the REPL input parser", function()
|
||||
it("returns true when accepted by both parsers", function()
|
||||
helpers.with_window(50, 10, function()
|
||||
expect(syntax.parse_repl("print(x)")):eq(true)
|
||||
end)
|
||||
end)
|
||||
|
||||
it("returns true when accepted by one parser", function()
|
||||
helpers.with_window(50, 10, function()
|
||||
expect(syntax.parse_repl("x")):eq(true)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user