use crate::ast;
use crate::ast::Span;
use std::num::ParseIntError;
#[derive(Debug, PartialEq)]
pub struct BinaryOperator {
pub span: Span,
pub operation: BinaryOperatorType,
}
#[derive(Debug, PartialEq, Clone)]
#[allow(missing_docs)]
pub enum BinaryOperatorType {
Add,
Subtract,
Multiply,
Divide,
Union,
Intersect,
PowerXor,
GreaterThan,
LessThan,
GreaterEqual,
LessEqual,
Equal,
Near,
NotEqual,
And,
Or,
Xor,
}
impl BinaryOperatorType {
pub fn as_str(&self) -> &'static str {
match self {
Self::Add => "+",
Self::Subtract => "-",
Self::Multiply => "*",
Self::Divide => "/",
Self::Union => "|",
Self::Intersect => "&",
Self::PowerXor => "^",
Self::GreaterThan => ">",
Self::LessThan => "<",
Self::GreaterEqual => "≥",
Self::LessEqual => "≤",
Self::Equal => "==",
Self::Near => "~",
Self::NotEqual => "!=",
Self::And => "&",
Self::Or => "|",
Self::Xor => "^",
}
}
}
#[derive(Debug, PartialEq)]
pub struct UnaryOperator {
pub span: Span,
pub operation: UnaryOperatorType,
}
#[derive(Debug, PartialEq, Clone)]
#[allow(missing_docs)]
pub enum UnaryOperatorType {
Minus,
Plus,
Not,
}
impl UnaryOperatorType {
pub fn as_str(&self) -> &'static str {
match self {
UnaryOperatorType::Minus => "-",
UnaryOperatorType::Plus => "+",
UnaryOperatorType::Not => "!",
}
}
}
#[derive(Debug, PartialEq)]
pub enum Expression {
Literal(ast::Literal),
Bracketed(Box<Expression>, Span),
Tuple(TupleExpression),
ArrayRange(ArrayRangeExpression),
ArrayList(ArrayListExpression),
String(FormatString),
QualifiedName(QualifiedName),
Marker(ast::Identifier),
BinaryOperation(BinaryOperation),
UnaryOperation(UnaryOperation),
Body(ast::Body),
Call(Call),
ElementAccess(ElementAccess),
If(If),
Error(Span),
}
impl Expression {
pub fn span(&self) -> Span {
match self {
Expression::Literal(ex) => ex.span.clone(),
Expression::Bracketed(_, span) => span.clone(),
Expression::Tuple(ex) => ex.span.clone(),
Expression::ArrayRange(ex) => ex.span.clone(),
Expression::ArrayList(ex) => ex.span.clone(),
Expression::String(ex) => ex.span.clone(),
Expression::QualifiedName(ex) => ex.span.clone(),
Expression::Marker(ex) => ex.span.clone(),
Expression::BinaryOperation(ex) => ex.span.clone(),
Expression::UnaryOperation(ex) => ex.span.clone(),
Expression::Body(ex) => ex.span.clone(),
Expression::Call(ex) => ex.span.clone(),
Expression::ElementAccess(ex) => ex.span.clone(),
Expression::If(ex) => ex.span.clone(),
Expression::Error(span) => span.clone(),
}
}
pub fn is_also_statement(&self) -> bool {
matches!(self, Expression::Body(_) | Expression::If(_))
}
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct FormatString {
pub span: Span,
pub extras: ast::ItemExtras,
pub parts: Vec<StringPart>,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub enum StringPart {
Char(StringCharacter),
Content(ast::StringLiteral),
Expression(StringExpression),
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct StringCharacter {
pub span: Span,
pub character: char,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct StringExpression {
pub span: Span,
pub extras: ast::ItemExtras,
pub expression: Box<Expression>,
pub specification: Box<StringFormatSpecification>,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct StringFormatSpecification {
pub span: Span,
pub precision: Option<Result<u32, (ParseIntError, Span)>>,
pub width: Option<Result<u32, (ParseIntError, Span)>>,
}
impl StringFormatSpecification {
pub fn is_some(&self) -> bool {
self.precision.is_some() || self.width.is_some()
}
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct TupleItem {
pub span: Span,
pub extras: ast::ItemExtras,
pub name: Option<ast::Identifier>,
pub value: Expression,
}
impl ast::Dummy for TupleItem {
fn dummy(span: Span) -> Self {
Self {
span: span.clone(),
extras: ast::ItemExtras::default(),
name: None,
value: Expression::Error(span),
}
}
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct TupleExpression {
pub span: Span,
pub extras: ast::ItemExtras,
pub values: Vec<TupleItem>,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct ArrayRangeExpression {
pub span: Span,
pub extras: ast::ItemExtras,
pub start: Box<ArrayItem>,
pub end: Box<ArrayItem>,
pub unit: Option<ast::Unit>,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct ArrayListExpression {
pub span: Span,
pub extras: ast::ItemExtras,
pub items: Vec<ArrayItem>,
pub unit: Option<ast::Unit>,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct ArrayItem {
pub span: Span,
pub extras: ast::ItemExtras,
pub expression: Expression,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct QualifiedName {
pub span: Span,
pub extras: ast::ItemExtras,
pub parts: Vec<ast::Identifier>,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct BinaryOperation {
pub span: Span,
pub lhs: Box<Expression>,
pub operation: BinaryOperator,
pub rhs: Box<Expression>,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct UnaryOperation {
pub span: Span,
pub extras: ast::ItemExtras,
pub operation: UnaryOperator,
pub rhs: Box<Expression>,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct Call {
pub span: Span,
pub extras: ast::ItemExtras,
pub name: QualifiedName,
pub arguments: ArgumentList,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct ElementAccess {
pub span: Span,
pub value: Box<Expression>,
pub element_chain: Vec<Element>,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub enum ElementInner {
Attribute(ast::Identifier),
Tuple(ast::Identifier),
Method(Call),
ArrayElement(Box<Expression>),
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct Element {
pub span: Span,
pub extras: ast::ItemExtras,
pub inner: ElementInner,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct Body {
pub span: Span,
pub statements: ast::StatementList,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct If {
pub span: Span,
pub if_span: Span,
pub extras: ast::ItemExtras,
pub condition: Box<Expression>,
pub body: Body,
pub next_if_span: Option<Span>,
pub next_if: Option<Box<If>>,
pub else_span: Option<Span>,
pub else_body: Option<Body>,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct ArgumentList {
pub span: Span,
pub extras: ast::ItemExtras,
pub arguments: Vec<Argument>,
}
impl ast::Dummy for ArgumentList {
fn dummy(span: Span) -> Self {
Self {
span,
extras: ast::ItemExtras::default(),
arguments: Vec::new(),
}
}
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub enum Argument {
Unnamed(UnnamedArgument),
Named(NamedArgument),
}
impl Argument {
pub fn name(&self) -> Option<&ast::Identifier> {
match self {
Argument::Unnamed(_) => None,
Argument::Named(arg) => Some(&arg.name),
}
}
pub fn value(&self) -> &Expression {
match self {
Argument::Unnamed(arg) => &arg.value,
Argument::Named(arg) => &arg.value,
}
}
pub fn span(&self) -> &Span {
match self {
Argument::Unnamed(arg) => &arg.span,
Argument::Named(arg) => &arg.span,
}
}
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct UnnamedArgument {
pub span: Span,
pub extras: ast::ItemExtras,
pub value: Expression,
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub struct NamedArgument {
pub span: Span,
pub extras: ast::ItemExtras,
pub name: ast::Identifier,
pub value: Expression,
}