ksl 0.1.30

KSL core library and interpreter
Documentation
//! # ksl::eval::pair
//!
//! Defines functions that parse pairs of parts of a token stream,
//! such as function brackets and list brackets.

use crate::{
    Environment,
    eval::sentence::eval_expression,
    token::{Token, TokenType},
    value::Value,
};

/// The type of Token pair.
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum PairType {
    Function,
    List,
}

/// Parses the paired parts of the token stream.
pub(crate) fn eval_pair(
    tokens: &[Token],
    env: Environment,
    pair_type: PairType,
) -> Result<(Vec<Value>, usize), std::sync::Arc<str>> {
    let mut token_index: usize = 0;
    let mut vals: Vec<Value> = Vec::new();
    let mut expect_element = true;

    let close_type = match pair_type {
        PairType::Function => TokenType::FuncListClose,
        PairType::List => TokenType::ListClose,
    };

    while let Some(token) = tokens.get(token_index) {
        // Check if the pair is closed
        if std::mem::discriminant(&token.value) == std::mem::discriminant(&close_type) {
            return Ok((vals, token_index + 1));
        }

        if expect_element {
            let (val, bias) = eval_expression(&tokens[token_index..], env.clone())?;
            vals.push(val);
            token_index += bias;
            expect_element = false;
        } else if matches!(token.value, TokenType::Seperator) {
            token_index += 1;
            expect_element = true;
        } else {
            return Err(std::sync::Arc::from(format!(
                concat!(
                    "Error[ksl::eval::pair::eval_pair]: ",
                    "Invalid token type `{:?}` at `({}, {})`."
                ),
                token.value, token.location.0.0, token.location.0.1
            )));
        }
    }

    let last_pos = tokens.last().map_or((0, 0), |t| t.location.1);
    Err(std::sync::Arc::from(format!(
        "Error[ksl::eval::pair::eval_pair]: Unclosed pair `{:?}` at `({}, {})`.",
        pair_type, last_pos.0, last_pos.1
    )))
}