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
//! This module contains the AST representation for expressions in the SAP language.
//!
//! An expression is a combination of one or more values, variables, operators, and
//! functions that evaluates to a single value. The AST nodes in this module represent the
//! different types of expressions that are supported in the SAP language.
//!
//! Expressions are used in the language to perform calculations, make decisions, and
//! manipulate data. They can be used as standalone statements, or as part of larger
//! expressions or statements.
//!
//! Note: The `Box` type is used to indicate that the data enclosed is stored on the heap,
//! rather than on the stack. This is necessary because otherwise the compiler needs to
//! know the size of the expression at compile time, which is not possible for recursive
//! data structures like the AST.
use lexer::token::TokenKind;
use serde::Serialize;
use shared::span::{GetSpan, Span};
use crate::literal::Literal;
use crate::StatementList;
/// Represents a single expression in the SAP language.
#[derive(Debug, Serialize, PartialEq, Clone)]
// Tell serde not to include this enum in the JSON output, since it only adds clutter and doesn't
// provide any useful information.
#[serde(untagged)]
pub enum Expression {
Identifier(Identifier),
Unary(Unary),
Binary(Binary),
Selection(Selection),
FunctionCall(FunctionCall),
Array(Array),
Index(Index),
Literal(Literal),
}
impl GetSpan for Expression {
fn span(&self) -> &Span {
match self {
Expression::Identifier(identifier) => &identifier.span,
Expression::Unary(unary) => &unary.span,
Expression::Binary(binary) => &binary.span,
Expression::Selection(selection) => &selection.span,
Expression::FunctionCall(function_call) => &function_call.span,
Expression::Array(array) => &array.span,
Expression::Index(index) => &index.span,
Expression::Literal(literal) => literal.span(),
}
}
}
/// Represents an identifier in the SAP language.
/// For example: `x`
#[derive(Debug, Serialize, PartialEq, Clone)]
#[serde(tag = "type")]
pub struct Identifier {
pub name: String,
pub span: Span,
}
/// Represents a unary expression in the SAP language.
/// For example: `-x`
#[derive(Debug, Serialize, PartialEq, Clone)]
#[serde(tag = "type")]
pub struct Unary {
pub operator: TokenKind,
pub operand: Box<Expression>,
pub span: Span,
}
/// Represents a binary expression in the SAP language.
/// For example: `x + 5`
#[derive(Debug, Serialize, PartialEq, Clone)]
#[serde(tag = "type")]
pub struct Binary {
pub operator: TokenKind,
pub left: Box<Expression>,
pub right: Box<Expression>,
pub span: Span,
}
/// Represents a selection expression in the SAP language.
/// For example:
/// ```sap
/// if x > 5 then
/// display "x is greater than 5"
/// otherwise
/// display "x is less than or equal to 5"
/// end
/// ```
#[derive(Debug, Serialize, PartialEq, Clone)]
#[serde(tag = "type")]
pub struct Selection {
pub condition: Box<Expression>,
pub conditional: StatementList,
pub else_conditional: Option<StatementList>,
pub span: Span,
}
/// Represents a function call expression in the SAP language.
/// For example: `add(5, 10)`
#[derive(Debug, Serialize, PartialEq, Clone)]
#[serde(tag = "type")]
pub struct FunctionCall {
/// The function being called. This can be an identifier or an expression which
/// evaluates to a function.
pub callee: Box<Expression>,
pub arguments: Vec<Expression>,
pub span: Span,
}
/// Represents an array expression in the SAP language.
/// For example: `[1, 2, 3, 4, 5]`
#[derive(Debug, Serialize, PartialEq, Clone)]
#[serde(tag = "type")]
pub struct Array {
pub elements: Vec<Expression>,
pub span: Span,
}
/// Represents an index expression in the SAP language.
/// For example: `arr[0]`
#[derive(Debug, Serialize, PartialEq, Clone)]
#[serde(tag = "type")]
pub struct Index {
pub object: Box<Expression>,
pub index: Box<Expression>,
pub span: Span,
}