katex-parser 0.1.0

A port of the KaTeX parser: lexing and parsing LaTeX math expressions with macro expansion into a typed AST, plus a Unicode rendering backend
Documentation
use crate::ast::ParseNode;
use crate::error::ParseError;
use crate::function_registry::{ArgType, FunctionContext, FunctionParser, FunctionSpec};

use super::require_function_arg;

fn environment_name(arg: &ParseNode) -> Result<String, ParseError> {
    let body = match arg {
        ParseNode::OrdGroup { body, .. } => body,
        _ => {
            return Err(ParseError::InvalidArgument {
                message: "Invalid environment name".to_string(),
                loc: None,
            })
        }
    };
    let mut builder = String::new();
    for node in body {
        match node {
            ParseNode::TextOrd { text, .. } => builder.push_str(text),
            _ => {
                return Err(ParseError::InvalidArgument {
                    message: "Invalid environment name".to_string(),
                    loc: None,
                })
            }
        }
    }
    Ok(builder)
}

pub(crate) fn begin_end_spec() -> FunctionSpec {
    FunctionSpec {
        names: vec!["\\begin".to_string(), "\\end".to_string()],
        num_args: 1,
        arg_types: vec![ArgType::TextArg],
        handler: Some(environment_handler),
        ..Default::default()
    }
}

fn environment_handler(
    parser: &mut dyn FunctionParser,
    context: &FunctionContext,
    args: &[ParseNode],
    _opt_args: &[Option<ParseNode>],
) -> Result<ParseNode, ParseError> {
    let name = environment_name(&require_function_arg(args, 0, &context.func_name)?)?;
    if context.func_name == "\\begin" {
        parser.parse_environment(&name)
    } else {
        Ok(ParseNode::EnvironmentEnd {
            mode: context.mode,
            name,
        })
    }
}

pub(crate) fn hline_spec() -> FunctionSpec {
    FunctionSpec {
        names: vec!["\\hline".to_string(), "\\hdashline".to_string()],
        allowed_in_text: true,
        handler: Some(hline_handler),
        ..Default::default()
    }
}

fn hline_handler(
    _parser: &mut dyn FunctionParser,
    context: &FunctionContext,
    _args: &[ParseNode],
    _opt_args: &[Option<ParseNode>],
) -> Result<ParseNode, ParseError> {
    Err(ParseError::InvalidArgument {
        message: format!("{} valid only within array environment", context.func_name),
        loc: None,
    })
}