Compare commits

...

7 Commits

Author SHA1 Message Date
Tom Alexander
f21385a901
Add a helper function for logging during debugging.
All checks were successful
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-29 14:03:14 -04:00
Tom Alexander
1d06d95bb1
Add a minimum stars figure to heading parser to reduce re-parses. 2023-08-29 14:01:28 -04:00
Tom Alexander
bfc88c1d1b
Use a detect_headline function instead of the full headline parse for the section_end exit matcher.
This shaved 2 seconds off the first 800 lines of org-mode/doc/org-guide.org.
2023-08-29 11:35:54 -04:00
Tom Alexander
f29720e5b9
Switch to using a type for bracket depth.
This is to make changing the type easier in the future.
2023-08-29 11:18:15 -04:00
Tom Alexander
27a9b5aeb1
Switch to i16 for backet depth count.
This is having a measurable performance increase. 32k bracket depth should be enough for any non-malicious document.
2023-08-29 11:14:50 -04:00
Tom Alexander
8051c3d2b7
Remove line number tracking.
The documentation was incorrect, none of the org-mode elements have a line number restriction for their contents.
2023-08-29 11:09:28 -04:00
Tom Alexander
bd97d2f69d
Switch to i32 for tracking bracket depth. 2023-08-29 11:07:00 -04:00
10 changed files with 86 additions and 66 deletions

View File

@ -12,6 +12,7 @@ use nom::multi::separated_list1;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::citation_reference::must_balance_bracket; use super::citation_reference::must_balance_bracket;
use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
@ -102,7 +103,7 @@ fn global_prefix<'r, 's>(
} }
fn global_prefix_end( fn global_prefix_end(
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
move |context: Context, input: OrgSource<'_>| { move |context: Context, input: OrgSource<'_>| {
_global_prefix_end(context, input, starting_bracket_depth) _global_prefix_end(context, input, starting_bracket_depth)
@ -113,7 +114,7 @@ fn global_prefix_end(
fn _global_prefix_end<'r, 's>( fn _global_prefix_end<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_bracket_depth() - starting_bracket_depth; let current_depth = input.get_bracket_depth() - starting_bracket_depth;
if current_depth < 0 { if current_depth < 0 {
@ -154,7 +155,7 @@ fn global_suffix<'r, 's>(
} }
fn global_suffix_end( fn global_suffix_end(
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
move |context: Context, input: OrgSource<'_>| { move |context: Context, input: OrgSource<'_>| {
_global_suffix_end(context, input, starting_bracket_depth) _global_suffix_end(context, input, starting_bracket_depth)
@ -165,7 +166,7 @@ fn global_suffix_end(
fn _global_suffix_end<'r, 's>( fn _global_suffix_end<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_bracket_depth() - starting_bracket_depth; let current_depth = input.get_bracket_depth() - starting_bracket_depth;
if current_depth < 0 { if current_depth < 0 {

View File

@ -10,6 +10,7 @@ use nom::multi::many_till;
use nom::sequence::preceded; use nom::sequence::preceded;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
@ -109,7 +110,7 @@ fn key_suffix<'r, 's>(
} }
fn key_prefix_end( fn key_prefix_end(
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
move |context: Context, input: OrgSource<'_>| { move |context: Context, input: OrgSource<'_>| {
_key_prefix_end(context, input, starting_bracket_depth) _key_prefix_end(context, input, starting_bracket_depth)
@ -120,7 +121,7 @@ fn key_prefix_end(
fn _key_prefix_end<'r, 's>( fn _key_prefix_end<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_bracket_depth() - starting_bracket_depth; let current_depth = input.get_bracket_depth() - starting_bracket_depth;
if current_depth < 0 { if current_depth < 0 {
@ -140,7 +141,7 @@ fn _key_prefix_end<'r, 's>(
} }
fn key_suffix_end( fn key_suffix_end(
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
move |context: Context, input: OrgSource<'_>| { move |context: Context, input: OrgSource<'_>| {
_key_suffix_end(context, input, starting_bracket_depth) _key_suffix_end(context, input, starting_bracket_depth)
@ -151,7 +152,7 @@ fn key_suffix_end(
fn _key_suffix_end<'r, 's>( fn _key_suffix_end<'r, 's>(
_context: Context<'r, 's>, _context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_bracket_depth() - starting_bracket_depth; let current_depth = input.get_bracket_depth() - starting_bracket_depth;
if current_depth < 0 { if current_depth < 0 {

View File

@ -139,7 +139,7 @@ fn _document<'r, 's>(
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Document<'s>> { ) -> Res<OrgSource<'s>, Document<'s>> {
let zeroth_section_matcher = parser_with_context!(zeroth_section)(context); let zeroth_section_matcher = parser_with_context!(zeroth_section)(context);
let heading_matcher = parser_with_context!(heading)(context); let heading_matcher = parser_with_context!(heading(0))(context);
let (remaining, _blank_lines) = many0(blank_line)(input)?; let (remaining, _blank_lines) = many0(blank_line)(input)?;
let (remaining, zeroth_section) = opt(zeroth_section_matcher)(remaining)?; let (remaining, zeroth_section) = opt(zeroth_section_matcher)(remaining)?;
let (remaining, children) = many0(heading_matcher)(remaining)?; let (remaining, children) = many0(heading_matcher)(remaining)?;
@ -260,28 +260,31 @@ fn section<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn section_end<'r, 's>( fn section_end<'r, 's>(
context: Context<'r, 's>, _context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
let headline_matcher = parser_with_context!(headline)(context); recognize(detect_headline)(input)
recognize(headline_matcher)(input) }
const fn heading(
parent_stars: usize,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, Heading<'s>> {
move |context: Context, input: OrgSource<'_>| _heading(context, input, parent_stars)
} }
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn heading<'r, 's>( fn _heading<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
parent_stars: usize,
) -> Res<OrgSource<'s>, Heading<'s>> { ) -> Res<OrgSource<'s>, Heading<'s>> {
not(|i| context.check_exit_matcher(i))(input)?; not(|i| context.check_exit_matcher(i))(input)?;
let (remaining, (star_count, _ws, maybe_todo_keyword, title, heading_tags)) = let (remaining, (star_count, _ws, maybe_todo_keyword, title, heading_tags)) =
headline(context, input)?; headline(context, input, parent_stars)?;
let section_matcher = parser_with_context!(section)(context); let section_matcher = parser_with_context!(section)(context);
let heading_matcher = parser_with_context!(heading)(context); let heading_matcher = parser_with_context!(heading(star_count))(context);
let (remaining, children) = many0(alt(( let (remaining, children) = many0(alt((
map( map(heading_matcher, DocumentElement::Heading),
verify(heading_matcher, |h| h.stars > star_count),
DocumentElement::Heading,
),
map(section_matcher, DocumentElement::Section), map(section_matcher, DocumentElement::Section),
)))(remaining)?; )))(remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
@ -299,10 +302,17 @@ fn heading<'r, 's>(
)) ))
} }
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn detect_headline<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
tuple((start_of_line, many1(tag("*")), space1))(input)?;
Ok((input, ()))
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn headline<'r, 's>( fn headline<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
parent_stars: usize,
) -> Res< ) -> Res<
OrgSource<'s>, OrgSource<'s>,
( (
@ -325,7 +335,9 @@ fn headline<'r, 's>(
(_sol, star_count, ws, maybe_todo_keyword, title, maybe_tags, _ws, _line_ending), (_sol, star_count, ws, maybe_todo_keyword, title, maybe_tags, _ws, _line_ending),
) = tuple(( ) = tuple((
start_of_line, start_of_line,
many1_count(tag("*")), verify(many1_count(tag("*")), |star_count| {
*star_count > parent_stars
}),
space1, space1,
opt(tuple((heading_keyword, space1))), opt(tuple((heading_keyword, space1))),
many1(standard_set_object_matcher), many1(standard_set_object_matcher),

View File

@ -5,6 +5,7 @@ use nom::character::complete::space0;
use nom::combinator::verify; use nom::combinator::verify;
use nom::multi::many_till; use nom::multi::many_till;
use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::parser_context::ContextElement; use super::parser_context::ContextElement;
use super::Context; use super::Context;
@ -121,7 +122,7 @@ fn footnote_reference_only<'r, 's>(
} }
fn footnote_definition_end( fn footnote_definition_end(
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
move |context: Context, input: OrgSource<'_>| { move |context: Context, input: OrgSource<'_>| {
_footnote_definition_end(context, input, starting_bracket_depth) _footnote_definition_end(context, input, starting_bracket_depth)
@ -132,7 +133,7 @@ fn footnote_definition_end(
fn _footnote_definition_end<'r, 's>( fn _footnote_definition_end<'r, 's>(
_context: Context<'r, 's>, _context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_bracket_depth() - starting_bracket_depth; let current_depth = input.get_bracket_depth() - starting_bracket_depth;
if current_depth > 0 { if current_depth > 0 {

View File

@ -10,6 +10,7 @@ use nom::combinator::recognize;
use nom::combinator::verify; use nom::combinator::verify;
use nom::multi::many_till; use nom::multi::many_till;
use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
@ -91,7 +92,7 @@ fn header<'r, 's>(
} }
fn header_end( fn header_end(
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
move |context: Context, input: OrgSource<'_>| { move |context: Context, input: OrgSource<'_>| {
_header_end(context, input, starting_bracket_depth) _header_end(context, input, starting_bracket_depth)
@ -102,7 +103,7 @@ fn header_end(
fn _header_end<'r, 's>( fn _header_end<'r, 's>(
_context: Context<'r, 's>, _context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_bracket_depth() - starting_bracket_depth; let current_depth = input.get_bracket_depth() - starting_bracket_depth;
if current_depth > 0 { if current_depth > 0 {
@ -141,7 +142,7 @@ fn argument<'r, 's>(
} }
fn argument_end( fn argument_end(
starting_parenthesis_depth: isize, starting_parenthesis_depth: BracketDepth,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
move |context: Context, input: OrgSource<'_>| { move |context: Context, input: OrgSource<'_>| {
_argument_end(context, input, starting_parenthesis_depth) _argument_end(context, input, starting_parenthesis_depth)
@ -152,7 +153,7 @@ fn argument_end(
fn _argument_end<'r, 's>( fn _argument_end<'r, 's>(
_context: Context<'r, 's>, _context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
starting_parenthesis_depth: isize, starting_parenthesis_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_parenthesis_depth() - starting_parenthesis_depth; let current_depth = input.get_parenthesis_depth() - starting_parenthesis_depth;
if current_depth > 0 { if current_depth > 0 {

View File

@ -12,6 +12,7 @@ use nom::multi::many_till;
#[cfg(feature = "tracing")] #[cfg(feature = "tracing")]
use tracing::span; use tracing::span;
use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
@ -92,7 +93,7 @@ fn header<'r, 's>(
} }
fn header_end( fn header_end(
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
move |context: Context, input: OrgSource<'_>| { move |context: Context, input: OrgSource<'_>| {
_header_end(context, input, starting_bracket_depth) _header_end(context, input, starting_bracket_depth)
@ -103,7 +104,7 @@ fn header_end(
fn _header_end<'r, 's>( fn _header_end<'r, 's>(
_context: Context<'r, 's>, _context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
starting_bracket_depth: isize, starting_bracket_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_bracket_depth() - starting_bracket_depth; let current_depth = input.get_bracket_depth() - starting_bracket_depth;
if current_depth > 0 { if current_depth > 0 {
@ -152,7 +153,7 @@ fn body<'r, 's>(
} }
fn body_end( fn body_end(
starting_brace_depth: isize, starting_brace_depth: BracketDepth,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
move |context: Context, input: OrgSource<'_>| _body_end(context, input, starting_brace_depth) move |context: Context, input: OrgSource<'_>| _body_end(context, input, starting_brace_depth)
} }
@ -161,7 +162,7 @@ fn body_end(
fn _body_end<'r, 's>( fn _body_end<'r, 's>(
_context: Context<'r, 's>, _context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
starting_brace_depth: isize, starting_brace_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_brace_depth() - starting_brace_depth; let current_depth = input.get_brace_depth() - starting_brace_depth;
if current_depth > 0 { if current_depth > 0 {

View File

@ -33,7 +33,7 @@ pub fn standard_set_object<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Object<'s>> { ) -> Res<OrgSource<'s>, Object<'s>> {
alt(( let (remaining, object) = alt((
map(parser_with_context!(timestamp)(context), Object::Timestamp), map(parser_with_context!(timestamp)(context), Object::Timestamp),
map(parser_with_context!(subscript)(context), Object::Subscript), map(parser_with_context!(subscript)(context), Object::Subscript),
map( map(
@ -82,7 +82,8 @@ pub fn standard_set_object<'r, 's>(
map(parser_with_context!(angle_link)(context), Object::AngleLink), map(parser_with_context!(angle_link)(context), Object::AngleLink),
map(parser_with_context!(org_macro)(context), Object::OrgMacro), map(parser_with_context!(org_macro)(context), Object::OrgMacro),
map(parser_with_context!(plain_text)(context), Object::PlainText), map(parser_with_context!(plain_text)(context), Object::PlainText),
))(input) ))(input)?;
Ok((remaining, object))
} }
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
@ -90,7 +91,7 @@ pub fn minimal_set_object<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Object<'s>> { ) -> Res<OrgSource<'s>, Object<'s>> {
alt(( let (remaining, object) = alt((
map(parser_with_context!(subscript)(context), Object::Subscript), map(parser_with_context!(subscript)(context), Object::Subscript),
map( map(
parser_with_context!(superscript)(context), parser_with_context!(superscript)(context),
@ -103,7 +104,8 @@ pub fn minimal_set_object<'r, 's>(
), ),
parser_with_context!(text_markup)(context), parser_with_context!(text_markup)(context),
map(parser_with_context!(plain_text)(context), Object::PlainText), map(parser_with_context!(plain_text)(context), Object::PlainText),
))(input) ))(input)?;
Ok((remaining, object))
} }
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
@ -111,7 +113,7 @@ pub fn any_object_except_plain_text<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Object<'s>> { ) -> Res<OrgSource<'s>, Object<'s>> {
alt(( let (remaining, object) = alt((
map(parser_with_context!(timestamp)(context), Object::Timestamp), map(parser_with_context!(timestamp)(context), Object::Timestamp),
map(parser_with_context!(subscript)(context), Object::Subscript), map(parser_with_context!(subscript)(context), Object::Subscript),
map( map(
@ -159,7 +161,8 @@ pub fn any_object_except_plain_text<'r, 's>(
map(parser_with_context!(plain_link)(context), Object::PlainLink), map(parser_with_context!(plain_link)(context), Object::PlainLink),
map(parser_with_context!(angle_link)(context), Object::AngleLink), map(parser_with_context!(angle_link)(context), Object::AngleLink),
map(parser_with_context!(org_macro)(context), Object::OrgMacro), map(parser_with_context!(org_macro)(context), Object::OrgMacro),
))(input) ))(input)?;
Ok((remaining, object))
} }
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
@ -168,7 +171,7 @@ pub fn regular_link_description_object_set<'r, 's>(
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Object<'s>> { ) -> Res<OrgSource<'s>, Object<'s>> {
// TODO: It can also contain another link, but only when it is a plain or angle link. It can contain square brackets, but not ]] // TODO: It can also contain another link, but only when it is a plain or angle link. It can contain square brackets, but not ]]
alt(( let (remaining, object) = alt((
map( map(
parser_with_context!(export_snippet)(context), parser_with_context!(export_snippet)(context),
Object::ExportSnippet, Object::ExportSnippet,
@ -187,7 +190,8 @@ pub fn regular_link_description_object_set<'r, 's>(
), ),
map(parser_with_context!(org_macro)(context), Object::OrgMacro), map(parser_with_context!(org_macro)(context), Object::OrgMacro),
parser_with_context!(minimal_set_object)(context), parser_with_context!(minimal_set_object)(context),
))(input) ))(input)?;
Ok((remaining, object))
} }
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
@ -195,7 +199,7 @@ pub fn table_cell_set_object<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Object<'s>> { ) -> Res<OrgSource<'s>, Object<'s>> {
alt(( let (remaining, object) = alt((
map(parser_with_context!(citation)(context), Object::Citation), map(parser_with_context!(citation)(context), Object::Citation),
map( map(
parser_with_context!(export_snippet)(context), parser_with_context!(export_snippet)(context),
@ -220,5 +224,6 @@ pub fn table_cell_set_object<'r, 's>(
map(parser_with_context!(target)(context), Object::Target), map(parser_with_context!(target)(context), Object::Target),
map(parser_with_context!(timestamp)(context), Object::Timestamp), map(parser_with_context!(timestamp)(context), Object::Timestamp),
parser_with_context!(minimal_set_object)(context), parser_with_context!(minimal_set_object)(context),
))(input) ))(input)?;
Ok((remaining, object))
} }

View File

@ -11,17 +11,18 @@ use nom::Slice;
use crate::error::CustomError; use crate::error::CustomError;
use crate::error::MyError; use crate::error::MyError;
pub type BracketDepth = i16;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct OrgSource<'s> { pub struct OrgSource<'s> {
full_source: &'s str, full_source: &'s str,
start: usize, start: usize,
end: usize, // exclusive end: usize, // exclusive
start_of_line: usize, start_of_line: usize,
bracket_depth: BracketDepth, // []
brace_depth: BracketDepth, // {}
parenthesis_depth: BracketDepth, // ()
preceding_character: Option<char>, preceding_character: Option<char>,
line_number: usize,
bracket_depth: isize, // []
brace_depth: isize, // {}
parenthesis_depth: isize, // ()
} }
impl<'s> std::fmt::Debug for OrgSource<'s> { impl<'s> std::fmt::Debug for OrgSource<'s> {
@ -43,7 +44,6 @@ impl<'s> OrgSource<'s> {
end: input.len(), end: input.len(),
start_of_line: 0, start_of_line: 0,
preceding_character: None, preceding_character: None,
line_number: 1,
bracket_depth: 0, bracket_depth: 0,
brace_depth: 0, brace_depth: 0,
parenthesis_depth: 0, parenthesis_depth: 0,
@ -73,19 +73,15 @@ impl<'s> OrgSource<'s> {
self.slice(..(other.start - self.start)) self.slice(..(other.start - self.start))
} }
pub fn get_line_number(&self) -> usize { pub fn get_bracket_depth(&self) -> BracketDepth {
self.line_number
}
pub fn get_bracket_depth(&self) -> isize {
self.bracket_depth self.bracket_depth
} }
pub fn get_brace_depth(&self) -> isize { pub fn get_brace_depth(&self) -> BracketDepth {
self.brace_depth self.brace_depth
} }
pub fn get_parenthesis_depth(&self) -> isize { pub fn get_parenthesis_depth(&self) -> BracketDepth {
self.parenthesis_depth self.parenthesis_depth
} }
} }
@ -152,7 +148,6 @@ where
let skipped_text = &self.full_source[self.start..new_start]; let skipped_text = &self.full_source[self.start..new_start];
let mut start_of_line = self.start_of_line; let mut start_of_line = self.start_of_line;
let mut line_number = self.line_number;
let mut bracket_depth = self.bracket_depth; let mut bracket_depth = self.bracket_depth;
let mut brace_depth = self.brace_depth; let mut brace_depth = self.brace_depth;
let mut parenthesis_depth = self.parenthesis_depth; let mut parenthesis_depth = self.parenthesis_depth;
@ -160,7 +155,6 @@ where
match byte { match byte {
b'\n' => { b'\n' => {
start_of_line = self.start + offset + 1; start_of_line = self.start + offset + 1;
line_number += 1;
} }
b'[' => { b'[' => {
bracket_depth += 1; bracket_depth += 1;
@ -190,7 +184,6 @@ where
end: new_end, end: new_end,
start_of_line, start_of_line,
preceding_character: skipped_text.chars().last(), preceding_character: skipped_text.chars().last(),
line_number,
bracket_depth, bracket_depth,
brace_depth, brace_depth,
parenthesis_depth, parenthesis_depth,
@ -436,15 +429,6 @@ mod tests {
assert_eq!(input.slice(8..).get_preceding_character(), Some('💛')); assert_eq!(input.slice(8..).get_preceding_character(), Some('💛'));
} }
#[test]
fn line_number() {
let input = OrgSource::new("lorem\nfoo\nbar\nbaz\nipsum");
assert_eq!(input.get_line_number(), 1);
assert_eq!(input.slice(5..).get_line_number(), 1);
assert_eq!(input.slice(6..).get_line_number(), 2);
assert_eq!(input.slice(6..).slice(10..).get_line_number(), 4);
}
#[test] #[test]
fn depth() { fn depth() {
let input = OrgSource::new("[][()][({)]}}}}"); let input = OrgSource::new("[][()][({)]}}}}");

View File

@ -11,6 +11,7 @@ use nom::combinator::recognize;
use nom::combinator::verify; use nom::combinator::verify;
use nom::multi::many_till; use nom::multi::many_till;
use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::Context; use super::Context;
use super::Object; use super::Object;
@ -170,7 +171,7 @@ fn script_with_braces<'r, 's>(
} }
fn script_with_braces_end( fn script_with_braces_end(
starting_brace_depth: isize, starting_brace_depth: BracketDepth,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
move |context: Context, input: OrgSource<'_>| { move |context: Context, input: OrgSource<'_>| {
_script_with_braces_end(context, input, starting_brace_depth) _script_with_braces_end(context, input, starting_brace_depth)
@ -181,7 +182,7 @@ fn script_with_braces_end(
fn _script_with_braces_end<'r, 's>( fn _script_with_braces_end<'r, 's>(
_context: Context<'r, 's>, _context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
starting_brace_depth: isize, starting_brace_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_brace_depth() - starting_brace_depth; let current_depth = input.get_brace_depth() - starting_brace_depth;
if current_depth > 0 { if current_depth > 0 {

View File

@ -155,3 +155,16 @@ pub fn not_yet_implemented() -> Res<OrgSource<'static>, ()> {
"Not implemented yet.".into(), "Not implemented yet.".into(),
)))); ))));
} }
#[allow(dead_code)]
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
/// Text from the current point until the next line break or end of file
///
/// Useful for debugging.
pub fn text_until_eol<'r, 's>(
input: OrgSource<'s>,
) -> Result<&'s str, nom::Err<CustomError<OrgSource<'s>>>> {
let line = recognize(many_till(anychar, alt((line_ending, eof))))(input)
.map(|(_remaining, line)| Into::<&str>::into(line))?;
Ok(line.trim())
}