Implement comprehensive diagnostic reporting system: - Add Diagnostic struct with severity levels and span-based error tracking - Add diagnostic rendering with source context and caret positioning - Replace ParseError with diagnostic collection in lexer and parser - Add LexResult and ParseResult types to carry diagnostics Enhance driver crate with frontend output: - Replace CompileResult with FrontendOutput containing diagnostics - Add has_errors() and render_diagnostics() methods - Add AstSummary for
140 lines
3.0 KiB
Rust
140 lines
3.0 KiB
Rust
use std::fmt;
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
|
pub struct Span {
|
|
pub start: usize,
|
|
pub end: usize,
|
|
pub start_line: usize,
|
|
pub start_column: usize,
|
|
pub end_line: usize,
|
|
pub end_column: usize,
|
|
}
|
|
|
|
impl Span {
|
|
pub fn new(
|
|
start: usize,
|
|
end: usize,
|
|
start_line: usize,
|
|
start_column: usize,
|
|
end_line: usize,
|
|
end_column: usize,
|
|
) -> Self {
|
|
Self {
|
|
start,
|
|
end,
|
|
start_line,
|
|
start_column,
|
|
end_line,
|
|
end_column,
|
|
}
|
|
}
|
|
|
|
pub fn single(position: usize, line: usize, column: usize) -> Self {
|
|
Self::new(position, position, line, column, line, column)
|
|
}
|
|
|
|
pub fn merge(self, other: Self) -> Self {
|
|
Self {
|
|
start: self.start.min(other.start),
|
|
end: self.end.max(other.end),
|
|
start_line: self.start_line,
|
|
start_column: self.start_column,
|
|
end_line: other.end_line,
|
|
end_column: other.end_column,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct Token {
|
|
pub kind: TokenKind,
|
|
pub span: Span,
|
|
}
|
|
|
|
impl Token {
|
|
pub fn new(kind: TokenKind, span: Span) -> Self {
|
|
Self { kind, span }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum TokenKind {
|
|
Identifier(String),
|
|
Integer(String),
|
|
Float(String),
|
|
String(String),
|
|
Bool(bool),
|
|
Keyword(Keyword),
|
|
LeftParen,
|
|
RightParen,
|
|
Comma,
|
|
Colon,
|
|
Arrow,
|
|
Plus,
|
|
Minus,
|
|
Star,
|
|
Slash,
|
|
Percent,
|
|
Equal,
|
|
EqualEqual,
|
|
Bang,
|
|
BangEqual,
|
|
Less,
|
|
LessEqual,
|
|
Greater,
|
|
GreaterEqual,
|
|
AndAnd,
|
|
OrOr,
|
|
Newline,
|
|
Indent,
|
|
Dedent,
|
|
Eof,
|
|
}
|
|
|
|
impl TokenKind {
|
|
pub fn same_variant(&self, other: &Self) -> bool {
|
|
std::mem::discriminant(self) == std::mem::discriminant(other)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum Keyword {
|
|
Else,
|
|
Fn,
|
|
If,
|
|
Let,
|
|
Pub,
|
|
Return,
|
|
Struct,
|
|
}
|
|
|
|
impl Keyword {
|
|
pub fn from_ident(value: &str) -> Option<Self> {
|
|
match value {
|
|
"else" => Some(Self::Else),
|
|
"fn" => Some(Self::Fn),
|
|
"if" => Some(Self::If),
|
|
"let" => Some(Self::Let),
|
|
"pub" => Some(Self::Pub),
|
|
"return" => Some(Self::Return),
|
|
"struct" => Some(Self::Struct),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for TokenKind {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
TokenKind::Identifier(name) => write!(f, "identifier({name})"),
|
|
TokenKind::Integer(value) => write!(f, "integer({value})"),
|
|
TokenKind::Float(value) => write!(f, "float({value})"),
|
|
TokenKind::String(value) => write!(f, "string({value})"),
|
|
TokenKind::Bool(value) => write!(f, "bool({value})"),
|
|
TokenKind::Keyword(keyword) => write!(f, "keyword({keyword:?})"),
|
|
other => write!(f, "{other:?}"),
|
|
}
|
|
}
|
|
}
|
|
|