Skip to main content

oak_ruby/ast/
mod.rs

1#![doc = include_str!("readme.md")]
2use core::range::Range;
3
4/// Ruby AST root node
5pub type RubyAst = RubyRoot;
6
7/// Program node
8#[derive(Debug, Clone, PartialEq)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct RubyRoot {
11    /// List of statements
12    pub statements: Vec<StatementNode>,
13    /// Source code span
14    #[serde(with = "oak_core::serde_range")]
15    pub span: Range<usize>,
16}
17
18/// Ruby statement node
19#[derive(Debug, Clone, PartialEq)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21pub enum StatementNode {
22    /// Expression statement
23    Expression(ExpressionNode),
24    /// Method definition
25    MethodDef {
26        /// Method name
27        name: String,
28        /// Parameter list
29        params: Vec<String>,
30        /// Method body
31        body: Vec<StatementNode>,
32        /// Source code span
33        #[serde(with = "oak_core::serde_range")]
34        span: Range<usize>,
35    },
36    /// Class definition
37    ClassDef {
38        /// Class name
39        name: String,
40        /// Superclass name
41        superclass: Option<String>,
42        /// Class body
43        body: Vec<StatementNode>,
44        /// Source code span
45        #[serde(with = "oak_core::serde_range")]
46        span: Range<usize>,
47    },
48    /// Assignment statement
49    Assignment {
50        /// Assignment target
51        target: String,
52        /// Assignment value
53        value: ExpressionNode,
54        /// Source code span
55        #[serde(with = "oak_core::serde_range")]
56        span: Range<usize>,
57    },
58    /// Conditional statement
59    If {
60        /// Condition expression
61        condition: ExpressionNode,
62        /// then branch
63        then_body: Vec<StatementNode>,
64        /// else branch
65        else_body: Option<Vec<StatementNode>>,
66        /// Source code span
67        #[serde(with = "oak_core::serde_range")]
68        span: Range<usize>,
69    },
70    /// Loop statement
71    While {
72        /// Condition expression
73        condition: ExpressionNode,
74        /// Loop body
75        body: Vec<StatementNode>,
76        /// Source code span
77        #[serde(with = "oak_core::serde_range")]
78        span: Range<usize>,
79    },
80    /// Until loop statement
81    Until {
82        /// Condition expression
83        condition: ExpressionNode,
84        /// Loop body
85        body: Vec<StatementNode>,
86        /// Source code span
87        #[serde(with = "oak_core::serde_range")]
88        span: Range<usize>,
89    },
90    /// Case statement
91    Case {
92        /// Value expression
93        value: ExpressionNode,
94        /// When clauses
95        when_clauses: Vec<(ExpressionNode, Vec<StatementNode>)>,
96        /// Else clause
97        else_clause: Option<Vec<StatementNode>>,
98        /// Source code span
99        #[serde(with = "oak_core::serde_range")]
100        span: Range<usize>,
101    },
102    /// Return statement
103    Return {
104        /// Return value
105        value: Option<ExpressionNode>,
106        /// Source code span
107        #[serde(with = "oak_core::serde_range")]
108        span: Range<usize>,
109    },
110    /// Next statement
111    Next {
112        /// Source code span
113        #[serde(with = "oak_core::serde_range")]
114        span: Range<usize>,
115    },
116    /// Redo statement
117    Redo {
118        /// Source code span
119        #[serde(with = "oak_core::serde_range")]
120        span: Range<usize>,
121    },
122}
123
124/// Ruby expression node
125#[derive(Debug, Clone, PartialEq)]
126#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
127pub enum ExpressionNode {
128    /// Identifier
129    Identifier {
130        /// Identifier name
131        name: String,
132        /// Source code span
133        #[serde(with = "oak_core::serde_range")]
134        span: Range<usize>,
135    },
136    /// Literal
137    Literal(LiteralNode),
138    /// Method call
139    MethodCall {
140        /// Receiver
141        receiver: Option<Box<ExpressionNode>>,
142        /// Method name
143        method: String,
144        /// Argument list
145        args: Vec<ExpressionNode>,
146        /// Source code span
147        #[serde(with = "oak_core::serde_range")]
148        span: Range<usize>,
149    },
150    /// Binary operation
151    BinaryOp {
152        /// Left operand
153        left: Box<ExpressionNode>,
154        /// Operator
155        operator: String,
156        /// Right operand
157        right: Box<ExpressionNode>,
158        /// Source code span
159        #[serde(with = "oak_core::serde_range")]
160        span: Range<usize>,
161    },
162    /// Unary operation
163    UnaryOp {
164        /// Operator
165        operator: String,
166        /// Operand
167        operand: Box<ExpressionNode>,
168        /// Source code span
169        #[serde(with = "oak_core::serde_range")]
170        span: Range<usize>,
171    },
172    /// Array
173    Array {
174        /// Array element list
175        elements: Vec<ExpressionNode>,
176        /// Source code span
177        #[serde(with = "oak_core::serde_range")]
178        span: Range<usize>,
179    },
180    /// Hash
181    Hash {
182        /// The key-value pairs in the hash.
183        pairs: Vec<(ExpressionNode, ExpressionNode)>,
184        /// The source span of the hash.
185        #[serde(with = "oak_core::serde_range")]
186        span: Range<usize>,
187    },
188}
189
190/// Literal node
191#[derive(Debug, Clone, PartialEq)]
192#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
193pub enum LiteralNode {
194    /// Integer literal
195    Integer {
196        /// The integer value.
197        value: i64,
198        /// The source span of the integer.
199        #[serde(with = "oak_core::serde_range")]
200        span: Range<usize>,
201    },
202    /// Float literal
203    Float {
204        /// The floating-point value.
205        value: f64,
206        /// The source span of the float.
207        #[serde(with = "oak_core::serde_range")]
208        span: Range<usize>,
209    },
210    /// String literal
211    String {
212        /// The string value.
213        value: String,
214        /// The source span of the string.
215        #[serde(with = "oak_core::serde_range")]
216        span: Range<usize>,
217    },
218    /// Symbol literal
219    Symbol {
220        /// The symbol value.
221        value: String,
222        /// The source span of the symbol.
223        #[serde(with = "oak_core::serde_range")]
224        span: Range<usize>,
225    },
226    /// Boolean literal
227    Boolean {
228        /// The boolean value.
229        value: bool,
230        /// The source span of the boolean.
231        #[serde(with = "oak_core::serde_range")]
232        span: Range<usize>,
233    },
234    /// nil
235    Nil {
236        /// The source span of the nil literal.
237        #[serde(with = "oak_core::serde_range")]
238        span: Range<usize>,
239    },
240}
241
242/// Ruby AST visitor trait
243pub trait RubyAstVisitor {
244    /// Visits the root program node.
245    fn visit_program(&mut self, node: &RubyRoot);
246    /// Visits a statement node.
247    fn visit_statement(&mut self, stmt: &StatementNode);
248    /// Visits an expression node.
249    fn visit_expression(&mut self, expr: &ExpressionNode);
250    /// Visits a literal node.
251    fn visit_literal(&mut self, literal: &LiteralNode);
252}