Add an exit matcher to plain text.

This commit is contained in:
Tom Alexander
2023-04-22 19:46:27 -04:00
parent 9a3bde0d80
commit a4cce121c0
3 changed files with 35 additions and 4 deletions

View File

@@ -1,9 +1,16 @@
use nom::combinator::not;
use nom::combinator::recognize;
use super::object::PlainText;
use super::Context;
use crate::error::CustomError;
use crate::error::MyError;
use crate::error::Res;
use nom::combinator::not;
use crate::parser::exiting::ExitClass;
use crate::parser::object_parser::any_object_except_plain_text;
use crate::parser::parser_context::ContextElement;
use crate::parser::parser_context::ExitMatcherNode;
use crate::parser::parser_with_context::parser_with_context;
#[tracing::instrument(ret, level = "debug")]
pub fn plain_text<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, PlainText<'s>> {
@@ -12,12 +19,17 @@ pub fn plain_text<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s
"Zero input length to plain_text.",
))));
}
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
exit_matcher: &plain_text_end,
}));
let mut current_input = input.char_indices();
loop {
match current_input.next() {
Some((offset, _char)) => {
let remaining = &input[offset..];
let exit_matcher_status = not(|i| context.check_exit_matcher(i))(remaining);
let exit_matcher_status = not(|i| parser_context.check_exit_matcher(i))(remaining);
if exit_matcher_status.is_err() {
if offset == 0 {
// If we're at the start of the input, then nothing is plain text, so fire an error for zero-length match.
@@ -40,18 +52,22 @@ pub fn plain_text<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s
}
}
#[tracing::instrument(ret, level = "debug")]
fn plain_text_end<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> {
recognize(parser_with_context!(any_object_except_plain_text)(context))(input)
}
#[cfg(test)]
mod tests {
use nom::combinator::map;
use super::*;
use crate::parser::object::Object;
use crate::parser::parser_context::ContextElement;
use crate::parser::parser_context::ContextTree;
use crate::parser::parser_with_context::parser_with_context;
use crate::parser::source::Source;
use super::*;
#[test]
fn plain_text_simple() {
let input = "foobarbaz";