galvan-into-ast 0.0.3

CST to AST conversion for the Galvan programming language
Documentation
use crate::items::{read_free_function_call, read_trailing_closure_call};
use crate::result::CursorUtil;
use crate::{cursor_expect, AstError, ReadCursor, SpanExt};
use galvan_ast::{
    Assignment, AssignmentOperator, Closure, CollectionLiteral, ConstructorCall, DeclModifier,
    Declaration, ElseExpression, EnumAccess, Expression, ExpressionKind, FunctionCall, Group,
    Ident, InfixExpression, Literal, PostfixExpression, Span, Statement, TypeElement,
};
use galvan_parse::TreeCursor;

impl ReadCursor for Statement {
    fn read_cursor(cursor: &mut TreeCursor<'_>, source: &str) -> Result<Self, AstError> {
        cursor_expect!(cursor, "statement");

        cursor.child();
        let inner = match cursor.kind()? {
            "assignment" => Statement::Assignment(Assignment::read_cursor(cursor, source)?),
            "declaration" => Statement::Declaration(Declaration::read_cursor(cursor, source)?),
            "expression" => Statement::Expression(Expression::read_cursor(cursor, source)?),
            "free_function" => read_free_function_call(cursor, source)?,
            "break_statement" => {
                let node = cursor.node();
                let span = Span::from_node(node);
                Statement::Break(galvan_ast::Break { span })
            }
            "continue_statement" => {
                let node = cursor.node();
                let span = Span::from_node(node);
                Statement::Continue(galvan_ast::Continue { span })
            }
            _ => unreachable!("Unknown statement kind: {:?}", cursor.kind()?),
        };

        cursor.goto_parent();
        Ok(inner)
    }
}

impl ReadCursor for Declaration {
    fn read_cursor(cursor: &mut TreeCursor<'_>, source: &str) -> Result<Self, AstError> {
        let node = cursor_expect!(cursor, "declaration");
        let span = Span::from_node(node);

        cursor.child();

        let decl_modifier = DeclModifier::read_cursor(cursor, source)?;
        cursor.next();
        let identifier = Ident::read_cursor(cursor, source)?;
        cursor.next();

        let type_annotation = match cursor.kind()? {
            "colon" => {
                cursor.next();
                let elem = Some(TypeElement::read_cursor(cursor, source)?);
                cursor.next();
                elem
            }
            _ => None,
        };

        let assignment = match cursor.kind()? {
            "assign" => {
                cursor.next();
                let expr = Some(Expression::read_cursor(cursor, source)?);
                cursor.next();
                expr
            }
            _ => None,
        };

        cursor.goto_parent();

        let decl = Declaration {
            decl_modifier,
            identifier,
            type_annotation,
            assignment,
            span,
        };

        Ok(decl)
    }
}

impl ReadCursor for Assignment {
    fn read_cursor(cursor: &mut TreeCursor<'_>, source: &str) -> Result<Self, AstError> {
        let node = cursor_expect!(cursor, "assignment");
        let span = Span::from_node(node);

        cursor.child();
        let lhs = Expression::read_cursor(cursor, source)?;

        cursor.next();
        let operator = AssignmentOperator::read_cursor(cursor, source)?;

        cursor.next();
        let rhs = Expression::read_cursor(cursor, source)?;

        cursor.goto_parent();
        Ok(Assignment {
            target: lhs,
            operator,
            expression: rhs,
            span,
        })
    }
}

impl ReadCursor for AssignmentOperator {
    fn read_cursor(cursor: &mut TreeCursor<'_>, _source: &str) -> Result<Self, AstError> {
        let res = match cursor.kind()? {
            "assign" => Self::Assign,
            "add_assign" => Self::AddAssign,
            "sub_assign" => Self::SubAssign,
            "mul_assign" => Self::MulAssign,
            "pow_assign" => Self::PowAssign,
            "div_assign" => Self::DivAssign,
            "rem_assign" => Self::RemAssign,
            "concat_assign" => Self::ConcatAssign,
            unknown => unreachable!("Unknown assignment operator: {unknown}"),
        };

        Ok(res)
    }
}

impl ReadCursor for Expression {
    fn read_cursor(cursor: &mut TreeCursor<'_>, source: &str) -> Result<Self, AstError> {
        let node = cursor_expect!(cursor, "expression");
        let span = Span::from_node(node);

        cursor.child();

        let kind: ExpressionKind = match cursor.kind()? {
            "else_expression" => ElseExpression::read_cursor(cursor, source)?.into(),
            "trailing_closure_expression" => read_trailing_closure_call(cursor, source)?.into(),
            "function_call" => FunctionCall::read_cursor(cursor, source)?.into(),
            "postfix_expression" => {
                ExpressionKind::Postfix(PostfixExpression::read_cursor(cursor, source)?.into())
            }
            "constructor_call" => ConstructorCall::read_cursor(cursor, source)?.into(),
            "enum_access" => EnumAccess::read_cursor(cursor, source)?.into(),
            "collection_literal" => CollectionLiteral::read_cursor(cursor, source)?.into(),
            "literal" => Literal::read_cursor(cursor, source)?.into(),
            "ident" => Ident::read_cursor(cursor, source)?.into(),
            "closure" => Closure::read_cursor(cursor, source)?.into(),
            "group" => Group::read_cursor(cursor, source)?.into(),
            _ => ExpressionKind::Infix(InfixExpression::read_cursor(cursor, source)?.into()),
        };

        cursor.goto_parent();

        Ok(Expression { kind, span })
    }
}