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}