Skip to main content

m2_syn/schema/
nodes.rs

1crate::syntax! {
2// P = precedence, B = binary binding strength, U = unary binding strength.
3// `L` and `R` derive B from P. Columns absent for a role are omitted, and
4// spellings with identical metadata share one row.
5tokens {
6    // Operators                          roles                 (P, B, U)
7    [->] [<-] [=] [=>]                   { infix }              (14, R)
8    [>>]                                 { bin, aug }           (14, R)
9    [<<]                                 { bin, pref, aug }     (18, L)
10    [|-]                                 { bin, pref, aug }     (20, L)
11    [===>]                               { bin, aug }           (22, R)
12    [<===]                               { bin, pref }          (22, R)
13    [<==>]                               { bin, aug }           (24, R)
14    [==>]                                { bin, aug }           (26, R)
15    [<==]                                { bin, pref }          (26, R)
16    [or]                                 { bin }                (28, R)
17    [??]                                 { bin, pref, aug }     (28, R)
18    [xor]                                { bin }                (30, R)
19    [and]                                { bin }                (32, R)
20    [not]                                { pref }               (34)
21    [!=] [=!=] [==] [===]                { bin }                (36, R)
22    [<] [<=] [>] [>=] [?]                { bin, pref }          (36, R)
23    [~]                                  { bin, pref, aug }     (36, R)
24    [||]                                 { bin, aug }           (38, L)
25    [:]                                  { bin, aug }           (40, R)
26    [|]                                  { bin, aug }           (42, L)
27    [^^]                                 { bin, aug }           (44, L)
28    [&]                                  { bin, aug }           (46, L)
29    [..] [..<]                           { bin, aug }           (48, L)
30    [++]                                 { bin, aug }           (50, L)
31    [+] [-]                              { bin, pref, aug }     (50, L)
32    ["·"]                                { bin, aug }           (52, L)
33    [**] ["⊠"] ["⧢"]                     { bin, aug }           (54, L)
34    [%] [/] [/ /]                        { bin, aug }           (58, L)
35    [*]                                  { bin, pref, aug }     (58, L)
36    ["\\"] ["\\\\"]                      { bin, aug }           (58, R)
37    [@]                                  { bin, aug }           (60, R)
38    [(*)]                                { post }               (64)
39    [@@] [@@?]                           { bin, aug }           (66, L)
40    [^*] [^~] [_*] [_~]                  { post }               (68)
41    [#?] [.] [.?]                        { bin }                (70, L)
42    [^<] [^<=] [^>] [^>=]                { bin }                (70, L)
43    [_<] [_<=] [_>] [_>=]                { bin }                (70, L)
44    [^] [^**] [_] [|_]                   { bin, aug }           (70, L)
45    [#]                                  { bin, pref }          (70, L, 61)
46    [!] [^!] [_!]                        { post }               (72)
47
48    // Keywords
49    [else] [then] [do] [list] [except]                          (12)
50    [when] [of] [in] [from] [to]                                (16)
51    [break] [continue] [return]
52    [catch] [throw] [trap]
53    [if] [while] [try]
54    [TEST] [time] [timing]
55    [elapsedTime] [elapsedTiming]
56    [breakpoint] [profile] [shield]
57    [step] [finish]                                             (62, 12)
58    [for] [new]                                                 (62, 16)
59    [symbol] [global] [local] [threadLocal] [threadVariable]    (62, 74)
60
61    // Separators
62    [;]                                                         (8)
63    [,]                                                         (10)
64}
65
66// Leaves retain their source text. Canonical names select the specialized
67// storage and parsing behavior supplied by the schema macro.
68strutuct! { Symbol }
69strutuct! { Empty }
70strutuct! { Adj }
71strutuct! { EOC }
72strutuct! { BOF }
73strutuct! { EOF }
74strutuct! { EscapeSequence }
75strutuct! { FloatLiteral }
76strutuct! { IntegerLiteral }
77strutuct! { RawStringContent }
78strutuct! { StringContent }
79
80// `Lines<T>` is stored as `Vec<T>` and printed one element per line.
81#[comments]
82#[cell_stream]
83strutuct!{ SourceFile
84    bof: BOF,
85    cells: Lines<Cell>,
86    eof: EOF,
87}
88
89#[comments]
90strutuct!{ Cell
91    content: PackedContent,
92    semicolon: Token![;]?,
93    eoc: EOC,
94}
95
96strutuct!{ Component
97    Expr(Expr*)
98    Empty(Empty)
99}
100
101strutuct!{ ExprPack
102    pack: Punctuated<Component>,
103}
104
105strutuct!{ PackedContent
106    Expr(Expr*)
107    Pack(ExprPack)
108}
109
110strutuct!{ Statement
111    content: PackedContent,
112    semicolon: Token![;],
113}
114
115#[delimiter(bracket)]
116strutuct!{ Array
117    statements: Vec<Statement>,
118    elements: PackedContent?,
119}
120
121#[delimiter(brace)]
122strutuct!{ List
123    statements: Vec<Statement>,
124    elements: PackedContent?,
125}
126
127#[delimiter(angle_bar)]
128strutuct!{ AngleBarList
129    statements: Vec<Statement>,
130    elements: PackedContent?,
131}
132
133#[delimiter(parenthesis)]
134strutuct!{ Sequence
135    statements: Vec<Statement>,
136    elements: PackedContent?,
137}
138
139#[delimiter(parenthesis)]
140strutuct!{ Holder
141    muted: Vec<Statement>,
142    value: Expr*?,
143}
144
145strutuct!{ StringElement
146    Escape(EscapeSequence)
147    Content(StringContent)
148}
149
150#[literal(string)]
151strutuct!{ StringLiteral
152    elements: Vec<StringElement>,
153}
154
155strutuct!{ RawStringElement
156    Escape(EscapeSequence)
157    Content(RawStringContent)
158}
159
160#[literal(raw_string)]
161strutuct!{ RawStringLiteral
162    elements: Vec<RawStringElement>,
163}
164
165strutuct!{ AssignmentArgument
166    List(AssignmentList*)
167    Empty(Empty)
168    Symbol(Symbol)
169    Op(ExprOp)
170    // `x <- y` as a target: M2 reads it as an installation target for `<-`.
171    Evaluated(ExprAssignEvaluated)
172}
173
174strutuct!{ AssignmentListContent
175    Argument(AssignmentArgument)
176    Pack {
177        arguments: Punctuated<AssignmentArgument>,
178    }
179}
180
181strutuct!{ AssignmentList
182    contents: Delimited<Option<AssignmentListContent>>,
183}
184
185strutuct!{ ArgumentListContent
186    Symbol(Symbol)
187    Pack {
188        arguments: Punctuated<Symbol>,
189    }
190}
191
192// These products are shared by otherwise independent expression families.
193strutuct!{ TypeAnnotation
194    typical_value: Expr*,
195    operator: Token![=>],
196}
197
198strutuct!{ ThenClause
199    then_token: Token![then],
200    expr: Expr*,
201}
202
203strutuct!{ ElseClause
204    else_token: Token![else],
205    expr: Expr*,
206}
207
208strutuct!{ RangeBoundFrom
209    from_token: Token![from],
210    value: Expr*,
211}
212
213strutuct!{ RangeBoundTo
214    to_token: Token![to],
215    value: Expr*,
216}
217
218strutuct!{ WhenCondition
219    when_token: Token![when],
220    condition: Expr*,
221}
222
223strutuct!{ ListStep
224    list_token: Token![list],
225    expr: Expr*,
226}
227
228strutuct!{ DoStep
229    do_token: Token![do],
230    statement: Expr*,
231}
232
233strutuct!{ LoopBody
234    list_step: ListStep?,
235    do_step: DoStep?,
236}
237
238strutuct!{ OfClass
239    of_token: Token![of],
240    parent: Expr*,
241}
242
243strutuct!{ FromInstance
244    from_token: Token![from],
245    instance: Expr*,
246}
247
248strutuct!{ TryFallback
249    Else(ElseClause)
250    Except {
251        except_token: Token![except],
252        exception: Symbol,
253        do_token: Token![do],
254        value: Expr*,
255    }
256}
257
258// Semantic alternatives are nested so every layer becomes a dispatch point.
259// The short layer names keep the generated cumulative type names readable.
260strutuct!{ Expr
261    Literal {
262        Float(FloatLiteral)
263        Integer(IntegerLiteral)
264        RawString(RawStringLiteral)
265        String(StringLiteral)
266    }
267
268    Collection {
269        Sequence(Sequence)
270        List(List)
271        Array(Array)
272        AngleBar(AngleBarList)
273    }
274    Holder(Holder)
275    Op {
276        Bin {
277            Adj {
278                left_operand: Expr*,
279                operator: Adj,
280                right_operand: Expr*,
281            }
282            Regular {
283                left_operand: Expr*,
284                operator: BinaryOperator,
285                right_operand: Expr*,
286            }
287            Member {
288                Dot {
289                    receiver: Expr*,
290                    operator: Token![.],
291                    member: Expr*,
292                }
293                Optional {
294                    receiver: Expr*,
295                    operator: Token![.?],
296                    member: Expr*,
297                }
298            }
299            Index {
300                receiver: Expr*,
301                operator: Token![#],
302                index: Expr*,
303            }
304        }
305        Prefix {
306            operator: PrefixOperator,
307            operand: Expr*,
308        }
309        Postfix {
310            operand: Expr*,
311            operator: PostfixOperator,
312        }
313    }
314    Assign {
315        Simple {
316            Global {
317                variable: Symbol,
318                operator: Token![=],
319                value: Expr*,
320            }
321            Local {
322                variable: Symbol,
323                operator: Token![:=],
324                value: Expr*,
325            }
326        }
327        Parallel {
328            Global {
329                argument_list: AssignmentList*,
330                operator: Token![=],
331                value: Expr*,
332            }
333            Local {
334                argument_list: AssignmentList*,
335                operator: Token![:=],
336                value: Expr*,
337            }
338        }
339        Evaluated {
340            evaluated_domain: Expr*,
341            operator: Token![<-],
342            value: Expr*,
343        }
344        Augmented {
345            target: Expr*,
346            operator: AugmentedOperator,
347            value: Expr*,
348        }
349        Install {
350            Method {
351                method: Expr*,
352                operator: Adj,
353                signature: Expr*,
354                assign_op: Token![:=],
355                typical_value: TypeAnnotation?,
356                function: Expr*,
357            }
358            Op {
359                domain_expr: ExprOp,
360                assign_op: Token![:=],
361                typical_value: TypeAnnotation?,
362                function: Expr*,
363            }
364            New {
365                new_statement: ExprNew,
366                operator: Token![:=],
367                function: Expr*,
368            }
369        }
370        Op {
371            argument_expr: ExprOp,
372            operator: Token![=],
373            value_expr: Expr*,
374        }
375    }
376    Option {
377        key: Expr*,
378        operator: Token![=>],
379        value: Expr*,
380    }
381    Lambda {
382        Variadic {
383            argument: Symbol,
384            operator: Token![->],
385            body: Expr*,
386        }
387        List {
388            arguments: Delimited<Option<ArgumentListContent>>,
389            operator: Token![->],
390            body: Expr*,
391        }
392    }
393    If {
394        if_token: Token![if],
395        condition: Expr*,
396        then_clause: ThenClause,
397        else_clause: ElseClause?,
398    }
399    For {
400        Bare {
401            for_token: Token![for],
402            variable: Symbol,
403            condition: WhenCondition?,
404            body: LoopBody,
405        }
406        Range {
407            for_token: Token![for],
408            variable: Symbol,
409            lower_bound: RangeBoundFrom?,
410            upper_bound: RangeBoundTo?,
411            condition: WhenCondition?,
412            body: LoopBody,
413        }
414        In {
415            for_token: Token![for],
416            variable: Symbol,
417            in_token: Token![in],
418            collection: Expr*,
419            condition: WhenCondition?,
420            body: LoopBody,
421        }
422    }
423    While {
424        while_token: Token![while],
425        condition: Expr*,
426        body: LoopBody,
427    }
428    Try {
429        try_token: Token![try],
430        value: Expr*,
431        on_success: ThenClause?,
432        fallback: TryFallback?,
433    }
434    Quote {
435        Symbol {
436            specifier: Token![symbol],
437            symbol: Symbol,
438        }
439        Local {
440            specifier: Token![local],
441            symbol: Symbol,
442        }
443        Global {
444            specifier: Token![global],
445            symbol: Symbol,
446        }
447        ThreadVariable {
448            specifier: Token![threadVariable],
449            symbol: Symbol,
450        }
451        ThreadLocal {
452            specifier: Token![threadLocal],
453            symbol: Symbol,
454        }
455    }
456    New {
457        new_token: Token![new],
458        class: Expr*,
459        parent_class: OfClass?,
460        instance: FromInstance?,
461    }
462    Control {
463        Break {
464            break_token: Token![break],
465            value: Expr*?,
466        }
467        Continue {
468            continue_token: Token![continue],
469            value: Expr*?,
470        }
471        Return {
472            return_token: Token![return],
473            value: Expr*?,
474        }
475    }
476    Catch {
477        catch_token: Token![catch],
478        value: Expr*,
479    }
480    Throw {
481        throw_token: Token![throw],
482        value: Expr*,
483    }
484    Trap {
485        trap_token: Token![trap],
486        value: Expr*,
487    }
488    Debug {
489        Test {
490            keyword: Token![TEST],
491            value: Expr*?,
492        }
493        Step {
494            keyword: Token![step],
495            value: Expr*?,
496        }
497        Finish {
498            keyword: Token![finish],
499            value: Expr*?,
500        }
501        Shield {
502            keyword: Token![shield],
503            value: Expr*?,
504        }
505        Breakpoint {
506            keyword: Token![breakpoint],
507            value: Expr*?,
508        }
509    }
510    Profile {
511        ElapsedTime {
512            modifier: Token![elapsedTime],
513            value: Expr*,
514        }
515        ElapsedTiming {
516            modifier: Token![elapsedTiming],
517            value: Expr*,
518        }
519        Profile {
520            modifier: Token![profile],
521            value: Expr*,
522        }
523        Time {
524            modifier: Token![time],
525            value: Expr*,
526        }
527        Timing {
528            modifier: Token![timing],
529            value: Expr*,
530        }
531    }
532    Symbol(Symbol)
533}
534}