//! Frontend des Terminal-Basic-Compilers. //! //! Enthält Lexer, Parser, AST-Definitionen und die semantische Analyse //! (Symboltabellen, Typprüfung, implizite Deklarationen, `DEFINT`-Regeln usw.). //! Ausgabe des Frontends ist ein typgeprüfter AST, den `tb-vm` in Bytecode //! übersetzt. pub mod ast; pub mod hir; pub mod lexer; pub mod parser; pub mod sema; /// Quelltextposition für Diagnostik (1-basiert, wie im IDE-Vorbild). #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub struct SourcePos { pub line: u32, pub column: u32, } /// Eine Diagnosemeldung mit Position. Die Texte folgen den (englischen) /// Meldungen des Vorbilds, wo es eine Entsprechung gibt. #[derive(Debug, Clone)] pub struct Diagnostic { pub pos: SourcePos, pub message: String, } impl std::fmt::Display for Diagnostic { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}:{}: {}", self.pos.line, self.pos.column, self.message) } } /// Ergebnis der Frontend-Pipeline für ein Modul. pub struct Analysis { pub module: ast::Module, pub diagnostics: Vec, /// Typisiertes HIR (vollständig nur bei leeren Diagnosen). pub hir: Option, } /// Komplette Pipeline: Lexen → Parsen → semantische Prüfung + Lowering. pub fn analyze_source(module_name: &str, source: &str) -> Analysis { let lexed = lexer::lex(source); let mut diagnostics = lexed.diagnostics; let parsed = parser::parse(module_name, &lexed.tokens); diagnostics.extend(parsed.diagnostics); let (hir, sema_diags) = sema::lower(&parsed.module); diagnostics.extend(sema_diags); diagnostics.sort_by_key(|d| (d.pos.line, d.pos.column)); Analysis { module: parsed.module, diagnostics, hir } }