Improve diagnostics

This commit is contained in:
Laurenz 2022-05-04 23:26:15 +02:00
parent 2a45650dcc
commit 1bca9ccecb
9 changed files with 33 additions and 24 deletions

View File

@ -604,6 +604,7 @@ fn collection(p: &mut Parser, keyed: bool) -> (CollectionKind, usize) {
missing_coma = Some(p.trivia_start()); missing_coma = Some(p.trivia_start());
} }
} else { } else {
p.eat_if(NodeKind::Comma);
kind = Some(CollectionKind::Group); kind = Some(CollectionKind::Group);
} }
} }
@ -638,11 +639,15 @@ fn item(p: &mut Parser, keyed: bool) -> ParseResult<NodeKind> {
p.eat(); p.eat();
marker.perform(p, NodeKind::Keyed, expr)?; marker.perform(p, NodeKind::Keyed, expr)?;
} }
_ => { kind => {
let mut msg = EcoString::from("expected identifier"); let mut msg = EcoString::from("expected identifier");
if keyed { if keyed {
msg.push_str(" or string"); msg.push_str(" or string");
} }
if let Some(kind) = kind {
msg.push_str(", found ");
msg.push_str(kind.as_str());
}
let error = NodeKind::Error(ErrorPos::Full, msg); let error = NodeKind::Error(ErrorPos::Full, msg);
marker.end(p, error); marker.end(p, error);
p.eat(); p.eat();
@ -661,8 +666,7 @@ fn item(p: &mut Parser, keyed: bool) -> ParseResult<NodeKind> {
/// expressions. /// expressions.
fn array(p: &mut Parser, marker: Marker) { fn array(p: &mut Parser, marker: Marker) {
marker.filter_children(p, |x| match x.kind() { marker.filter_children(p, |x| match x.kind() {
NodeKind::Named => Err("expected expression, found named pair"), NodeKind::Named | NodeKind::Keyed => Err("expected expression"),
NodeKind::Keyed => Err("expected expression, found keyed pair"),
_ => Ok(()), _ => Ok(()),
}); });
marker.end(p, NodeKind::ArrayExpr); marker.end(p, NodeKind::ArrayExpr);
@ -685,7 +689,7 @@ fn dict(p: &mut Parser, marker: Marker) {
Ok(()) Ok(())
} }
NodeKind::Spread | NodeKind::Comma | NodeKind::Colon => Ok(()), NodeKind::Spread | NodeKind::Comma | NodeKind::Colon => Ok(()),
_ => Err("expected named or keyed pair, found expression"), _ => Err("expected named or keyed pair"),
}); });
marker.end(p, NodeKind::DictExpr); marker.end(p, NodeKind::DictExpr);
} }

View File

@ -4,6 +4,7 @@ use std::ops::Range;
use super::{TokenMode, Tokens}; use super::{TokenMode, Tokens};
use crate::syntax::{ErrorPos, Green, GreenData, GreenNode, NodeKind}; use crate::syntax::{ErrorPos, Green, GreenData, GreenNode, NodeKind};
use crate::util::EcoString;
/// A convenient token-based parser. /// A convenient token-based parser.
pub struct Parser<'s> { pub struct Parser<'s> {
@ -474,7 +475,12 @@ impl Marker {
} }
if let Err(msg) = f(child) { if let Err(msg) = f(child) {
let error = NodeKind::Error(ErrorPos::Full, msg.into()); let mut msg = EcoString::from(msg);
if msg.starts_with("expected") {
msg.push_str(", found ");
msg.push_str(child.kind().as_str());
}
let error = NodeKind::Error(ErrorPos::Full, msg);
let inner = mem::take(child); let inner = mem::take(child);
*child = GreenNode::with_child(error, inner).into(); *child = GreenNode::with_child(error, inner).into();
} }

View File

@ -964,7 +964,7 @@ pub enum ClosureParam {
Pos(Ident), Pos(Ident),
/// A named parameter with a default value: `draw: false`. /// A named parameter with a default value: `draw: false`.
Named(Named), Named(Named),
/// A parameter sink: `..args`. /// An argument sink: `..args`.
Sink(Ident), Sink(Ident),
} }

View File

@ -662,7 +662,7 @@ pub enum NodeKind {
MethodCall, MethodCall,
/// A function call's argument list: `(x, y)`. /// A function call's argument list: `(x, y)`.
CallArgs, CallArgs,
/// Spreaded arguments or a parameter sink: `..x`. /// Spreaded arguments or a argument sink: `..x`.
Spread, Spread,
/// A closure expression: `(x, y) => z`. /// A closure expression: `(x, y) => z`.
ClosureExpr, ClosureExpr,
@ -906,7 +906,7 @@ impl NodeKind {
Self::FuncCall => "function call", Self::FuncCall => "function call",
Self::MethodCall => "method call", Self::MethodCall => "method call",
Self::CallArgs => "call arguments", Self::CallArgs => "call arguments",
Self::Spread => "parameter sink", Self::Spread => "spread",
Self::ClosureExpr => "closure", Self::ClosureExpr => "closure",
Self::ClosureParams => "closure parameters", Self::ClosureParams => "closure parameters",
Self::LetExpr => "`let` expression", Self::LetExpr => "`let` expression",

View File

@ -79,17 +79,17 @@
// Error: 8 expected comma // Error: 8 expected comma
#func(1 2) #func(1 2)
// Error: 7-8 expected identifier // Error: 7-8 expected identifier, found integer
// Error: 9 expected expression // Error: 9 expected expression
#func(1:) #func(1:)
// Error: 7-8 expected identifier // Error: 7-8 expected identifier, found integer
#func(1:2) #func(1:2)
// Error: 7-12 expected identifier // Error: 7-12 expected identifier, found string
#func("abc": 2) #func("abc": 2)
// Error: 7-10 expected identifier // Error: 7-10 expected identifier, found group
{func((x):1)} {func((x):1)}
--- ---

View File

@ -145,13 +145,13 @@
} }
--- ---
// Error: 6-16 expected identifier, named pair or argument sink // Error: 6-16 expected identifier, named pair or argument sink, found keyed pair
{(a, "named": b) => none} {(a, "named": b) => none}
--- ---
// Error: 10-15 expected identifier // Error: 10-15 expected identifier, found string
#let foo("key": b) = key #let foo("key": b) = key
--- ---
// Error: 10-14 expected identifier // Error: 10-14 expected identifier, found `none`
#let foo(none: b) = key #let foo(none: b) = key

View File

@ -49,12 +49,12 @@
--- ---
// Simple expression after already being identified as a dictionary. // Simple expression after already being identified as a dictionary.
// Error: 9-10 expected named or keyed pair, found expression // Error: 9-10 expected named or keyed pair, found identifier
{(a: 1, b)} {(a: 1, b)}
// Identified as dictionary due to initial colon. // Identified as dictionary due to initial colon.
// Error: 4-5 expected named or keyed pair, found expression // Error: 4-5 expected named or keyed pair, found integer
// Error: 5 expected comma // Error: 5 expected comma
// Error: 12-16 expected identifier or string // Error: 12-16 expected identifier or string, found boolean
// Error: 17-18 expected expression, found colon // Error: 17-18 expected expression, found colon
{(:1 b:"", true::)} {(:1 b:"", true::)}

View File

@ -71,11 +71,11 @@ This is never reached.
// Error: 8 expected keyword `from` // Error: 8 expected keyword `from`
#import #import
// Error: 9-19 expected identifier // Error: 9-19 expected identifier, found string
// Error: 19 expected keyword `from` // Error: 19 expected keyword `from`
#import "file.typ" #import "file.typ"
// Error: 16-19 expected identifier // Error: 16-19 expected identifier, found string
// Error: 22 expected keyword `from` // Error: 22 expected keyword `from`
#import afrom, "b", c #import afrom, "b", c
@ -108,7 +108,6 @@ This is never reached.
// A star in the list. // A star in the list.
// Error: 12-13 expected expression, found star // Error: 12-13 expected expression, found star
// Error: 13-14 expected expression, found comma
#import a, *, b from "target.typ" #import a, *, b from "target.typ"
// An item after a star. // An item after a star.
@ -117,5 +116,5 @@ This is never reached.
#import *, a from "target.typ" #import *, a from "target.typ"
--- ---
// Error: 9-13 expected identifier // Error: 9-13 expected identifier, found named pair
#import a: 1 from "" #import a: 1 from ""

View File

@ -62,7 +62,7 @@
#min(.."nope") #min(.."nope")
--- ---
// Error: 8-14 expected identifier, named pair or argument sink // Error: 8-14 expected identifier, named pair or argument sink, found spread
#let f(..true) = none #let f(..true) = none
--- ---