Improve block body's diagnostics

This commit is contained in:
dkanus 2026-04-29 20:13:58 +07:00
commit b1f0714483
18 changed files with 783 additions and 119 deletions

View file

@ -16,45 +16,40 @@ use rottlib::parser::Parser;
/// Keep these small: the goal is to inspect lexer diagnostics and delimiter
/// recovery behavior, not full parser behavior.
const TEST_CASES: &[(&str, &str)] = &[
// L0001: invalid or unknown token
(
"files/L0001_01.uc",
"`",
),
// L0002: unexpected closing delimiter
(
"files/L0002_01.uc",
"]",
),
// L0003: unclosed delimiter before later closing delimiter
// P0027: `else` without a matching `if`
//
// The `}` can still recover by matching the earlier `{`.
// `else` cannot start a standalone block item. The parser should report
// P0027 at `else`, then recover by bailing out of the current block.
(
"files/L0003_01.uc",
"{\n foo(\n}\n",
"files/P0027_01.uc",
"{\n local bool bReady;\n bReady = CheckReady();\n else { StartMatch(); }\n NotifyReady();\n}\n",
),
// L0004: mismatched closing delimiter
(
"files/L0004_01.uc",
"(]",
),
// L0005: unclosed delimiter at end of file
(
"files/L0005_01.uc",
"foo(",
),
// Mixed recovery case:
// P0027: `case` outside of a `switch`
//
// `)` recovers by matching `(` after treating `[` as unclosed;
// the following `]` is then unexpected.
// `case` is a switch-arm boundary, not a valid statement or expression
// starter in an ordinary block.
(
"files/L_mixed_01.uc",
"([)]",
"files/P0027_02.uc",
"{ local int Count; Count = 3; case 3: Count++; UpdateHud();}",
),
// P0027: standalone `until` without a preceding `do`
//
// `until` is only meaningful as the tail of `do ... until`, so it should
// not be accepted as a normal block item.
(
"files/P0027_03.uc",
"{\n local bool bDone;\n bDone = false;\n until (bDone)\n TickWork();\n}\n",
),
// P0027: preprocessor/exec directive inside a statement block
//
// `#exec` is declaration/top-level-like syntax, not a valid statement or
// expression inside a braced statement block.
(
"files/P0027_04.uc",
"{\n local int Count;\n Count = 0;\n #exec TEXTURE IMPORT NAME=Bad FILE=Bad.bmp\n Count++;\n}\n",
),
];
@ -62,12 +57,12 @@ const TEST_CASES: &[(&str, &str)] = &[
///
/// For lexer-focused fixtures this is usually noisy, so keep it off unless you
/// want to inspect how parser recovery behaves after lexer diagnostics.
const RUN_PARSER: bool = false;
const RUN_PARSER: bool = true;
/// If true, print the parsed expression using Debug formatting.
const PRINT_PARSED_EXPR: bool = false;
/// If true, print diagnostics even when parsing returned a value.
const PRINT_LEXER_DIAGNOSTICS: bool = false;
const ALWAYS_PRINT_DIAGNOSTICS: bool = true;
fn main() {
@ -89,7 +84,7 @@ fn main() {
} else {
had_any_problem = true;
if ALWAYS_PRINT_DIAGNOSTICS {
if PRINT_LEXER_DIAGNOSTICS {
println!("Lexer diagnostics:");
for diag in lexer_diagnostics {
render_diagnostic(diag, &tf, Some(label), false);