xenon-codegen 0.1.0

Codegen and AST for the Xenon programming language
Documentation
use core::fmt;

use enum_as_inner::EnumAsInner;

use crate::identifier::IdentifierAccess;

#[derive(Debug, Clone, Default, EnumAsInner)]
pub enum Expression {
    IntegerLiteral(IntegerLiteral),
    FloatLiteral(FloatLiteral),
    StringLiteral(StringLiteral),
    BooleanLiteral(BooleanLiteral),
    Parentheses(Parentheses),
    UnaryOperation(UnaryOperation),
    BinaryOperation(BinaryOperation),
    Identifier(IdentifierAccess),
    #[default]
    Null,
}
impl Expression {
    pub fn is_valid(&self) -> bool {
        if self.is_integer_literal() {
            self.as_integer_literal().unwrap().is_valid()
        } else if self.is_float_literal() {
            return self.as_float_literal().unwrap().is_valid();
        } else if self.is_string_literal() {
            return self.as_string_literal().unwrap().is_valid();
        } else if self.is_boolean_literal() {
            return self.as_boolean_literal().unwrap().is_valid();
        } else if self.is_parentheses() {
            return self.as_parentheses().unwrap().is_valid();
        } else if self.is_unary_operation() {
            return self.as_unary_operation().unwrap().is_valid();
        } else if self.is_binary_operation() {
            return self.as_binary_operation().unwrap().is_valid();
        } else if self.is_identifier() {
            return self.as_identifier().unwrap().is_valid();
        } else {
            return false;
        }
    }
}
impl fmt::Display for Expression {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self.is_integer_literal() {
            match write!(fmt, "{}", self.as_integer_literal().unwrap()) {
                Ok(_) => (),
                Err(e) => return Err(e),
            }
        } else if self.is_float_literal() {
            match write!(fmt, "{}", self.as_float_literal().unwrap()) {
                Ok(_) => (),
                Err(e) => return Err(e),
            }
        } else if self.is_string_literal() {
            match write!(fmt, "{}", self.as_string_literal().unwrap()) {
                Ok(_) => (),
                Err(e) => return Err(e),
            }
        } else if self.is_boolean_literal() {
            match write!(fmt, "{}", self.as_boolean_literal().unwrap()) {
                Ok(_) => (),
                Err(e) => return Err(e),
            }
        } else if self.is_unary_operation() {
            match write!(fmt, "{}", self.as_unary_operation().unwrap()) {
                Ok(_) => (),
                Err(e) => return Err(e),
            }
        } else if self.is_binary_operation() {
            match write!(fmt, "{}", self.as_binary_operation().unwrap()) {
                Ok(_) => (),
                Err(e) => return Err(e),
            }
        } else if self.is_identifier() {
            match write!(fmt, "{}", self.as_identifier().unwrap()) {
                Ok(_) => (),
                Err(e) => return Err(e),
            }
        }
        Ok(())
    }
}

#[derive(Debug, Clone, Default)]
pub struct IntegerLiteral {
    pub value: i64,
}
impl IntegerLiteral {
    pub fn new(val: i64) -> IntegerLiteral {
        IntegerLiteral { value: val }
    }

    pub fn is_valid(&self) -> bool {
        true
    }
}
impl fmt::Display for IntegerLiteral {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match write!(fmt, "{}", self.value) {
            Ok(_) => (),
            Err(e) => return Err(e),
        }
        Ok(())
    }
}

#[derive(Debug, Clone, Default)]
pub struct FloatLiteral {
    pub value: f64,
}
impl FloatLiteral {
    pub fn new(val: f64) -> FloatLiteral {
        FloatLiteral { value: val }
    }

    pub fn is_valid(&self) -> bool {
        self.value.is_normal() || self.value == 0.0
    }
}
impl fmt::Display for FloatLiteral {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match write!(fmt, "{}", self.value) {
            Ok(_) => (),
            Err(e) => return Err(e),
        }
        Ok(())
    }
}

#[derive(Debug, Clone, Default)]
pub struct StringLiteral {
    pub value: String,
}
impl StringLiteral {
    pub fn new(val: String) -> StringLiteral {
        StringLiteral { value: val }
    }
    pub fn is_valid(&self) -> bool {
        true
    }
}
impl fmt::Display for StringLiteral {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match write!(fmt, "\"{}\"", self.value) {
            Ok(_) => (),
            Err(e) => return Err(e),
        }
        Ok(())
    }
}

#[derive(Debug, Clone, Default)]
pub struct BooleanLiteral {
    pub value: bool,
}
impl BooleanLiteral {
    pub fn new(val: bool) -> BooleanLiteral {
        BooleanLiteral { value: val }
    }

    pub fn is_valid(&self) -> bool {
        true
    }
}
impl fmt::Display for BooleanLiteral {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match write!(fmt, "{}", self.value) {
            Ok(_) => (),
            Err(e) => return Err(e),
        }
        Ok(())
    }
}

#[derive(Debug, Clone, Default)]
pub struct UnaryOperation {
    pub operator: String,
    pub term: Box<Expression>,
}
impl UnaryOperation {
    pub fn new(op: String, val: Expression) -> UnaryOperation {
        UnaryOperation {
            operator: op,
            term: Box::new(val),
        }
    }

    pub fn is_valid(&self) -> bool {
        if !["+", "-", "*", "&"].contains(&self.operator.as_str()) {
            return false;
        }
        self.term.is_valid()
    }
}
impl fmt::Display for UnaryOperation {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match write!(fmt, "{}{}", self.operator, self.term) {
            Ok(_) => (),
            Err(e) => return Err(e),
        }
        Ok(())
    }
}

#[derive(Debug, Clone, Default)]
pub struct Parentheses {
    pub value: Box<Expression>,
}
impl Parentheses {
    pub fn new(expr: Expression) -> Parentheses {
        Parentheses {
            value: Box::new(expr),
        }
    }

    pub fn is_valid(&self) -> bool {
        self.value.is_valid()
    }
}
impl fmt::Display for Parentheses {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match write!(fmt, "({})", self.value) {
            Ok(_) => (),
            Err(e) => return Err(e),
        }
        Ok(())
    }
}

#[derive(Debug, Clone, Default)]
pub struct BinaryOperation {
    pub left: Box<Expression>,
    pub operator: String,
    pub right: Box<Expression>,
}
impl BinaryOperation {
    pub fn new(left: Expression, op: String, right: Expression) -> BinaryOperation {
        BinaryOperation {
            left: Box::new(left),
            operator: op,
            right: Box::new(right),
        }
    }

    pub fn is_valid(&self) -> bool {
        self.left.is_valid()
            && self.right.is_valid()
            && ["+", "-", "*", "/", "==", "<", "<=", ">", ">=", "&&", "||"]
                .contains(&self.operator.as_str())
    }
}
impl fmt::Display for BinaryOperation {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match write!(fmt, "{} {} {}", self.left, self.operator, self.right) {
            Ok(_) => (),
            Err(e) => return Err(e),
        }
        Ok(())
    }
}