castle_schema_parser 0.20.2

Castle Schema Parser
Documentation
use std::collections::HashMap;

use castle_shared_parser::parse_inputs::consume_optional_separator;
use castle_tokenizer::{
    extensions::{ExpectIdentifier, ExpectPunctuator, IsPunctuator},
    Punctuator, TokenKind, Tokenizable,
};
use castle_types::{AppliedDirective, EnumDefinition, CastleError, VariantDefinition, VariantKindDefinition, Kind};


use super::{parse_directives::parse_directives, parse_kind::parse_kind};

pub(crate) fn parse_enum_definition(
    tokenizer: &mut impl Tokenizable,
    directives: Vec<AppliedDirective>,
) -> Result<EnumDefinition, CastleError> {
    Ok(EnumDefinition {
        ident: tokenizer.expect_identifier(true)?,
        variants: parse_enum_variants(tokenizer)?,
        directives,
    })
}

fn parse_enum_variants(
    tokenizer: &mut impl Tokenizable,
) -> Result<HashMap<Box<str>, VariantDefinition>, CastleError> {
    let mut map = HashMap::new();
    tokenizer.expect_punctuator(Punctuator::OpenBlock, true)?;
    loop {
        if tokenizer.peek_is_punctuator(Punctuator::CloseBlock, true)? {
            break;
        }
        let variant_def = parse_variant_definition(tokenizer)?;
        map.insert(variant_def.ident.clone(), variant_def);
        consume_optional_separator(tokenizer)?;
    }
    tokenizer.expect_punctuator(Punctuator::CloseBlock, true)?;
    Ok(map)
}

fn parse_variant_definition(
    tokenizer: &mut impl Tokenizable,
) -> Result<VariantDefinition, CastleError> {
    Ok(VariantDefinition {
        ident: tokenizer.expect_identifier(true)?,
        kind: parse_variant_kind_definition(tokenizer)?,
        directives: parse_directives(tokenizer)?,
    })
}

fn parse_variant_kind_definition(
    tokenizer: &mut impl Tokenizable,
) -> Result<VariantKindDefinition, CastleError> {
    return match tokenizer.peek_expect(true)?.kind {
        TokenKind::Punctuator(Punctuator::OpenBlock) => Ok(VariantKindDefinition::Map(parse_map(
            tokenizer,
            Punctuator::OpenBlock,
            Punctuator::CloseBlock,
        )?)),
        TokenKind::Punctuator(Punctuator::OpenParen) => Ok(VariantKindDefinition::Tuple(
            parse_tuple(tokenizer, Punctuator::OpenParen, Punctuator::CloseParen)?,
        )),
        _ => Ok(VariantKindDefinition::Unit),
    };
}

pub fn parse_map(
    tokenizer: &mut impl Tokenizable,
    opening: Punctuator,
    closing: Punctuator,
) -> Result<HashMap<Box<str>, Kind>, CastleError> {
    tokenizer.expect_punctuator(opening, true)?;
    let mut inputs = HashMap::new();
    loop {
        if tokenizer.peek_is_punctuator(closing, true)? {
            break;
        }
        inputs.insert(
            tokenizer.expect_identifier(true)?,
            expect_colon_and_kind(tokenizer)?,
        );
        consume_optional_separator(tokenizer)?;
    }
    tokenizer.expect_punctuator(closing, true)?;
    Ok(inputs)
}

fn expect_colon_and_kind(tokenizer: &mut impl Tokenizable) -> Result<Kind, CastleError> {
    tokenizer.expect_punctuator(Punctuator::Colon, true)?;
    parse_kind(tokenizer)
}

pub fn parse_tuple(
    tokenizer: &mut impl Tokenizable,
    opening: Punctuator,
    closing: Punctuator,
) -> Result<Vec<Kind>, CastleError> {
    let mut inputs_vec: Vec<Kind> = Vec::new();
    tokenizer.expect_punctuator(opening, true)?;
    loop {
        if tokenizer.peek_is_punctuator(closing, true)? {
            break;
        }
        inputs_vec.push(parse_kind(tokenizer)?);
        consume_optional_separator(tokenizer)?;
    }
    tokenizer.expect_punctuator(closing, true)?;
    Ok(inputs_vec)
}