Implement parser for subscript/superscript with braces.
This commit is contained in:
parent
f717d5e7df
commit
23d587c699
@ -194,6 +194,18 @@ pub enum ContextElement<'r, 's> {
|
|||||||
/// unbalanced brackets can be detected in the middle of an
|
/// unbalanced brackets can be detected in the middle of an
|
||||||
/// object.
|
/// object.
|
||||||
InlineSourceBlockBracket(InlineSourceBlockBracket<'s>),
|
InlineSourceBlockBracket(InlineSourceBlockBracket<'s>),
|
||||||
|
|
||||||
|
/// Stores the current bracket or parenthesis depth inside a
|
||||||
|
/// superscript or superscript.
|
||||||
|
///
|
||||||
|
/// Inside the braces of a subscript or superscript there must be
|
||||||
|
/// balanced braces {}, so this stores the amount of opening
|
||||||
|
/// braces subtracted by the amount of closing braces within the
|
||||||
|
/// definition must equal zero.
|
||||||
|
///
|
||||||
|
/// A reference to the position in the string is also included so
|
||||||
|
/// unbalanced braces can be detected in the middle of an object.
|
||||||
|
SubscriptSuperscriptBrace(SubscriptSuperscriptBrace<'s>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ExitMatcherNode<'r> {
|
pub struct ExitMatcherNode<'r> {
|
||||||
@ -225,6 +237,12 @@ pub struct InlineSourceBlockBracket<'s> {
|
|||||||
pub depth: usize,
|
pub depth: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SubscriptSuperscriptBrace<'s> {
|
||||||
|
pub position: &'s str,
|
||||||
|
pub depth: usize,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'r> std::fmt::Debug for ExitMatcherNode<'r> {
|
impl<'r> std::fmt::Debug for ExitMatcherNode<'r> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let mut formatter = f.debug_struct("ExitMatcherNode");
|
let mut formatter = f.debug_struct("ExitMatcherNode");
|
||||||
|
@ -16,7 +16,13 @@ use super::Object;
|
|||||||
use crate::error::CustomError;
|
use crate::error::CustomError;
|
||||||
use crate::error::MyError;
|
use crate::error::MyError;
|
||||||
use crate::error::Res;
|
use crate::error::Res;
|
||||||
|
use crate::parser::exiting::ExitClass;
|
||||||
|
use crate::parser::object_parser::standard_set_object;
|
||||||
|
use crate::parser::parser_context::ContextElement;
|
||||||
|
use crate::parser::parser_context::ExitMatcherNode;
|
||||||
|
use crate::parser::parser_context::SubscriptSuperscriptBrace;
|
||||||
use crate::parser::parser_with_context::parser_with_context;
|
use crate::parser::parser_with_context::parser_with_context;
|
||||||
|
use crate::parser::util::exit_matcher_parser;
|
||||||
use crate::parser::util::get_consumed;
|
use crate::parser::util::get_consumed;
|
||||||
use crate::parser::util::get_one_before;
|
use crate::parser::util::get_one_before;
|
||||||
use crate::parser::Subscript;
|
use crate::parser::Subscript;
|
||||||
@ -79,6 +85,9 @@ fn script_body<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str,
|
|||||||
map(parser_with_context!(script_alphanum)(context), |body| {
|
map(parser_with_context!(script_alphanum)(context), |body| {
|
||||||
ScriptBody::Braceless(body)
|
ScriptBody::Braceless(body)
|
||||||
}),
|
}),
|
||||||
|
map(parser_with_context!(script_with_braces)(context), |body| {
|
||||||
|
ScriptBody::WithBraces(body)
|
||||||
|
}),
|
||||||
))(input)
|
))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,3 +128,77 @@ fn end_script_alphanum_character<'r, 's>(
|
|||||||
)))(remaining)?;
|
)))(remaining)?;
|
||||||
Ok((remaining, final_char))
|
Ok((remaining, final_char))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(ret, level = "debug")]
|
||||||
|
fn script_with_braces<'r, 's>(
|
||||||
|
context: Context<'r, 's>,
|
||||||
|
input: &'s str,
|
||||||
|
) -> Res<&'s str, Vec<Object<'s>>> {
|
||||||
|
let (remaining, _) = tag("{")(input)?;
|
||||||
|
let parser_context = context
|
||||||
|
.with_additional_node(ContextElement::SubscriptSuperscriptBrace(
|
||||||
|
SubscriptSuperscriptBrace {
|
||||||
|
position: remaining,
|
||||||
|
depth: 0,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
|
class: ExitClass::Beta,
|
||||||
|
exit_matcher: &script_with_braces_end,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let (remaining, (children, _exit_contents)) = many_till(
|
||||||
|
parser_with_context!(standard_set_object)(&parser_context),
|
||||||
|
parser_with_context!(exit_matcher_parser)(&parser_context),
|
||||||
|
)(remaining)?;
|
||||||
|
|
||||||
|
let (remaining, _) = tag("}")(remaining)?;
|
||||||
|
Ok((remaining, children))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(ret, level = "debug")]
|
||||||
|
fn script_with_braces_end<'r, 's>(
|
||||||
|
context: Context<'r, 's>,
|
||||||
|
input: &'s str,
|
||||||
|
) -> Res<&'s str, &'s str> {
|
||||||
|
let context_depth = get_bracket_depth(context)
|
||||||
|
.expect("This function should only be called from inside a subscript or superscript.");
|
||||||
|
let text_since_context_entry = get_consumed(context_depth.position, input);
|
||||||
|
let mut current_depth = context_depth.depth;
|
||||||
|
for c in text_since_context_entry.chars() {
|
||||||
|
match c {
|
||||||
|
'{' => {
|
||||||
|
current_depth += 1;
|
||||||
|
}
|
||||||
|
'}' if current_depth == 0 => {
|
||||||
|
panic!("Exceeded subscript or superscript brace depth.")
|
||||||
|
}
|
||||||
|
'}' if current_depth > 0 => {
|
||||||
|
current_depth -= 1;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if current_depth == 0 {
|
||||||
|
let close_bracket = tag::<&str, &str, CustomError<&str>>("}")(input);
|
||||||
|
if close_bracket.is_ok() {
|
||||||
|
return close_bracket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
||||||
|
"Not a valid end for subscript or superscript.",
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(ret, level = "debug")]
|
||||||
|
fn get_bracket_depth<'r, 's>(
|
||||||
|
context: Context<'r, 's>,
|
||||||
|
) -> Option<&'r SubscriptSuperscriptBrace<'s>> {
|
||||||
|
for node in context.iter() {
|
||||||
|
match node.get_data() {
|
||||||
|
ContextElement::SubscriptSuperscriptBrace(depth) => return Some(depth),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user