use std::fmt;
use crate::ast::{DeclKind, Expr, Modifier, PatchItem, Point, Stmt};
use crate::parser::{PResult, Parser};
pub struct Word {
pub text: &'static str,
pub doc: &'static str,
pub reserved: bool,
pub roles: &'static [Role],
}
pub type Starts = Option<fn(&Parser) -> bool>;
#[derive(Clone, Copy)]
pub enum Role {
Decl {
starts: Starts,
parse: fn(&mut Parser) -> PResult<DeclKind>,
},
Stmt {
parse: fn(&mut Parser) -> PResult<Stmt>,
},
Prefix {
starts: Starts,
parse: fn(&mut Parser) -> PResult<Expr>,
},
Infix {
level: Level,
parse: fn(&mut Parser, Expr, bool) -> PResult<Expr>,
negatable: bool,
},
Modifier(Modifier),
PatchItem {
parse: fn(&mut Parser) -> PResult<PatchItem>,
},
Point {
parse: fn(&mut Parser) -> PResult<Point>,
},
Part,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Level {
Coalesce,
Or,
And,
Compare,
Range,
Sum,
Product,
Convert,
}
impl Word {
pub fn role<T>(&self, pick: impl Fn(&Role) -> Option<T>) -> Option<T> {
self.roles.iter().find_map(pick)
}
}
impl PartialEq for Word {
fn eq(&self, other: &Word) -> bool {
self.text == other.text
}
}
impl fmt::Debug for Word {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "`{}`", self.text)
}
}
pub fn reserved(text: &str) -> Option<&'static Word> {
ALL.iter().copied().find(|w| w.reserved && w.text == text)
}
pub fn named(text: &str) -> Option<&'static Word> {
ALL.iter().copied().find(|w| w.text == text)
}
macro_rules! words {
($($file:ident $(= $path:literal)?),* $(,)?) => {
$($(#[path = $path])? pub(crate) mod $file;)*
pub static ALL: &[&Word] = &[$(&$file::WORD),*];
};
}
words! {
r#use, module = "words/mod_word.rs", r#fn, r#let, r#var, val, r#const, r#type, unit, record, union, r#enum,
extend, on, test, native, version, recipe, screen, command, state, action, slots,
patch,
was, requires, ui, of, mc,
server, client, shared, saved, synced, tune, r#pub,
r#for, r#while, r#loop, r#break, r#continue, r#return, skip,
r#if, r#else, r#match, r#try, r#true, r#false, none, this = "words/self_word.rs", it, not, and, or, is, r#as, r#in,
add, before, after, inside, replace, read, write, priority, uses, local,
around, at, call, new, constant, first, last, r#where,
}