1#![doc = include_str!("readme.md")]
2use core::range::Range;
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6pub type RubyAst = RubyRoot;
8
9#[derive(Debug, Clone, PartialEq)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12pub struct RubyRoot {
13 pub statements: Vec<StatementNode>,
14 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
15 pub span: Range<usize>,
16}
17
18#[derive(Debug, Clone, PartialEq)]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21pub enum StatementNode {
22 Expression(ExpressionNode),
24 MethodDef {
26 name: String,
27 params: Vec<String>,
28 body: Vec<StatementNode>,
29 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
30 span: Range<usize>,
31 },
32 ClassDef {
34 name: String,
35 superclass: Option<String>,
36 body: Vec<StatementNode>,
37 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
38 span: Range<usize>,
39 },
40 Assignment {
42 target: String,
43 value: ExpressionNode,
44 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
45 span: Range<usize>,
46 },
47 If {
49 condition: ExpressionNode,
50 then_body: Vec<StatementNode>,
51 else_body: Option<Vec<StatementNode>>,
52 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
53 span: Range<usize>,
54 },
55 While {
57 condition: ExpressionNode,
58 body: Vec<StatementNode>,
59 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
60 span: Range<usize>,
61 },
62 Return {
64 value: Option<ExpressionNode>,
65 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
66 span: Range<usize>,
67 },
68}
69
70#[derive(Debug, Clone, PartialEq)]
72#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
73pub enum ExpressionNode {
74 Identifier {
76 name: String,
77 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
78 span: Range<usize>,
79 },
80 Literal(LiteralNode),
82 MethodCall {
84 receiver: Option<Box<ExpressionNode>>,
85 method: String,
86 args: Vec<ExpressionNode>,
87 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
88 span: Range<usize>,
89 },
90 BinaryOp {
92 left: Box<ExpressionNode>,
93 operator: String,
94 right: Box<ExpressionNode>,
95 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
96 span: Range<usize>,
97 },
98 UnaryOp {
100 operator: String,
101 operand: Box<ExpressionNode>,
102 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
103 span: Range<usize>,
104 },
105 Array {
107 elements: Vec<ExpressionNode>,
108 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
109 span: Range<usize>,
110 },
111 Hash {
113 pairs: Vec<(ExpressionNode, ExpressionNode)>,
114 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
115 span: Range<usize>,
116 },
117}
118
119#[derive(Debug, Clone, PartialEq)]
121#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
122pub enum LiteralNode {
123 Integer {
125 value: i64,
126 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
127 span: Range<usize>,
128 },
129 Float {
131 value: f64,
132 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
133 span: Range<usize>,
134 },
135 String {
137 value: String,
138 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
139 span: Range<usize>,
140 },
141 Symbol {
143 value: String,
144 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
145 span: Range<usize>,
146 },
147 Boolean {
149 value: bool,
150 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
151 span: Range<usize>,
152 },
153 Nil {
155 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
156 span: Range<usize>,
157 },
158}
159
160pub trait RubyAstVisitor {
162 fn visit_program(&mut self, node: &RubyRoot);
163 fn visit_statement(&mut self, stmt: &StatementNode);
164 fn visit_expression(&mut self, expr: &ExpressionNode);
165 fn visit_literal(&mut self, literal: &LiteralNode);
166}