Skip to main content

swan_core/
ast.rs

1//! The abstract syntax tree produced by the [`Parser`](crate::parser::Parser).
2//!
3//! A parsed expression is a tree of [`Node`]s. Every node records `pos`, the
4//! byte offset in the source of the token that produced it (for a binary
5//! operation, the operator; for function application, which has no operator,
6//! the start of the argument). Evaluation errors report this position.
7//!
8//! Syntax errors do not stop parsing. They become [`Node::Unclosed`] or
9//! [`Node::UnexpectedToken`] leaves, which evaluate to `Undefined` values.
10
11
12/// A leaf node: a literal value and its source position.
13#[derive(Debug, PartialEq, Clone)]
14pub struct Leaf<T> {
15    /// Byte offset of the token in the source.
16    pub pos: usize,
17    /// The literal value.
18    pub val: T,
19}
20
21
22/// A node with one operand: a prefix operator or a bracketed group.
23#[derive(Debug, PartialEq, Clone)]
24pub struct UnaryOp {
25    /// Byte offset of the operator or opening bracket in the source.
26    pub pos: usize,
27    /// The operand.
28    pub opd: Box<Node>,
29}
30
31
32/// A node with two operands: an infix operator or function application.
33#[derive(Debug, PartialEq, Clone)]
34pub struct BinaryOp {
35    /// Byte offset of the operator in the source. For function application,
36    /// which has no operator, it is the byte offset of the argument.
37    pub pos: usize,
38    /// The left-hand operand.
39    pub lho: Box<Node>,
40    /// The right-hand operand.
41    pub rho: Box<Node>,
42}
43
44
45
46
47/// A node of the Swan syntax tree.
48///
49/// The comment on each variant shows the syntax that produces it.
50#[derive(Debug, PartialEq, Clone)]
51pub enum Node {
52
53    // Literals / Leaves
54
55    /// A name, such as `x` or `my_var`.
56    Identifier(Leaf<String>),
57    /// A number literal, such as `42` or `1.5e-3`.
58    Numb(Leaf<f64>),
59    /// A text literal, such as `"hello"`. The value excludes the quotes.
60    Text(Leaf<String>),
61    /// `()`, or an empty expression.
62    Nothing(Leaf<()>),
63    /// Syntax error: a group that is not closed. The value is the missing
64    /// closing bracket (`)`, `]` or `}`).
65    Unclosed(Leaf<char>),
66    /// Syntax error: a token that cannot appear where it was found. The value
67    /// is a debug description of the token.
68    UnexpectedToken(Leaf<String>),
69
70
71    // Grouping
72
73    /// `[X]`: a list literal.
74    List(UnaryOp),
75    /// `{X}`: a namespace literal.
76    Namespace(UnaryOp),
77
78
79    // Unary Operations
80
81    /// `+X`
82    AffirmOp(UnaryOp),
83    /// `-X`
84    NegateOp(UnaryOp),
85    /// `!X`
86    LogicalNegationOp(UnaryOp),
87    /// `$X`
88    LiftingOp(UnaryOp),
89
90
91    // Binary Operations :: Core
92
93    /// `X -> Y`
94    FunctionDefinitionOp(BinaryOp),
95    /// `X Y`: function application, written by juxtaposition.
96    ApplicationOp(BinaryOp),
97    /// `X , Y`
98    PairingOp(BinaryOp),
99    /// `X => Y`
100    MappingOp(BinaryOp),
101    /// `X = Y`
102    AssignmentOp(BinaryOp),
103    /// `X : Y`
104    LabellingOp(BinaryOp),
105    /// `X . Y`
106    SubcontextingOp(BinaryOp),
107    /// `X ~> Y`
108    ThenOp(BinaryOp),
109
110
111    // Binary Operations :: Arithmetic
112
113    /// `X ^ Y`
114    PowerOp(BinaryOp),
115    /// `X * Y`
116    ProductOp(BinaryOp),
117    /// `X / Y`
118    DivisionOp(BinaryOp),
119    /// `X % Y`
120    ModuloOp(BinaryOp),
121    /// `X + Y`
122    SumOp(BinaryOp),
123    /// `X - Y`
124    SubtractionOp(BinaryOp),
125
126
127    // Binary Operations :: Comparison
128
129    /// `X == Y`
130    EqualToOp(BinaryOp),
131    /// `X != Y`
132    NotEqualToOp(BinaryOp),
133    /// `X < Y`
134    LessThanOp(BinaryOp),
135    /// `X <= Y`
136    LessThanOrEqualToOp(BinaryOp),
137    /// `X > Y`
138    GreaterThanOp(BinaryOp),
139    /// `X >= Y`
140    GreaterThanOrEqualToOp(BinaryOp),
141
142
143    // Binary Operations :: Logic
144
145    /// `X & Y`
146    AndOp(BinaryOp),
147    /// `X | Y`
148    OrOp(BinaryOp),
149
150
151    // Binary Operations :: Conditional
152
153    /// `X ? Y`
154    ConditionalOp(BinaryOp),
155    /// `X ; Y`
156    AlternativeOp(BinaryOp),
157
158
159    // Binary Operations :: Function Composition
160
161    /// `X << Y`
162    CompositionOp(BinaryOp),
163    /// `X >> Y`
164    ReverseCompositionOp(BinaryOp),
165}
166
167
168impl Node {
169
170    /// Returns the source byte offset recorded in this node.
171    pub fn position (&self) -> usize {
172        match self {
173
174            Self::Identifier(leaf)      => leaf.pos,
175            Self::Numb(leaf)            => leaf.pos,
176            Self::Text(leaf)            => leaf.pos,
177            Self::Nothing(leaf)         => leaf.pos,
178            Self::Unclosed(leaf)        => leaf.pos,
179            Self::UnexpectedToken(leaf) => leaf.pos,
180
181            Self::List(unary)      => unary.pos,
182            Self::Namespace(unary) => unary.pos,
183
184            Self::AffirmOp(unary)          => unary.pos,
185            Self::NegateOp(unary)          => unary.pos,
186            Self::LogicalNegationOp(unary) => unary.pos,
187            Self::LiftingOp(unary)         => unary.pos,
188
189            Self::FunctionDefinitionOp(binary) => binary.pos,
190            Self::ApplicationOp(binary)        => binary.pos,
191            Self::PairingOp(binary)            => binary.pos,
192            Self::MappingOp(binary)            => binary.pos,
193            Self::AssignmentOp(binary)         => binary.pos,
194            Self::LabellingOp(binary)          => binary.pos,
195            Self::SubcontextingOp(binary)      => binary.pos,
196            Self::ThenOp(binary)               => binary.pos,
197
198            Self::PowerOp(binary)       => binary.pos,
199            Self::ProductOp(binary)     => binary.pos,
200            Self::DivisionOp(binary)    => binary.pos,
201            Self::ModuloOp(binary)      => binary.pos,
202            Self::SumOp(binary)         => binary.pos,
203            Self::SubtractionOp(binary) => binary.pos,
204
205            Self::EqualToOp(binary)              => binary.pos,
206            Self::NotEqualToOp(binary)           => binary.pos,
207            Self::LessThanOp(binary)             => binary.pos,
208            Self::LessThanOrEqualToOp(binary)    => binary.pos,
209            Self::GreaterThanOp(binary)          => binary.pos,
210            Self::GreaterThanOrEqualToOp(binary) => binary.pos,
211
212            Self::AndOp(binary) => binary.pos,
213            Self::OrOp(binary)  => binary.pos,
214
215            Self::ConditionalOp(binary) => binary.pos,
216            Self::AlternativeOp(binary) => binary.pos,
217
218            Self::CompositionOp(binary)        => binary.pos,
219            Self::ReverseCompositionOp(binary) => binary.pos,
220        }
221    }
222
223}