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    /// Return statement
81    Return {
82        /// Return value
83        value: Option<ExpressionNode>,
84        /// Source code span
85        #[serde(with = "oak_core::serde_range")]
86        span: Range<usize>,
87    },
88}
89
90/// Ruby expression node
91#[derive(Debug, Clone, PartialEq)]
92#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
93pub enum ExpressionNode {
94    /// Identifier
95    Identifier {
96        /// Identifier name
97        name: String,
98        /// Source code span
99        #[serde(with = "oak_core::serde_range")]
100        span: Range<usize>,
101    },
102    /// Literal
103    Literal(LiteralNode),
104    /// Method call
105    MethodCall {
106        /// Receiver
107        receiver: Option<Box<ExpressionNode>>,
108        /// Method name
109        method: String,
110        /// Argument list
111        args: Vec<ExpressionNode>,
112        /// Source code span
113        #[serde(with = "oak_core::serde_range")]
114        span: Range<usize>,
115    },
116    /// Binary operation
117    BinaryOp {
118        /// Left operand
119        left: Box<ExpressionNode>,
120        /// Operator
121        operator: String,
122        /// Right operand
123        right: Box<ExpressionNode>,
124        /// Source code span
125        #[serde(with = "oak_core::serde_range")]
126        span: Range<usize>,
127    },
128    /// Unary operation
129    UnaryOp {
130        /// Operator
131        operator: String,
132        /// Operand
133        operand: Box<ExpressionNode>,
134        /// Source code span
135        #[serde(with = "oak_core::serde_range")]
136        span: Range<usize>,
137    },
138    /// Array
139    Array {
140        /// Array element list
141        elements: Vec<ExpressionNode>,
142        /// Source code span
143        #[serde(with = "oak_core::serde_range")]
144        span: Range<usize>,
145    },
146    /// Hash
147    Hash {
148        /// The key-value pairs in the hash.
149        pairs: Vec<(ExpressionNode, ExpressionNode)>,
150        /// The source span of the hash.
151        #[serde(with = "oak_core::serde_range")]
152        span: Range<usize>,
153    },
154}
155
156/// Literal node
157#[derive(Debug, Clone, PartialEq)]
158#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
159pub enum LiteralNode {
160    /// Integer literal
161    Integer {
162        /// The integer value.
163        value: i64,
164        /// The source span of the integer.
165        #[serde(with = "oak_core::serde_range")]
166        span: Range<usize>,
167    },
168    /// Float literal
169    Float {
170        /// The floating-point value.
171        value: f64,
172        /// The source span of the float.
173        #[serde(with = "oak_core::serde_range")]
174        span: Range<usize>,
175    },
176    /// String literal
177    String {
178        /// The string value.
179        value: String,
180        /// The source span of the string.
181        #[serde(with = "oak_core::serde_range")]
182        span: Range<usize>,
183    },
184    /// Symbol literal
185    Symbol {
186        /// The symbol value.
187        value: String,
188        /// The source span of the symbol.
189        #[serde(with = "oak_core::serde_range")]
190        span: Range<usize>,
191    },
192    /// Boolean literal
193    Boolean {
194        /// The boolean value.
195        value: bool,
196        /// The source span of the boolean.
197        #[serde(with = "oak_core::serde_range")]
198        span: Range<usize>,
199    },
200    /// nil
201    Nil {
202        /// The source span of the nil literal.
203        #[serde(with = "oak_core::serde_range")]
204        span: Range<usize>,
205    },
206}
207
208/// Ruby AST visitor trait
209pub trait RubyAstVisitor {
210    /// Visits the root program node.
211    fn visit_program(&mut self, node: &RubyRoot);
212    /// Visits a statement node.
213    fn visit_statement(&mut self, stmt: &StatementNode);
214    /// Visits an expression node.
215    fn visit_expression(&mut self, expr: &ExpressionNode);
216    /// Visits a literal node.
217    fn visit_literal(&mut self, literal: &LiteralNode);
218}