Skip to main content

compiler/
compiler.rs

1use duck_diagnostic::*;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4enum LangError {
5  UnterminatedString,
6  InvalidCharacter,
7  UnexpectedToken,
8  MissingSemicolon,
9  ExpectedExpression,
10  UndeclaredVariable,
11  TypeMismatch,
12  UnusedVariable,
13  UnreachableCode,
14}
15
16impl DiagnosticCode for LangError {
17  fn code(&self) -> &str {
18    match self {
19      Self::UnterminatedString => "E0001",
20      Self::InvalidCharacter => "E0002",
21      Self::UnexpectedToken => "E0100",
22      Self::MissingSemicolon => "E0101",
23      Self::ExpectedExpression => "E0102",
24      Self::UndeclaredVariable => "E0200",
25      Self::TypeMismatch => "E0201",
26      Self::UnusedVariable => "W0001",
27      Self::UnreachableCode => "W0002",
28    }
29  }
30
31  fn severity(&self) -> Severity {
32    match self {
33      Self::UnusedVariable | Self::UnreachableCode => Severity::Warning,
34      _ => Severity::Error,
35    }
36  }
37}
38
39fn main() {
40  let source = r#"fn main() {
41    let name = "hello
42    let x = 42;
43    println(name);
44}"#;
45
46  let mut engine = DiagnosticEngine::<LangError>::new();
47
48  engine.emit(
49    Diagnostic::new(LangError::UnterminatedString, "unterminated string literal")
50      .with_label(Label::primary(
51        Span::new("main.lang", 2, 16, 6),
52        Some("string starts here but never closes".into()),
53      ))
54      .with_help("close the string with a matching `\"`"),
55  );
56
57  engine.emit(
58    Diagnostic::new(LangError::UnusedVariable, "unused variable `x`")
59      .with_label(Label::primary(
60        Span::new("main.lang", 3, 8, 1),
61        Some("declared here but never used".into()),
62      ))
63      .with_help("prefix with `_` to silence: `_x`"),
64  );
65
66  engine.print_all(source);
67}