Implent better diagnostics for control flow and primaries

This commit is contained in:
dkanus 2026-04-28 14:54:36 +07:00
commit 519d0cd3a7
39 changed files with 5990 additions and 1270 deletions

View file

@ -8,7 +8,6 @@ pub fn render_diagnostic(
_file: &TokenizedFile,
file_name: Option<&str>,
colors: bool,
) -> String {
) {
diag.render(_file, file_name.unwrap_or("<default>"));
"fuck it".to_string()
}

View file

@ -308,7 +308,6 @@ fn main() {
// first window
for (k, d) in diags.iter().take(first_n).enumerate() {
let s = pretty::render_diagnostic(d, tf, Some(&fname), use_colors);
eprintln!("{s}");
if ALSO_PRINT_DEBUG_AFTER_PRETTY {
eprintln!("#{}: {:#?}", k + 1, d);
}
@ -319,7 +318,6 @@ fn main() {
for (offset, d) in diags.iter().skip(start).enumerate() {
let idx_global = start + offset + 1;
let s = pretty::render_diagnostic(d, tf, Some(&fname), use_colors);
eprintln!("{s}");
if ALSO_PRINT_DEBUG_AFTER_PRETTY {
eprintln!("#{idx_global}: {d:#?}");
}
@ -327,7 +325,6 @@ fn main() {
} else {
for (k, d) in diags.iter().enumerate() {
let s = pretty::render_diagnostic(d, tf, Some(&fname), use_colors);
eprintln!("{s}");
if ALSO_PRINT_DEBUG_AFTER_PRETTY {
eprintln!("#{}: {:#?}", k + 1, d);
}

View file

@ -14,14 +14,138 @@ mod pretty;
// a * * *
/// Expressions to test.
///
/// Add, remove, or edit entries here.
/// Using `(&str, &str)` gives each case a human-readable label.
/// Expressions to test.
///
/// Add, remove, or edit entries here.
/// Using `(&str, &str)` gives each case a human-readable label.
const TEST_CASES: &[(&str, &str)] = &[
("files/P0003_01.uc", "(a + b && c / d ^ e @ f"),
("files/P0003_02.uc", "(a]"),
("files/P0003_03.uc", "(a\n;"),
// P0016: invalid initializer start after `for (`
(
"files/P0016_01.uc",
"for\n(] ; )",
),
(
"files/P0016_02.uc",
"for (\n ]\n ;\n)\n Body();\n",
),
(
"files/P0016_03.uc",
"for (\n }\n ;\n)\n",
),
(
"files/P0016_06.uc",
"for (\n ]\n\n\n ; Step)\n",
),
// P0017: initializer parsed, but first `;` is missing
(
"files/P0017_01.uc",
"for (Init ] ; )",
),
(
"files/P0017_02.uc",
"for (Init\n ]\n ;\n)\n",
),
(
"files/P0017_04.uc",
"for (Init {\n Body();\n}; )\n",
),
(
"files/P0017_05.uc",
"for (Init",
),
// P0018: invalid condition start after first `;`
(
"files/P0018_01.uc",
"for \n\n (; ] ; )",
),
(
"files/P0018_02.uc",
"for (;\n ]\n ;\n)\n Body();\n",
),
(
"files/P0018_03.uc",
"for (;\n }\n ;\n)\n",
),
(
"files/P0018_06.uc",
"for (;",
),
// P0019: condition parsed, but second `;` is missing
(
"files/P0019_01.uc",
"for (; bCondition )",
),
(
"files/P0019_02.uc",
"for (; bCondition\n)\n Body();\n",
),
(
"files/P0019_03.uc",
"for (; bCondition ] ; )",
),
(
"files/P0019_04.uc",
"for (; bCondition\n{\n Body();\n}\n;\n)\n",
),
(
"files/P0019_06.uc",
"for (; bCondition",
),
(
"files/P0019_07.uc",
"for (; bCondition Step)",
),
// P0020: invalid step start after second `;`
(
"files/P0020_01.uc",
"for (;;;)",
),
(
"files/P0020_02.uc",
"for (;;\n ;\n)\n",
),
(
"files/P0020_03.uc",
"for (;; ])",
),
(
"files/P0020_04.uc",
"for (;;\n }\n)\n",
),
(
"files/P0020_08.uc",
"for (;;\n ]\n",
),
// P0021: missing `)` to close `for` header
(
"files/P0021_01.uc",
"for (;;",
),
(
"files/P0021_02.uc",
"for (;; Step",
),
(
"files/P0021_03.uc",
"for (;; Step;\n Body();\n",
),
(
"files/P0021_05.uc",
"for (Init; bCondition; Step\n{\n Body();\n}\n",
),
(
"files/P0021_09.uc",
"for\n(Init;\n bCondition;\n Step\n]\n",
),
];
/// If true, print the parsed expression using Debug formatting.
@ -33,24 +157,14 @@ const ALWAYS_PRINT_DIAGNOSTICS: bool = true;
fn main() {
let arena = Arena::new();
println!("Running {} expression test case(s)...", TEST_CASES.len());
println!();
let mut had_any_problem = false;
for (idx, (label, source)) in TEST_CASES.iter().enumerate() {
println!("============================================================");
println!("Case #{:02}: {}", idx + 1, label);
println!("Source: {}", source);
println!("------------------------------------------------------------");
let tf = TokenizedFile::tokenize(source);
let mut parser = Parser::new(&tf, &arena);
let expr = parser.parse_expression();
println!("parse_expression() returned.");
if PRINT_PARSED_EXPR {
println!("Parsed expression:");
println!("{expr:#?}");
@ -60,14 +174,10 @@ fn main() {
println!("Diagnostics: none");
} else {
had_any_problem = true;
println!("Diagnostics: {}", parser.diagnostics.len());
if ALWAYS_PRINT_DIAGNOSTICS {
let use_colors = false;
for (k, diag) in parser.diagnostics.iter().enumerate() {
let rendered = pretty::render_diagnostic(diag, &tf, Some(label), use_colors);
println!("Diagnostic #{}:", k + 1);
println!("{rendered}");
pretty::render_diagnostic(diag, &tf, Some(label), use_colors);
}
}
}
@ -82,4 +192,4 @@ fn main() {
} else {
println!("Done. All cases completed without diagnostics.");
}
}
}