canadensis_dsdl_parser/ast/
types.rs

1//! Abstract syntax tree types
2
3use num_rational::BigRational;
4use pest::Span;
5
6/// An expression and its associated span
7#[derive(Debug)]
8pub struct Expression<'i> {
9    /// The expression
10    pub expression: ExpressionType<'i>,
11    /// The span in the source that represents this expression
12    pub span: Span<'i>,
13}
14
15/// An expression
16#[derive(Debug)]
17pub enum ExpressionType<'i> {
18    /// An atom (single value)
19    Atom(Box<ExpressionAtom<'i>>),
20    /// `+expr`
21    UnaryPlus(Box<Expression<'i>>),
22    /// `-expr`
23    UnaryMinus(Box<Expression<'i>>),
24    /// `!expr`
25    UnaryNot(Box<Expression<'i>>),
26    /// `expr.ident`
27    Attribute(Box<Expression<'i>>, &'i str),
28    /// `expr ** expr`
29    Exponent(Box<Expression<'i>>, Box<Expression<'i>>),
30    /// `expr * expr`
31    Multiply(Box<Expression<'i>>, Box<Expression<'i>>),
32    /// `expr / expr`
33    Divide(Box<Expression<'i>>, Box<Expression<'i>>),
34    /// `expr % expr`
35    Modulo(Box<Expression<'i>>, Box<Expression<'i>>),
36    /// `expr + expr`
37    Add(Box<Expression<'i>>, Box<Expression<'i>>),
38    /// `expr - expr`
39    Subtract(Box<Expression<'i>>, Box<Expression<'i>>),
40    /// `expr | expr`
41    BitOr(Box<Expression<'i>>, Box<Expression<'i>>),
42    /// `expr ^ expr`
43    BitXor(Box<Expression<'i>>, Box<Expression<'i>>),
44    /// `expr & expr`
45    BitAnd(Box<Expression<'i>>, Box<Expression<'i>>),
46    /// `expr == expr`
47    Equal(Box<Expression<'i>>, Box<Expression<'i>>),
48    /// `expr != expr`
49    NotEqual(Box<Expression<'i>>, Box<Expression<'i>>),
50    /// `expr <= expr`
51    LessOrEqual(Box<Expression<'i>>, Box<Expression<'i>>),
52    /// `expr >= expr`
53    GreaterOrEqual(Box<Expression<'i>>, Box<Expression<'i>>),
54    /// `expr < expr`
55    Less(Box<Expression<'i>>, Box<Expression<'i>>),
56    /// `expr > expr`
57    Greater(Box<Expression<'i>>, Box<Expression<'i>>),
58    /// `expr || expr`
59    LogicalOr(Box<Expression<'i>>, Box<Expression<'i>>),
60    /// `expr && expr`
61    LogicalAnd(Box<Expression<'i>>, Box<Expression<'i>>),
62}
63
64/// An atom (single value in an expression)
65#[derive(Debug)]
66pub enum ExpressionAtom<'i> {
67    /// Expression in parentheses
68    Parenthesized(Expression<'i>),
69    /// Data type
70    Type(Type<'i>),
71    /// Literal value
72    Literal(Literal<'i>),
73    /// Identifier
74    Identifier(&'i str),
75}
76
77/// A literal value
78#[derive(Debug)]
79pub struct Literal<'i> {
80    /// The value
81    pub literal: LiteralType<'i>,
82    /// The span in the source that contains this literal
83    pub span: Span<'i>,
84}
85
86/// An identifier
87#[derive(Debug)]
88pub struct Identifier<'i> {
89    /// The name of the identifier
90    pub name: &'i str,
91    /// The span in the source where this identifier was found
92    pub span: Span<'i>,
93}
94
95/// A literal value
96#[derive(Debug)]
97pub enum LiteralType<'i> {
98    /// A set of expressions
99    Set(Vec<Expression<'i>>),
100    /// A number (integer or real)
101    Number(BigRational),
102    /// A string
103    String(String),
104    /// A boolean value
105    Boolean(bool),
106}
107
108/// A type
109#[derive(Debug)]
110pub enum Type<'i> {
111    /// A scalar type
112    Scalar(ScalarType<'i>),
113    /// An array type
114    Array(ArrayType<'i>),
115}
116
117/// Scalar types (single values)
118#[derive(Debug)]
119pub enum ScalarType<'i> {
120    /// A composite type with a name and version
121    Versioned(VersionedType<'i>),
122    /// A primitive type
123    Primitive(PrimitiveType),
124    /// A void type
125    Void { bits: u8 },
126}
127
128/// A primitive type
129#[derive(Debug)]
130pub enum PrimitiveType {
131    /// Boolean, always saturated
132    Boolean,
133    /// Character in a UTF-8 string (serialized like uint8)
134    Utf8,
135    /// Arbitrary 8-bit data (serialized like uint8)
136    Byte,
137    /// Signed integer, always saturated
138    Int { bits: u8 },
139    /// Unsigned integer
140    UInt { bits: u8, mode: CastMode },
141    /// 16-bit float
142    Float16 { mode: CastMode },
143    /// 32-bit float
144    Float32 { mode: CastMode },
145    /// 64-bit float
146    Float64 { mode: CastMode },
147}
148
149/// Cast modes for numeric values
150#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
151pub enum CastMode {
152    Truncated,
153    Saturated,
154}
155
156/// A composite type with a name and version
157#[derive(Debug)]
158pub struct VersionedType<'i> {
159    /// The path segments before the type name, if any
160    pub path: Vec<&'i str>,
161    /// The name of the type
162    pub name: &'i str,
163    /// The version of the type
164    pub version: TypeVersion,
165}
166
167/// The version of a versioned type
168#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
169pub struct TypeVersion {
170    // These can be 8 bits each: "Valid data type version numbers range from 0 to 255, inclusively"
171    pub major: u8,
172    pub minor: u8,
173}
174
175mod fmt_impl {
176    use super::TypeVersion;
177    use std::fmt::{Display, Formatter, Result};
178
179    impl Display for TypeVersion {
180        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
181            write!(f, "{}.{}", self.major, self.minor)
182        }
183    }
184}
185
186/// An array type, with an element type and length
187#[derive(Debug)]
188pub struct ArrayType<'i> {
189    /// The type of each array element
190    ///
191    /// This can't be an array or void type.
192    pub element: ScalarType<'i>,
193    /// The allowed range of array lengths
194    pub length: ArrayLength<'i>,
195}
196
197/// A range of allowed array lengths
198#[derive(Debug)]
199pub enum ArrayLength<'i> {
200    /// `type[expr]`
201    Fixed(Expression<'i>),
202    /// `type[<=expr]`
203    Inclusive(Expression<'i>),
204    /// `name[<expr]`
205    Exclusive(Expression<'i>),
206}
207
208/// A statement in a DSDL file
209#[derive(Debug)]
210pub enum Statement<'i> {
211    /// A directive, like `@assert`
212    Directive {
213        name: Identifier<'i>,
214        value: Option<Expression<'i>>,
215    },
216    /// A constant, like `uint8 THINGY = 9`
217    Constant {
218        ty: PrimitiveType,
219        name: Identifier<'i>,
220        value: Expression<'i>,
221    },
222    /// A field, like `uint16 value`
223    Field {
224        ty: Type<'i>,
225        name: Identifier<'i>,
226        span: Span<'i>,
227    },
228    /// A void padding field, like `void6`
229    PaddingField { bits: u8, span: Span<'i> },
230    /// The `---` marker that separates the request and response fields in a service type
231    ServiceResponseMarker(Span<'i>),
232    /// A comment, not including the # character or line terminator but including whitespace
233    Comment(Span<'i>),
234}
235
236/// The top-level abstract syntax tree of a DSDL file
237#[derive(Debug)]
238pub struct Definition<'i> {
239    /// The statements in the file
240    pub statements: Vec<Statement<'i>>,
241    /// A span representing the end of the file
242    pub eof_span: Span<'i>,
243}