Files
NexaCore/crates/nxc-frontend/src/token.rs
nessi dfd2f10234 feat: add diagnostic system and improve CLI with check command
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
2026-04-06 17:07:50 +02:00

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:?}"),
}
}
}