compose_parser 2.1.0

Rust parser created to parse the Jetpack Compose Text and Images
Documentation
extern crate pest;
extern crate pest_derive;

use pest::{Parser, Span};
use pest_derive::Parser;

#[derive(Parser)]
#[grammar = "composable.pest"]
#[doc = r"Struct for parsing composable functions"]
pub struct ComposableFunctionParser;

#[derive(Debug, PartialEq, Eq)]
#[doc = r"Enum for composable function content"]
pub enum Content {
    FunctionName(String),
    Text(String),
    Image(String),
}

#[doc = r"Parse a composable function and return a vector of Content"]
pub fn parse_composable_content(input: &str) -> Result<Vec<Content>, pest::error::Error<Rule>> {
    let mut tokens = vec![];
    let parse_result = ComposableFunctionParser::parse(Rule::compose_function, input);

    return match parse_result {
        Ok(pairs) => {
            let composable_function = pairs
                .into_iter()
                .find(|pair| pair.as_rule() == Rule::compose_function)
                .ok_or_else(|| {
                    pest::error::Error::<Rule>::new_from_span(
                        pest::error::ErrorVariant::CustomError {
                            message: "No composable function found".to_string(),
                        },
                        Span::new(input, 0, 0).unwrap(),
                    )
                })?;

            let function_declaration = composable_function
                .into_inner()
                .find(|pair| pair.as_rule() == Rule::function_declaration)
                .ok_or_else(|| {
                    pest::error::Error::<Rule>::new_from_span(
                        pest::error::ErrorVariant::CustomError {
                            message: "No function declaration found".to_string(),
                        },
                        Span::new(input, 0, 0).unwrap(),
                    )
                })?;

            let function_declaration_pairs = function_declaration.into_inner();

            let function_name = function_declaration_pairs
                .clone()
                .find(|pair| pair.as_rule() == Rule::function_name)
                .ok_or_else(|| {
                    pest::error::Error::<Rule>::new_from_span(
                        pest::error::ErrorVariant::CustomError {
                            message: "No function name found".to_string(),
                        },
                        Span::new(input, 0, 0).unwrap(),
                    )
                })?;

            tokens.push(Content::FunctionName(function_name.as_str().to_string()));

            let block_content = function_declaration_pairs
                .clone()
                .find(|pair| pair.as_rule() == Rule::block)
                .ok_or_else(|| {
                    pest::error::Error::<Rule>::new_from_span(
                        pest::error::ErrorVariant::CustomError {
                            message: "No block content found".to_string(),
                        },
                        Span::new(input, 0, 0).unwrap(),
                    )
                })?;

            for inner_pair in block_content.into_inner() {
                for statement in inner_pair.into_inner() {
                    match statement.as_rule() {
                        Rule::text_function => {
                            if let Some(text_function) = statement.into_inner().next() {
                                tokens.push(Content::Text(text_function.as_str().to_string()));
                            }
                        }
                        Rule::image_function => {
                            if let Some(image_function) = statement.into_inner().next() {
                                tokens.push(Content::Image(image_function.as_str().to_string()));
                            }
                        }
                        _ => {}
                    }
                }
            }
            return Ok(tokens);
        }
        Err(error) => Err(error),
    };
}