1use std::fmt;
6
7use crate::ast::{DeclKind, Expr, Modifier, PatchItem, Point, Stmt};
8use crate::parser::{PResult, Parser};
9
10pub struct Word {
12 pub text: &'static str,
14 pub doc: &'static str,
16 pub reserved: bool,
19 pub roles: &'static [Role],
21}
22
23pub type Starts = Option<fn(&Parser) -> bool>;
25
26#[derive(Clone, Copy)]
28pub enum Role {
29 Decl {
31 starts: Starts,
32 parse: fn(&mut Parser) -> PResult<DeclKind>,
33 },
34 Stmt {
36 parse: fn(&mut Parser) -> PResult<Stmt>,
37 },
38 Prefix {
40 starts: Starts,
41 parse: fn(&mut Parser) -> PResult<Expr>,
42 },
43 Infix {
45 level: Level,
46 parse: fn(&mut Parser, Expr) -> PResult<Expr>,
47 },
48 Modifier(Modifier),
50 BuiltinType,
52 PatchItem {
54 parse: fn(&mut Parser) -> PResult<PatchItem>,
55 },
56 Point {
58 parse: fn(&mut Parser) -> PResult<Point>,
59 },
60 Part,
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
67pub enum Level {
68 Coalesce,
69 Or,
70 And,
71 Equality,
72 Compare,
73 Range,
74 Sum,
75 Product,
76 Switch,
77}
78
79impl Word {
80 pub fn role<T>(&self, pick: impl Fn(&Role) -> Option<T>) -> Option<T> {
82 self.roles.iter().find_map(pick)
83 }
84
85 pub fn is_type(&self) -> bool {
87 self.roles.iter().any(|r| matches!(r, Role::BuiltinType))
88 }
89}
90
91impl PartialEq for Word {
92 fn eq(&self, other: &Word) -> bool {
93 self.text == other.text
94 }
95}
96
97impl fmt::Debug for Word {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 write!(f, "`{}`", self.text)
100 }
101}
102
103pub fn reserved(text: &str) -> Option<&'static Word> {
105 ALL.iter().copied().find(|w| w.reserved && w.text == text)
106}
107
108pub fn named(text: &str) -> Option<&'static Word> {
110 ALL.iter().copied().find(|w| w.text == text)
111}
112
113macro_rules! words {
114 ($($file:ident $(= $path:literal)?),* $(,)?) => {
115 $($(#[path = $path])? pub mod $file;)*
116
117 pub static ALL: &[&Word] = &[$(&$file::WORD),*];
119 };
120}
121
122words! {
123 using, global, namespace, module = "words/mod_word.rs", r#macro, class, r#struct, record, interface, r#enum, unit,
125 component, system, extend, event, test, screen, command, patch, targets,
126 was, requires, every, has, r#where, when, get, set, init, mc, out,
128 public, private, internal, protected, r#static, r#const, readonly, r#async,
130 r#abstract, r#virtual, r#override, sealed, r#extern,
131 server, client, shared, saved, synced, tune,
132 void, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, decimal, bool, char, string, object,
134 dynamic,
135 r#let, r#mut, r#if, r#else, foreach, r#for, r#while, r#do, r#break, r#continue, r#return, skip,
137 new, this, base, r#ref, r#move, r#typeof, nameof, default, r#true, r#false, null, r#await, r#try, is, r#as, r#in, switch, and, or, not,
139 add, before, after, inside, replace, read, write, priority, uses, local,
141 around, at, call, constant, first, last,
142}