1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/// The main statement enum, allowing for grouping of statements inside of the
/// AST.
#[derive(Debug, PartialEq)]
pub enum StatementNode {
    Function(Function),
    WhileLoop(WhileLoop),
    Variable(Variable),
}

/// The main expression enum, allowing for grouping of all expressions inside
/// of the AST.
#[derive(Debug, PartialEq)]
pub enum ExpressionNode {
    /// A binary operation (basic maths) involving 2 recursive
    /// [ExpressionNode]s.
    BinOp(Box<ExpressionNode>, BinOp, Box<ExpressionNode>),

    /// A constant forming from [Constant]
    Constant(Constant),
}

/// A binary operation type. Having a seperate enum for this avoids repitition
/// and allows for some optimisations downstream.
#[derive(Debug, PartialEq)]
pub enum BinOp {
    /// Addition. Example: `10+14` is `24`
    Add,

    /// Subtraction. Example: `5-3` is `2`
    Sub,

    /// Division. Example: `32/4` is `8`
    Div,

    /// Multiplication. Example: `5*11` is `55`
    Mul,

    /// Power of. Example: (`3^3` or `3**3`) is `81`
    Power,

    /// Modulo. Example: `20 % 2` is `0`
    Mod,
}

/// A while loop. This goes down into [WhileLoop] and would look something
/// like this in Zypo:
///
/// ```zypo
/// while(50 > 49) {
///     // --snip--
/// }
/// ```
#[derive(Debug, PartialEq)]
pub struct WhileLoop {
    pub condition: ExpressionNode,
    pub body: Vec<StatementNode>,
}

/// Similar to the [VarType] enum but with defined data in each possible
/// option.
#[derive(Debug, PartialEq)]
pub enum Constant {
    Int(i32),
    Str(String),
    Bool(bool),
}

/// Variable types for zypo-rs.
#[derive(Debug, PartialEq)]
pub enum VarType {
    /// An integer type (whole number).
    Int,

    /// A string type (char array/other types). This is not fully worked out yet.
    Str,

    /// A boolean (true/false).
    Bool,

    /// A null type, primarily used for functions that do not return anything.
    Void,
}

/// A function statement, the basis for the whole language. An example of a
/// function statement would be the following inside of Zypo itself:
///
/// ```zypo
/// fun number_adder(first_num: int, second_num: int) -> int {
///     // --snip--
/// }
/// ```
#[derive(Debug, PartialEq)]
pub struct Function {
    pub ident: String,
    pub params: Vec<Parameter>,
    pub body: Vec<StatementNode>,
    pub return_type: VarType,
}

/// A eration of a parameter. This would originally look like `my_id: str`
/// when being parsed.
///
/// This structure is usually used with the [Function] to generate the
/// parameters.
///
/// # Parser input
///
/// ```none
/// my_id: str
/// ```
///
/// # Generated AST
///
/// ```none
/// Parameter { ident: "my_id".to_string(), ty: VarType::Str }
/// ```
#[derive(Debug, PartialEq)]
pub struct Parameter {
    pub ident: String,
    pub ty: VarType,
}

/// Variable that includes a parameter but extends with a recursive
/// [ExpressionNode].
///
/// A variable declaration inside of the language would look like the
/// following:
///
/// ```zypo
/// var x: int = 3432;
/// ```
#[derive(Debug, PartialEq)]
pub struct Variable {
    pub ident: String,
    pub ty: VarType,
    pub body: Box<ExpressionNode>,
}