#![doc = include_str!("readme.md")]
use core::range::Range;
pub type RubyAst = RubyRoot;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct RubyRoot {
pub statements: Vec<StatementNode>,
#[serde(with = "oak_core::serde_range")]
pub span: Range<usize>,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum StatementNode {
Expression(ExpressionNode),
MethodDef {
name: String,
params: Vec<String>,
body: Vec<StatementNode>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
ClassDef {
name: String,
superclass: Option<String>,
body: Vec<StatementNode>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Assignment {
target: String,
value: ExpressionNode,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
If {
condition: ExpressionNode,
then_body: Vec<StatementNode>,
else_body: Option<Vec<StatementNode>>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
While {
condition: ExpressionNode,
body: Vec<StatementNode>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Until {
condition: ExpressionNode,
body: Vec<StatementNode>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Case {
value: ExpressionNode,
when_clauses: Vec<(ExpressionNode, Vec<StatementNode>)>,
else_clause: Option<Vec<StatementNode>>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Return {
value: Option<ExpressionNode>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Next {
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Redo {
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ExpressionNode {
Identifier {
name: String,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Literal(LiteralNode),
MethodCall {
receiver: Option<Box<ExpressionNode>>,
method: String,
args: Vec<ExpressionNode>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
BinaryOp {
left: Box<ExpressionNode>,
operator: String,
right: Box<ExpressionNode>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
UnaryOp {
operator: String,
operand: Box<ExpressionNode>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Array {
elements: Vec<ExpressionNode>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Hash {
pairs: Vec<(ExpressionNode, ExpressionNode)>,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum LiteralNode {
Integer {
value: i64,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Float {
value: f64,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
String {
value: String,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Symbol {
value: String,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Boolean {
value: bool,
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
Nil {
#[serde(with = "oak_core::serde_range")]
span: Range<usize>,
},
}
pub trait RubyAstVisitor {
fn visit_program(&mut self, node: &RubyRoot);
fn visit_statement(&mut self, stmt: &StatementNode);
fn visit_expression(&mut self, expr: &ExpressionNode);
fn visit_literal(&mut self, literal: &LiteralNode);
}