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::{Measurement, ParseNode};
use crate::error::ParseError;
use crate::function_registry::{ArgType, FunctionContext, FunctionParser, FunctionSpec};

use super::require_function_arg;

pub(crate) fn require_size_argument(
    arg: ParseNode,
    func_name: &str,
) -> Result<Measurement, ParseError> {
    match arg {
        ParseNode::Size { value, .. } => Ok(value),
        _ => Err(ParseError::InternalInvariant {
            message: format!("Expected size argument for {func_name}"),
        }),
    }
}

pub(crate) fn rule_spec() -> FunctionSpec {
    FunctionSpec {
        names: vec!["\\rule".to_string()],
        num_args: 2,
        num_optional_args: 1,
        arg_types: vec![ArgType::SizeArg, ArgType::SizeArg, ArgType::SizeArg],
        allowed_in_text: true,
        handler: Some(rule_handler),
        ..Default::default()
    }
}

fn rule_handler(
    _parser: &mut dyn FunctionParser,
    context: &FunctionContext,
    args: &[ParseNode],
    opt_args: &[Option<ParseNode>],
) -> Result<ParseNode, ParseError> {
    let shift = opt_args
        .first()
        .and_then(|o| o.as_ref())
        .map(|arg| require_size_argument(arg.clone(), &context.func_name))
        .transpose()?;
    Ok(ParseNode::Rule {
        mode: context.mode,
        shift,
        width: require_size_argument(
            require_function_arg(args, 0, &context.func_name)?,
            &context.func_name,
        )?,
        height: require_size_argument(
            require_function_arg(args, 1, &context.func_name)?,
            &context.func_name,
        )?,
    })
}