#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Span {
pub offset: usize,
pub line: u32,
pub column: usize,
pub len: usize,
}
impl Span {
pub fn dummy() -> Self {
Self {
offset: 0,
line: 1,
column: 1,
len: 0,
}
}
pub fn to_lsp_range(&self) -> (u32, u32, u32, u32) {
let start_line = self.line.saturating_sub(1);
let start_char = self.column.saturating_sub(1);
let end_char = start_char.saturating_add(self.len);
(start_line, start_char as u32, start_line, end_char as u32)
}
}
#[cfg(test)]
mod tests {
use super::Span;
#[test]
fn span_dummy() {
let s = Span::dummy();
assert_eq!(s.offset, 0);
assert_eq!(s.line, 1);
assert_eq!(s.column, 1);
assert_eq!(s.len, 0);
}
}
#[derive(Debug, Clone)]
pub struct Node<T> {
pub span: Span,
pub value: T,
}
impl<T: PartialEq> PartialEq for Node<T> {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl<T: Eq> Eq for Node<T> {}
impl<T> Node<T> {
pub fn new(span: Span, value: T) -> Self {
Self { span, value }
}
}
impl<T> std::ops::Deref for Node<T> {
type Target = T;
fn deref(&self) -> &T {
&self.value
}
}
pub trait AstNode {
fn span(&self) -> Span;
}
impl<T> AstNode for Node<T> {
fn span(&self) -> Span {
self.span.clone()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BinaryOperator {
Eq,
Ne,
StrictEq,
StrictNe,
Lt,
Le,
Gt,
Ge,
Add,
Sub,
Mul,
Div,
Mod,
Exp,
Pow,
And,
Or,
Xor,
Implies,
Range,
BitOr,
BitAnd,
Other(String),
}
impl BinaryOperator {
pub fn from_token(token: &str) -> Self {
match token {
"==" => Self::Eq,
"!=" => Self::Ne,
"===" => Self::StrictEq,
"!==" => Self::StrictNe,
"<" => Self::Lt,
"<=" => Self::Le,
">" => Self::Gt,
">=" => Self::Ge,
"+" => Self::Add,
"-" => Self::Sub,
"*" => Self::Mul,
"/" => Self::Div,
"%" => Self::Mod,
"^" => Self::Pow,
"**" => Self::Exp,
"&&" | "and" => Self::And,
"||" | "or" => Self::Or,
"xor" => Self::Xor,
"implies" => Self::Implies,
".." => Self::Range,
"|" => Self::BitOr,
"&" => Self::BitAnd,
other => Self::Other(other.to_string()),
}
}
pub fn as_str(&self) -> &str {
match self {
Self::Eq => "==",
Self::Ne => "!=",
Self::StrictEq => "===",
Self::StrictNe => "!==",
Self::Lt => "<",
Self::Le => "<=",
Self::Gt => ">",
Self::Ge => ">=",
Self::Add => "+",
Self::Sub => "-",
Self::Mul => "*",
Self::Div => "/",
Self::Mod => "%",
Self::Pow => "^",
Self::Exp => "**",
Self::And => "&&",
Self::Or => "||",
Self::Xor => "xor",
Self::Implies => "implies",
Self::Range => "..",
Self::BitOr => "|",
Self::BitAnd => "&",
Self::Other(s) => s.as_str(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum UnaryOperator {
Plus,
Minus,
Not,
BitNot,
Other(String),
}
impl UnaryOperator {
pub fn from_token(token: &str) -> Self {
match token {
"+" => Self::Plus,
"-" => Self::Minus,
"not" => Self::Not,
"~" => Self::BitNot,
other => Self::Other(other.to_string()),
}
}
pub fn as_str(&self) -> &str {
match self {
Self::Plus => "+",
Self::Minus => "-",
Self::Not => "not",
Self::BitNot => "~",
Self::Other(s) => s.as_str(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Expression {
LiteralInteger(i64),
LiteralReal(String),
LiteralString(String),
LiteralBoolean(bool),
FeatureRef(String),
MemberAccess(Box<Node<Expression>>, String),
Index {
base: Box<Node<Expression>>,
index: Box<Node<Expression>>,
},
Bracket(Box<Node<Expression>>),
LiteralWithUnit {
value: Box<Node<Expression>>,
unit: Box<Node<Expression>>,
},
BinaryOp {
op: BinaryOperator,
left: Box<Node<Expression>>,
right: Box<Node<Expression>>,
},
UnaryOp {
op: UnaryOperator,
operand: Box<Node<Expression>>,
},
Invocation {
callee: Box<Node<Expression>>,
args: Vec<Node<Expression>>,
},
Tuple(Vec<Node<Expression>>),
Null,
}