rib-lang 0.0.5

Rib language: parser, typechecker, compiler, and interpreter for WebAssembly component (WIT) workflows
Documentation
use crate::parser::RibParseError;
use crate::rib_source_span::GetSourcePosition;
use crate::type_parameter::TypeParameter;
use combine::stream::Stream;
use combine::{attempt, choice, ParseError, Parser};
use internal::*;

// Parser for TypeParameter
pub fn type_parameter<Input>() -> impl Parser<Input, Output = TypeParameter>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
    RibParseError: Into<
        <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
    >,
    Input::Position: GetSourcePosition,
{
    choice((
        attempt(fully_qualified_interface_name().map(TypeParameter::FullyQualifiedInterface)),
        attempt(package_name().map(TypeParameter::PackageName)),
        attempt(interface_name().map(TypeParameter::Interface)),
    ))
}

mod internal {
    use crate::parser::RibParseError;
    use crate::rib_source_span::GetSourcePosition;
    use crate::type_parameter::{FullyQualifiedInterfaceName, InterfaceName, PackageName};
    use combine::parser::char::{alpha_num, char as char_};
    use combine::stream::Stream;
    use combine::{many1, optional, ParseError, Parser};

    pub(crate) fn fully_qualified_interface_name<Input>(
    ) -> impl Parser<Input, Output = FullyQualifiedInterfaceName>
    where
        Input: Stream<Token = char>,
        Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
        RibParseError: Into<
            <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
        >,
        Input::Position: GetSourcePosition,
    {
        (package_name().skip(char_('/')), interface_name()).map(|(package_name, interface_name)| {
            FullyQualifiedInterfaceName {
                package_name,
                interface_name,
            }
        })
    }

    pub(crate) fn package_name<Input>() -> impl Parser<Input, Output = PackageName>
    where
        Input: Stream<Token = char>,
        Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
        RibParseError: Into<
            <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
        >,
        Input::Position: GetSourcePosition,
    {
        let namespace = many1(alpha_num().or(char_('-')).or(char_('_')));
        let package_name = many1(alpha_num().or(char_('-')).or(char_('_')));
        let version = optional(char_('@').with(version()));

        (namespace.skip(char_(':')), package_name, version).map(
            |(namespace, package_name, version)| PackageName {
                namespace,
                package_name,
                version,
            },
        )
    }

    pub(crate) fn interface_name<Input>() -> impl Parser<Input, Output = InterfaceName>
    where
        Input: Stream<Token = char>,
        Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
        RibParseError: Into<
            <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
        >,
        Input::Position: GetSourcePosition,
    {
        let name = many1(alpha_num().or(char_('-')).or(char_('_')));
        let version = optional(char_('@').with(version()));

        (name, version).map(|(name, version)| InterfaceName { name, version })
    }

    fn version<Input>() -> impl Parser<Input, Output = String>
    where
        Input: Stream<Token = char>,
        Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
        RibParseError: Into<
            <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
        >,
        Input::Position: GetSourcePosition,
    {
        many1(alpha_num().or(char_('.')).or(char_('-'))).map(|s: Vec<char>| s.into_iter().collect())
    }
}