Skip to main content

kasm/preprocessor/
past.rs

1use std::num::NonZeroU8;
2
3use crate::errors::Span;
4use crate::lexer::Token;
5
6/// PAST stands for Preprocessor Abstract Syntax Tree
7///
8/// Basically, in KASM the preprocessor is treated as a tiny programming language, and is first
9/// parsed, then "generated" which means that it generates the rest of the code that will be used
10/// in KASM's subsequent operation.
11///
12
13#[derive(Debug, Clone)]
14pub enum PASTNode {
15    BenignTokens(BenignTokens),
16    SLMacroDef(SLMacroDef),
17    MacroInvok(MacroInvok),
18    MLMacroDef(MLMacroDef),
19    SLMacroUndef(SLMacroUndef),
20    MLMacroUndef(MLMacroUndef),
21    Repeat(Repeat),
22    IfStatement(IfStatement),
23    Include(Include),
24}
25
26impl PASTNode {
27    pub fn span_end(&self) -> usize {
28        match self {
29            PASTNode::BenignTokens(benign_tokens) => benign_tokens.span.end,
30            PASTNode::SLMacroDef(sl_macro_def) => sl_macro_def.span.end,
31            PASTNode::MacroInvok(macro_invok) => macro_invok.span.end,
32            PASTNode::MLMacroDef(ml_macro_def) => ml_macro_def.span.end,
33            PASTNode::SLMacroUndef(sl_macro_undef) => sl_macro_undef.span.end,
34            PASTNode::MLMacroUndef(ml_macro_undef) => ml_macro_undef.span.end,
35            PASTNode::Repeat(repeat) => repeat.span.end,
36            PASTNode::IfStatement(if_statement) => if_statement.span.end,
37            PASTNode::Include(include) => include.span.end,
38        }
39    }
40}
41
42#[derive(Debug, Copy, Clone)]
43pub struct Ident {
44    pub span: Span,
45    pub hash: u64,
46}
47
48impl Ident {
49    pub fn new(span: Span, hash: u64) -> Self {
50        Self { span, hash }
51    }
52}
53
54impl PartialEq for Ident {
55    fn eq(&self, other: &Self) -> bool {
56        self.hash == other.hash
57    }
58}
59
60#[derive(Debug, Clone)]
61pub struct BenignTokens {
62    pub span: Span,
63    pub tokens: Vec<Token>,
64}
65
66impl BenignTokens {
67    /// Creates a new BenignTokens struct using the tokens provided
68    ///
69    /// The vector MUST NOT BE EMPTY. If it is, this function will panic
70    ///
71    pub fn from_vec(tokens: Vec<Token>) -> Self {
72        let mut span = Span::new(0, 0, 0);
73
74        let first_span = tokens.first().unwrap().as_span();
75        let last_span = tokens.last().unwrap().as_span();
76
77        span.file = first_span.file;
78        span.start = first_span.start;
79        span.end = last_span.end;
80
81        Self { span, tokens }
82    }
83}
84
85/// A PAST Node representing a single line macro definition
86///
87/// Grammar:
88///
89/// ```sh,ignore,no_run
90/// <SLMacroDef> ::= .define <identifier>
91///              |   .define <identifier> <SLMacroDefContents>
92///              |   .define <identifier> <SLMacroDefArgs>
93///              |   .define <identifier> <SLMacroDefArgs> <SLMacroDefContents>
94/// ```
95///
96#[derive(Debug, Clone)]
97pub struct SLMacroDef {
98    pub span: Span,
99    pub identifier: Ident,
100    pub args: Option<SLMacroDefArgs>,
101    pub contents: Option<SLMacroDefContents>,
102}
103
104impl SLMacroDef {
105    pub fn new(
106        span: Span,
107        identifier: Ident,
108        args: Option<SLMacroDefArgs>,
109        contents: Option<SLMacroDefContents>,
110    ) -> Self {
111        SLMacroDef {
112            span,
113            identifier,
114            args,
115            contents,
116        }
117    }
118}
119
120/// A PAST Node representing a single line macro definition's arguments
121///
122/// Grammar:
123///
124/// ```sh,ignore,no_run
125/// <SLMacroDefArgs> ::= ()
126///                  |   (<arguments>)
127///
128/// <arguments> ::= <identifier> | <identifier>, <arguments>
129/// ```
130///
131#[derive(Debug, Clone)]
132pub struct SLMacroDefArgs {
133    pub span: Span,
134    pub args: Vec<Ident>,
135}
136
137impl SLMacroDefArgs {
138    pub fn new(span: Span, args: Vec<Ident>) -> Self {
139        Self { span, args }
140    }
141}
142
143/// A PAST Node representing a single line macro definition's contents
144///
145/// This grammar may be incomplete, however it is meant to convey that this can contain anything
146/// except any preprocessor directives.
147///
148/// Grammar:
149///
150/// ```sh,ignore,no_run
151/// <SLMacroDefContents> ::=
152///                      |   <identifier> <SLMacroDefContents>
153///                      |   <literal> <SLMacroDefContents>
154///                      |   <non-definition directive> <SLMacroDefContents>
155///                      |   <operator> <SLMacroDefContents>
156///                      |   <keyword> <SLMacroDefContents>
157/// ```
158///
159#[derive(Debug, Clone)]
160pub struct SLMacroDefContents {
161    pub span: Span,
162    pub contents: Vec<PASTNode>,
163}
164
165impl SLMacroDefContents {
166    pub fn new(span: Span, contents: Vec<PASTNode>) -> Self {
167        Self { span, contents }
168    }
169}
170
171#[derive(Debug, Clone)]
172pub struct MacroInvok {
173    pub span: Span,
174    pub identifier: Ident,
175    pub args: Option<MacroInvokArgs>,
176}
177
178impl MacroInvok {
179    pub fn new(span: Span, identifier: Ident, args: Option<MacroInvokArgs>) -> Self {
180        Self {
181            span,
182            identifier,
183            args,
184        }
185    }
186}
187
188#[derive(Debug, Clone)]
189pub struct MacroInvokArgs {
190    pub span: Span,
191    pub args: Vec<MacroInvokArg>,
192}
193
194impl MacroInvokArgs {
195    pub fn new(span: Span, args: Vec<MacroInvokArg>) -> Self {
196        Self { span, args }
197    }
198
199    pub fn from_vec(args: Vec<MacroInvokArg>) -> Self {
200        let mut span = Span::new(0, 0, 0);
201
202        let first_span = args.first().unwrap().span;
203        let last_span = args.last().unwrap().span;
204
205        span.start = first_span.start;
206        span.file = first_span.file;
207        span.end = last_span.end;
208
209        MacroInvokArgs { span, args }
210    }
211}
212
213#[derive(Debug, Clone)]
214pub struct MacroInvokArg {
215    pub span: Span,
216    pub contents: Vec<PASTNode>,
217}
218
219impl MacroInvokArg {
220    pub fn new(span: Span, contents: Vec<PASTNode>) -> Self {
221        Self { span, contents }
222    }
223}
224
225#[derive(Debug, Clone)]
226pub struct MLMacroDef {
227    pub span: Span,
228    pub identifier: Ident,
229    pub args: Option<MLMacroArgs>,
230    pub defaults: Option<MLMacroDefDefaults>,
231    pub contents: Vec<PASTNode>,
232}
233
234impl MLMacroDef {
235    pub fn new(
236        span: Span,
237        identifier: Ident,
238        args: Option<MLMacroArgs>,
239        defaults: Option<MLMacroDefDefaults>,
240        contents: Vec<PASTNode>,
241    ) -> Self {
242        Self {
243            span,
244            identifier,
245            args,
246            defaults,
247            contents,
248        }
249    }
250}
251
252#[derive(Debug, Clone)]
253pub struct MLMacroArgs {
254    pub span: Span,
255    pub required: u8,
256    pub maximum: Option<NonZeroU8>,
257}
258
259impl MLMacroArgs {
260    pub fn new(span: Span, required: u8, maximum: Option<NonZeroU8>) -> Self {
261        Self {
262            span,
263            required,
264            maximum,
265        }
266    }
267}
268
269#[derive(Debug, Clone)]
270pub struct MLMacroDefDefaults {
271    pub span: Span,
272    pub values: Vec<BenignTokens>,
273}
274
275impl MLMacroDefDefaults {
276    pub fn new(span: Span, values: Vec<BenignTokens>) -> Self {
277        Self { span, values }
278    }
279
280    pub fn from_vec(values: Vec<BenignTokens>) -> Self {
281        let mut span = Span::new(0, 0, 0);
282
283        let first_span = values.first().unwrap().span;
284        let last_span = values.last().unwrap().span;
285
286        span.start = first_span.start;
287        span.file = first_span.file;
288        span.end = last_span.end;
289
290        MLMacroDefDefaults { span, values }
291    }
292}
293
294/// A PAST Node that represents a single line macro undefinition
295///
296/// Grammar:
297///
298/// ```sh,ignore,no_run
299/// <SLMacroUndef> ::= .undef <ident>
300///                |   .undef <ident> <SLMacroUndefArgs>
301/// ```
302///
303#[derive(Debug, Clone)]
304pub struct SLMacroUndef {
305    pub span: Span,
306    pub identifier: Ident,
307    pub args: SLMacroUndefArgs,
308}
309
310impl SLMacroUndef {
311    pub fn new(span: Span, identifier: Ident, args: SLMacroUndefArgs) -> Self {
312        Self {
313            span,
314            identifier,
315            args,
316        }
317    }
318}
319
320/// Represents a single line macro's number of arguments
321///
322/// ```sh,ignore,no_run
323/// <SLMacroUndefArgs> ::= <number>
324/// ```
325///
326#[derive(Debug, Clone)]
327pub struct SLMacroUndefArgs {
328    pub span: Span,
329    pub num: u8,
330}
331
332impl SLMacroUndefArgs {
333    pub fn new(span: Span, num: u8) -> Self {
334        Self { span, num }
335    }
336}
337
338/// A PAST Node that represents a multi line macro undefinition
339///
340/// Grammar:
341///
342/// ```sh,ignore,no_run
343/// <MLMacroUndef> ::= .unmacro <ident>
344///                |   .unmacro <ident> <MLMacroArgs>
345/// ```
346///
347#[derive(Debug, Clone)]
348pub struct MLMacroUndef {
349    pub span: Span,
350    pub identifier: Ident,
351    pub args: MLMacroArgs,
352}
353
354impl MLMacroUndef {
355    pub fn new(span: Span, identifier: Ident, args: MLMacroArgs) -> Self {
356        Self {
357            span,
358            identifier,
359            args,
360        }
361    }
362}
363
364/// A PAST node that represents a repeat directive
365///
366/// Grammar:
367///
368/// ```sh,ignore,no_run
369/// <Repeat> ::= .rep <RepeatNumber>
370/// ```
371///
372#[derive(Debug, Clone)]
373pub struct Repeat {
374    pub span: Span,
375    pub number: RepeatNumber,
376    pub contents: Vec<PASTNode>,
377}
378
379impl Repeat {
380    pub fn new(span: Span, number: RepeatNumber, contents: Vec<PASTNode>) -> Self {
381        Self {
382            span,
383            number,
384            contents,
385        }
386    }
387}
388
389/// A PAST node that represents a repeat directive's number of repetitions
390///
391/// Grammar:
392///
393/// ```sh,ignore,no_run
394/// <RepeatNumber> ::= <BenignTokens> | <MacroInvok>
395/// ```
396///
397#[derive(Debug, Clone)]
398pub struct RepeatNumber {
399    pub span: Span,
400    pub expression: Vec<PASTNode>,
401}
402
403impl RepeatNumber {
404    pub fn new(span: Span, expression: Vec<PASTNode>) -> Self {
405        Self { span, expression }
406    }
407}
408
409#[derive(Debug, Clone)]
410pub struct IfStatement {
411    pub span: Span,
412    pub clauses: Vec<IfClause>,
413}
414
415impl IfStatement {
416    pub fn new(span: Span, clauses: Vec<IfClause>) -> Self {
417        Self { span, clauses }
418    }
419
420    pub fn from_vec(clauses: Vec<IfClause>) -> Self {
421        let mut span = Span::new(0, 0, 0);
422
423        let first_span = clauses.first().unwrap().span;
424        let last_span = clauses.last().unwrap().span;
425
426        span.start = first_span.start;
427        span.file = first_span.file;
428        span.end = last_span.end;
429
430        Self { span, clauses }
431    }
432}
433
434#[derive(Debug, Clone)]
435pub struct IfClause {
436    pub span: Span,
437    pub begin: IfClauseBegin,
438    pub condition: IfCondition,
439    pub contents: Vec<PASTNode>,
440}
441
442impl IfClause {
443    pub fn new(
444        span: Span,
445        begin: IfClauseBegin,
446        condition: IfCondition,
447        contents: Vec<PASTNode>,
448    ) -> Self {
449        Self {
450            span,
451            begin,
452            condition,
453            contents,
454        }
455    }
456}
457
458/// This represents a single part like .if or .ifn
459#[derive(Debug, Clone)]
460pub struct IfClauseBegin {
461    pub span: Span,
462    pub inverse: bool,
463}
464
465impl IfClauseBegin {
466    pub fn new(span: Span, inverse: bool) -> Self {
467        Self { span, inverse }
468    }
469}
470
471#[derive(Debug, Clone)]
472pub enum IfCondition {
473    Exp(IfExpCondition),
474    Def(IfDefCondition),
475    Else,
476}
477
478#[derive(Debug, Clone)]
479pub struct IfDefCondition {
480    pub span: Span,
481    pub identifier: Ident,
482    pub args: Option<MLMacroArgs>,
483}
484
485impl IfDefCondition {
486    pub fn new(span: Span, identifier: Ident, args: Option<MLMacroArgs>) -> Self {
487        Self {
488            span,
489            identifier,
490            args,
491        }
492    }
493}
494
495#[derive(Debug, Clone)]
496pub struct IfExpCondition {
497    pub span: Span,
498    pub expression: Vec<PASTNode>,
499}
500
501impl IfExpCondition {
502    pub fn new(span: Span, expression: Vec<PASTNode>) -> Self {
503        Self { span, expression }
504    }
505}
506
507#[derive(Debug, Clone)]
508pub struct Include {
509    pub span: Span,
510    pub path: IncludePath,
511}
512
513impl Include {
514    pub fn new(span: Span, path: IncludePath) -> Self {
515        Self { span, path }
516    }
517}
518
519#[derive(Debug, Clone)]
520pub struct IncludePath {
521    pub span: Span,
522    pub expression: Vec<PASTNode>,
523}
524
525impl IncludePath {
526    pub fn new(span: Span, expression: Vec<PASTNode>) -> Self {
527        Self { span, expression }
528    }
529}