1#![doc = include_str!("readme.md")]
2use core::range::Range;
3
4pub type RubyAst = RubyRoot;
6
7#[derive(Debug, Clone, PartialEq)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct RubyRoot {
11 pub statements: Vec<StatementNode>,
13 #[serde(with = "oak_core::serde_range")]
15 pub span: Range<usize>,
16}
17
18#[derive(Debug, Clone, PartialEq)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21pub enum StatementNode {
22 Expression(ExpressionNode),
24 MethodDef {
26 name: String,
28 params: Vec<String>,
30 body: Vec<StatementNode>,
32 #[serde(with = "oak_core::serde_range")]
34 span: Range<usize>,
35 },
36 ClassDef {
38 name: String,
40 superclass: Option<String>,
42 body: Vec<StatementNode>,
44 #[serde(with = "oak_core::serde_range")]
46 span: Range<usize>,
47 },
48 Assignment {
50 target: String,
52 value: ExpressionNode,
54 #[serde(with = "oak_core::serde_range")]
56 span: Range<usize>,
57 },
58 If {
60 condition: ExpressionNode,
62 then_body: Vec<StatementNode>,
64 else_body: Option<Vec<StatementNode>>,
66 #[serde(with = "oak_core::serde_range")]
68 span: Range<usize>,
69 },
70 While {
72 condition: ExpressionNode,
74 body: Vec<StatementNode>,
76 #[serde(with = "oak_core::serde_range")]
78 span: Range<usize>,
79 },
80 Until {
82 condition: ExpressionNode,
84 body: Vec<StatementNode>,
86 #[serde(with = "oak_core::serde_range")]
88 span: Range<usize>,
89 },
90 Case {
92 value: ExpressionNode,
94 when_clauses: Vec<(ExpressionNode, Vec<StatementNode>)>,
96 else_clause: Option<Vec<StatementNode>>,
98 #[serde(with = "oak_core::serde_range")]
100 span: Range<usize>,
101 },
102 Return {
104 value: Option<ExpressionNode>,
106 #[serde(with = "oak_core::serde_range")]
108 span: Range<usize>,
109 },
110 Next {
112 #[serde(with = "oak_core::serde_range")]
114 span: Range<usize>,
115 },
116 Redo {
118 #[serde(with = "oak_core::serde_range")]
120 span: Range<usize>,
121 },
122}
123
124#[derive(Debug, Clone, PartialEq)]
126#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
127pub enum ExpressionNode {
128 Identifier {
130 name: String,
132 #[serde(with = "oak_core::serde_range")]
134 span: Range<usize>,
135 },
136 Literal(LiteralNode),
138 MethodCall {
140 receiver: Option<Box<ExpressionNode>>,
142 method: String,
144 args: Vec<ExpressionNode>,
146 #[serde(with = "oak_core::serde_range")]
148 span: Range<usize>,
149 },
150 BinaryOp {
152 left: Box<ExpressionNode>,
154 operator: String,
156 right: Box<ExpressionNode>,
158 #[serde(with = "oak_core::serde_range")]
160 span: Range<usize>,
161 },
162 UnaryOp {
164 operator: String,
166 operand: Box<ExpressionNode>,
168 #[serde(with = "oak_core::serde_range")]
170 span: Range<usize>,
171 },
172 Array {
174 elements: Vec<ExpressionNode>,
176 #[serde(with = "oak_core::serde_range")]
178 span: Range<usize>,
179 },
180 Hash {
182 pairs: Vec<(ExpressionNode, ExpressionNode)>,
184 #[serde(with = "oak_core::serde_range")]
186 span: Range<usize>,
187 },
188}
189
190#[derive(Debug, Clone, PartialEq)]
192#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
193pub enum LiteralNode {
194 Integer {
196 value: i64,
198 #[serde(with = "oak_core::serde_range")]
200 span: Range<usize>,
201 },
202 Float {
204 value: f64,
206 #[serde(with = "oak_core::serde_range")]
208 span: Range<usize>,
209 },
210 String {
212 value: String,
214 #[serde(with = "oak_core::serde_range")]
216 span: Range<usize>,
217 },
218 Symbol {
220 value: String,
222 #[serde(with = "oak_core::serde_range")]
224 span: Range<usize>,
225 },
226 Boolean {
228 value: bool,
230 #[serde(with = "oak_core::serde_range")]
232 span: Range<usize>,
233 },
234 Nil {
236 #[serde(with = "oak_core::serde_range")]
238 span: Range<usize>,
239 },
240}
241
242pub trait RubyAstVisitor {
244 fn visit_program(&mut self, node: &RubyRoot);
246 fn visit_statement(&mut self, stmt: &StatementNode);
248 fn visit_expression(&mut self, expr: &ExpressionNode);
250 fn visit_literal(&mut self, literal: &LiteralNode);
252}