sipha_tree/lowering/
trait_impl.rs

1//! AST lowering trait and context.
2
3use builder_pattern::Builder;
4use sipha_core::traits::{NodeId, RuleId, TokenKind};
5use std::fmt::Debug;
6
7use crate::node::CstNode;
8
9/// Context data shared by AST lowering routines.
10///
11/// This context is passed to `AstNode::lower` methods during AST lowering.
12/// It can be extended to include symbol tables, diagnostics, or other context
13/// needed during the lowering process.
14///
15/// # Usage
16///
17/// ```rust
18/// use sipha_tree::lowering::LowerCtx;
19///
20/// let mut ctx = LowerCtx::builder()
21///     .build();
22///
23/// // Add notes during lowering
24/// ctx.notes.push("Processing expression".to_string());
25/// ```
26///
27/// # Extending
28///
29/// For custom context, create a wrapper:
30///
31/// ```rust
32/// struct MyLoweringContext {
33///     ctx: LowerCtx,
34///     symbol_table: SymbolTable,
35/// }
36/// ```
37#[derive(Builder, Debug, Clone, Default)]
38pub struct LowerCtx {
39    /// Future extension point for diagnostics or symbol lookups.
40    /// Use this to collect notes, warnings, or other information during lowering.
41    pub notes: Vec<String>,
42}
43
44/// AST nodes implement this trait so they can be lowered from CST nodes.
45///
46/// This trait enables conversion from Concrete Syntax Trees (CST) to
47/// Abstract Syntax Trees (AST). CST nodes preserve all syntax information,
48/// while AST nodes represent semantic structure.
49///
50/// # Implementation
51///
52/// Implement this trait for each AST node type:
53///
54/// ```rust
55/// use sipha_tree::lowering::{AstNode, LowerCtx};
56/// use sipha_tree::CstNode;
57///
58/// #[derive(Clone)]
59/// enum Expr {
60///     Literal(i64),
61///     Binary { op: Op, left: Box<Expr>, right: Box<Expr> },
62/// }
63///
64/// impl AstNode for Expr {
65///     type TokenKind = Token;
66///     type Rule = Rule;
67///     type Node = RawNodeId;
68///     type Error = String;
69///
70///     fn lower(
71///         cst: &CstNode<Self::TokenKind, Self::Rule, Self::Node>,
72///         ctx: &mut LowerCtx,
73///     ) -> Result<Self, Self::Error> {
74///         // Convert CST node to AST node
75///         // ...
76///     }
77/// }
78/// ```
79///
80/// # Error Handling
81///
82/// Lowering can fail for various reasons:
83/// - Unexpected node structure
84/// - Invalid token values
85/// - Missing required children
86/// - Type conversion errors
87///
88/// Return descriptive errors to help with debugging.
89pub trait AstNode: Sized + Clone {
90    /// Token kind enum used by the CST.
91    type TokenKind: TokenKind;
92    /// Grammar rule identifier.
93    type Rule: RuleId;
94    /// Node identifier stored in the arena.
95    type Node: NodeId;
96    /// Error type produced during lowering.
97    type Error: std::error::Error + Debug + Clone + Send + Sync + 'static;
98
99    /// Lower a CST node into the strongly-typed AST representation.
100    fn lower(
101        cst: &CstNode<Self::TokenKind, Self::Rule, Self::Node>,
102        ctx: &mut LowerCtx,
103    ) -> Result<Self, Self::Error>;
104}