#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Kw {
Module,
Extends,
Constant,
Variable,
Let,
In,
If,
Then,
Else,
Choose,
Case,
Other,
Assume,
Theorem,
Instance,
With,
Local,
Recursive,
Lambda,
Proof,
Except,
True,
False,
Domain,
Subset,
Union,
Enabled,
Unchanged,
}
impl Kw {
pub fn text(self) -> Option<&'static str> {
Some(match self {
Self::Module => "MODULE",
Self::Extends => "EXTENDS",
Self::Constant => "CONSTANT",
Self::Variable => "VARIABLE",
Self::Let => "LET",
Self::In => "IN",
Self::If => "IF",
Self::Then => "THEN",
Self::Else => "ELSE",
Self::Choose => "CHOOSE",
Self::Case => "CASE",
Self::Other => "OTHER",
Self::Assume => "ASSUME",
Self::Theorem => "THEOREM",
Self::Instance => "INSTANCE",
Self::With => "WITH",
Self::Local => "LOCAL",
Self::Recursive => "RECURSIVE",
Self::Lambda => "LAMBDA",
Self::Except => "EXCEPT",
Self::True => "TRUE",
Self::False => "FALSE",
Self::Domain => "DOMAIN",
Self::Subset => "SUBSET",
Self::Union => "UNION",
Self::Enabled => "ENABLED",
Self::Unchanged => "UNCHANGED",
Self::Proof => return None,
})
}
pub fn lookup(word: &str) -> Option<Self> {
Some(match word {
"MODULE" => Self::Module,
"EXTENDS" => Self::Extends,
"CONSTANT" | "CONSTANTS" => Self::Constant,
"VARIABLE" | "VARIABLES" => Self::Variable,
"LET" => Self::Let,
"IN" => Self::In,
"IF" => Self::If,
"THEN" => Self::Then,
"ELSE" => Self::Else,
"CHOOSE" => Self::Choose,
"CASE" => Self::Case,
"OTHER" => Self::Other,
"ASSUME" | "ASSUMPTION" => Self::Assume,
"INSTANCE" => Self::Instance,
"WITH" => Self::With,
"LOCAL" => Self::Local,
"RECURSIVE" => Self::Recursive,
"LAMBDA" => Self::Lambda,
"THEOREM" | "LEMMA" | "COROLLARY" | "PROPOSITION" | "AXIOM" => Self::Theorem,
"PROOF" | "BY" | "OBVIOUS" | "OMITTED" | "QED" | "DEF" | "DEFS" | "DEFINE"
| "SUFFICES" | "PICK" | "WITNESS" | "HAVE" | "TAKE" | "USE" | "HIDE" | "PROVE"
| "NEW" | "ONLY" => Self::Proof,
"EXCEPT" => Self::Except,
"TRUE" => Self::True,
"FALSE" => Self::False,
"DOMAIN" => Self::Domain,
"SUBSET" => Self::Subset,
"UNION" => Self::Union,
"ENABLED" => Self::Enabled,
"UNCHANGED" => Self::Unchanged,
_ => return None,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Op {
Implies,
Equiv,
Or,
And,
Eq,
Neq,
Lt,
Gt,
Le,
Ge,
In,
NotIn,
Subseteq,
Supseteq,
AtAt,
OneTo,
Cup,
Cap,
SetMinus,
DotDot,
Plus,
Minus,
Times,
Div,
Mod,
Cartesian,
Concat,
Pow,
Not,
Always,
Eventually,
Forall,
Exists,
Domain,
Subset,
BigUnion,
Enabled,
Unchanged,
LeadsTo,
TemporalForall,
TemporalExists,
User(&'static str),
}
pub(crate) const USER_OPERATORS: &[(&str, u8)] = &[
("\\prec", 5),
("\\preceq", 5),
("\\succ", 5),
("\\succeq", 5),
("\\sqsubset", 5),
("\\sqsubseteq", 5),
("\\sqsupset", 5),
("\\sqsupseteq", 5),
("\\subset", 5),
("\\supset", 5),
("\\ll", 5),
("\\gg", 5),
("\\sim", 5),
("\\simeq", 5),
("\\approx", 5),
("\\asymp", 5),
("\\cong", 5),
("\\doteq", 5),
("\\propto", 5),
("\\cdot", 5),
("\\mod", 11),
("...", 9),
("--", 11),
("\\times", 11),
("|-", 5),
("-|", 5),
("|=", 5),
("=|", 5),
("::=", 5),
("<:", 7),
(":=", 5),
("\\sqcap", 9),
("\\sqcup", 9),
("\\uplus", 9),
("\\oplus", 10),
("\\ominus", 11),
("(+)", 10),
("(-)", 11),
("(.)", 13),
("(/)", 13),
("(\\X)", 13),
("\\odot", 13),
("\\oslash", 13),
("\\otimes", 13),
("\\star", 13),
("\\bullet", 13),
("\\bigcirc", 13),
("\\wr", 14),
("&", 13),
("&&", 13),
("|", 10),
("||", 10),
("$", 9),
("$$", 9),
("??", 9),
("%%", 11),
("##", 9),
("!!", 9),
("^^", 14),
("++", 10),
("**", 13),
("//", 13),
("/", 13),
("^+", 15),
("^*", 15),
("^#", 15),
("-+->", 2),
];
pub(crate) fn user_operator(symbol: &str) -> Option<Op> {
USER_OPERATORS
.iter()
.find(|(name, _)| *name == symbol)
.map(|(name, _)| Op::User(name))
}
impl Op {
pub fn infix_prec(self) -> Option<u8> {
Some(match self {
Self::Implies => 1,
Self::Equiv | Self::LeadsTo => 2,
Self::Or => 3,
Self::And => 4,
Self::Eq
| Self::Neq
| Self::Lt
| Self::Gt
| Self::Le
| Self::Ge
| Self::In
| Self::NotIn
| Self::Subseteq
| Self::Supseteq => 5,
Self::AtAt => 6,
Self::OneTo => 7,
Self::Cup | Self::Cap | Self::SetMinus => 8,
Self::DotDot => 9,
Self::Plus | Self::Minus => 10,
Self::Times | Self::Div | Self::Mod | Self::Cartesian => 11,
Self::Concat => 12,
Self::Pow => 13,
Self::User(_) if self.is_postfix() => return None,
Self::User(symbol) => {
return USER_OPERATORS
.iter()
.find(|(name, _)| *name == symbol)
.map(|(_, prec)| *prec);
}
_ => return None,
})
}
pub fn is_postfix(self) -> bool {
matches!(self, Self::User("^+" | "^*" | "^#"))
}
pub fn is_right_assoc(self) -> bool {
matches!(self, Self::Implies | Self::Pow)
}
pub fn symbol(self) -> &'static str {
match self {
Self::Implies => "=>",
Self::Equiv => "<=>",
Self::Or => "\\/",
Self::And => "/\\",
Self::Eq => "=",
Self::Neq => "#",
Self::Lt => "<",
Self::Gt => ">",
Self::Le => "<=",
Self::Ge => ">=",
Self::In => "\\in",
Self::NotIn => "\\notin",
Self::Subseteq => "\\subseteq",
Self::Supseteq => "\\supseteq",
Self::AtAt => "@@",
Self::OneTo => ":>",
Self::Cup => "\\cup",
Self::Cap => "\\cap",
Self::SetMinus => "\\",
Self::DotDot => "..",
Self::Plus => "+",
Self::Minus => "-",
Self::Times => "*",
Self::Div => "\\div",
Self::Mod => "%",
Self::Cartesian => "\\X",
Self::Concat => "\\o",
Self::Pow => "^",
Self::Not => "~",
Self::Always => "[]",
Self::Eventually => "<>",
Self::Forall => "\\A",
Self::Exists => "\\E",
Self::Domain => "DOMAIN",
Self::Subset => "SUBSET",
Self::BigUnion => "UNION",
Self::Enabled => "ENABLED",
Self::Unchanged => "UNCHANGED",
Self::LeadsTo => "~>",
Self::TemporalForall => "\\AA",
Self::TemporalExists => "\\EE",
Self::User(symbol) => symbol,
}
}
pub fn prefix_prec(self) -> u8 {
match self {
Self::Minus => 11,
Self::Domain | Self::Subset | Self::BigUnion => 9,
_ => 5,
}
}
pub fn is_word(self) -> bool {
matches!(
self,
Self::Domain | Self::Subset | Self::BigUnion | Self::Enabled | Self::Unchanged
)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Tok {
Ident(String),
Num(i64),
Decimal(String),
Str(String),
Kw(Kw),
Op(Op),
Fair {
strong: bool,
subscript: String,
},
ModuleEnd,
Separator,
DefEq,
LParen,
RParen,
LBrack,
RBrack,
LBrace,
RBrace,
LTup,
RTup,
Comma,
Colon,
ColonColon,
Dot,
Bang,
At,
Underscore,
Prime,
MapsTo,
Arrow,
Gets,
Eof,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Token {
pub tok: Tok,
pub line: u32,
pub col: u32,
}