galvan-into-ast 0.0.3

CST to AST conversion for the Galvan programming language
Documentation
use galvan_ast::{
    AccessExpression, Block, Body, ClosureParameter, ElseExpression, Expression, PostfixExpression,
    Span, YeetExpression,
};
use galvan_parse::TreeCursor;

use crate::{cursor_expect, result::CursorUtil, AstError, ReadCursor, SpanExt};

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

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

        cursor.next();
        cursor_expect!(cursor, "postfix_operator");

        cursor.child();
        let res = match cursor.kind()? {
            "yeet_operator" => YeetExpression { inner, span }.into(),
            "access_operator" => {
                cursor.child();
                cursor_expect!(cursor, "bracket_open");

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

                cursor.next();
                cursor_expect!(cursor, "bracket_close");

                cursor.goto_parent();
                AccessExpression {
                    base: inner,
                    index,
                    span,
                }
                .into()
            }
            unknown => unreachable!("Unknown postfix operator: {unknown}"),
        };
        cursor.goto_parent();

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

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

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

        cursor.next();
        cursor_expect!(cursor, "else_keyword");

        cursor.next();
        let mut parameter = Vec::new();
        if cursor.kind()? == "pipe" {
            cursor_expect!(cursor, "pipe");
            cursor.next();
            while cursor.kind()? == "closure_argument" {
                parameter.push(ClosureParameter::read_cursor(cursor, source)?);
                cursor.next();
                while cursor.kind()? == "," {
                    cursor.next();
                }
            }

            cursor_expect!(cursor, "pipe");
        }

        cursor.next();
        let body = Body::read_cursor(cursor, source)?;
        let body_span = body.span;
        let block = Block {
            body,
            span: body_span,
        };

        cursor.goto_parent();
        Ok(ElseExpression {
            receiver,
            block,
            parameters: parameter,
        })
    }
}