2023-07-18 20:51:06 -04:00
use nom ::branch ::alt ;
use nom ::bytes ::complete ::tag ;
2023-07-18 21:50:29 -04:00
use nom ::character ::complete ::alpha1 ;
use nom ::character ::complete ::anychar ;
use nom ::character ::complete ::line_ending ;
2023-07-18 22:21:52 -04:00
use nom ::character ::complete ::none_of ;
2023-07-18 21:50:29 -04:00
use nom ::character ::complete ::one_of ;
2023-07-18 20:51:06 -04:00
use nom ::combinator ::peek ;
use nom ::combinator ::recognize ;
2023-07-18 22:21:52 -04:00
use nom ::combinator ::verify ;
2023-07-19 00:37:51 -04:00
use nom ::multi ::many0 ;
2023-07-18 21:50:29 -04:00
use nom ::multi ::many_till ;
use nom ::sequence ::tuple ;
2023-07-18 20:51:06 -04:00
2023-08-23 00:30:26 -04:00
use super ::org_source ::OrgSource ;
2023-08-31 15:44:44 -04:00
use super ::util ::maybe_consume_object_trailing_whitespace_if_not_exiting ;
2023-09-03 12:23:18 -04:00
use crate ::context ::parser_with_context ;
use crate ::context ::RefContext ;
2023-07-18 22:21:52 -04:00
use crate ::error ::CustomError ;
use crate ::error ::MyError ;
2023-07-18 20:51:06 -04:00
use crate ::error ::Res ;
2023-07-18 21:50:29 -04:00
use crate ::parser ::util ::exit_matcher_parser ;
2023-07-18 20:51:06 -04:00
use crate ::parser ::util ::get_consumed ;
2023-09-03 12:23:18 -04:00
use crate ::types ::LatexFragment ;
2023-07-18 20:51:06 -04:00
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-11 13:11:08 -04:00
fn latex_fragment < ' b , ' g , ' r , ' s > (
2023-09-03 15:44:18 -04:00
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , LatexFragment < ' s > > {
2023-07-18 22:02:38 -04:00
let ( remaining , _ ) = alt ( (
parser_with_context! ( raw_latex_fragment ) ( context ) ,
parser_with_context! ( escaped_parenthesis_fragment ) ( context ) ,
parser_with_context! ( escaped_bracket_fragment ) ( context ) ,
2023-07-18 22:21:52 -04:00
parser_with_context! ( double_dollar_fragment ) ( context ) ,
parser_with_context! ( dollar_char_fragment ) ( context ) ,
2023-07-18 22:39:05 -04:00
parser_with_context! ( bordered_dollar_fragment ) ( context ) ,
2023-07-18 22:02:38 -04:00
) ) ( input ) ? ;
2023-08-31 15:44:44 -04:00
let ( remaining , _trailing_whitespace ) =
maybe_consume_object_trailing_whitespace_if_not_exiting ( context , remaining ) ? ;
2023-07-18 21:50:29 -04:00
let source = get_consumed ( input , remaining ) ;
2023-08-23 00:30:26 -04:00
Ok ( (
remaining ,
LatexFragment {
source : source . into ( ) ,
} ,
) )
2023-07-18 21:50:29 -04:00
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-03 15:44:18 -04:00
fn raw_latex_fragment < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-18 20:51:06 -04:00
let ( remaining , _ ) = tag ( " \\ " ) ( input ) ? ;
2023-07-18 21:50:29 -04:00
let ( remaining , _ ) = name ( context , remaining ) ? ;
2023-07-19 00:37:51 -04:00
let ( remaining , _ ) = many0 ( parser_with_context! ( brackets ) ( context ) ) ( remaining ) ? ;
2023-07-18 21:50:29 -04:00
let source = get_consumed ( input , remaining ) ;
Ok ( ( remaining , source ) )
}
2023-07-18 20:51:06 -04:00
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-03 15:44:18 -04:00
fn name < ' b , ' g , ' r , ' s > (
_context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-18 21:50:29 -04:00
alpha1 ( input )
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-03 15:44:18 -04:00
fn brackets < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-18 21:50:29 -04:00
let ( remaining , body ) = alt ( (
recognize ( tuple ( (
tag ( " [ " ) ,
many_till (
anychar ,
peek ( alt ( (
parser_with_context! ( exit_matcher_parser ) ( context ) ,
alt ( ( recognize ( one_of ( " {}[] " ) ) , line_ending ) ) ,
) ) ) ,
) ,
tag ( " ] " ) ,
) ) ) ,
recognize ( tuple ( (
tag ( " { " ) ,
many_till (
anychar ,
peek ( alt ( (
parser_with_context! ( exit_matcher_parser ) ( context ) ,
alt ( ( recognize ( one_of ( " {} " ) ) , line_ending ) ) ,
) ) ) ,
) ,
tag ( " } " ) ,
) ) ) ,
) ) ( input ) ? ;
Ok ( ( remaining , body ) )
2023-07-18 20:51:06 -04:00
}
2023-07-18 22:02:38 -04:00
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-03 15:44:18 -04:00
fn escaped_parenthesis_fragment < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-18 22:02:38 -04:00
let ( remaining , _ ) = tag ( " \\ ( " ) ( input ) ? ;
let ( remaining , _ ) = recognize ( many_till (
anychar ,
peek ( alt ( (
parser_with_context! ( exit_matcher_parser ) ( context ) ,
tag ( " \\ ) " ) ,
) ) ) ,
) ) ( remaining ) ? ;
let ( remaining , _ ) = tag ( " \\ ) " ) ( remaining ) ? ;
let source = get_consumed ( input , remaining ) ;
Ok ( ( remaining , source ) )
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-03 15:44:18 -04:00
fn escaped_bracket_fragment < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-18 22:02:38 -04:00
let ( remaining , _ ) = tag ( " \\ [ " ) ( input ) ? ;
let ( remaining , _ ) = recognize ( many_till (
anychar ,
peek ( alt ( (
parser_with_context! ( exit_matcher_parser ) ( context ) ,
tag ( " \\ ] " ) ,
) ) ) ,
) ) ( remaining ) ? ;
let ( remaining , _ ) = tag ( " \\ ] " ) ( remaining ) ? ;
let source = get_consumed ( input , remaining ) ;
Ok ( ( remaining , source ) )
}
2023-07-18 22:21:52 -04:00
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-03 15:44:18 -04:00
fn double_dollar_fragment < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-18 22:21:52 -04:00
// TODO: The documentation on the dollar sign versions is incomplete. Test to figure out what the real requirements are. For example, can this span more than 3 lines and can this contain a single $ since its terminated by $$?
let ( remaining , _ ) = tag ( " $$ " ) ( input ) ? ;
let ( remaining , _ ) = recognize ( many_till (
anychar ,
peek ( alt ( (
parser_with_context! ( exit_matcher_parser ) ( context ) ,
tag ( " $ " ) ,
) ) ) ,
) ) ( remaining ) ? ;
let ( remaining , _ ) = tag ( " $$ " ) ( remaining ) ? ;
let source = get_consumed ( input , remaining ) ;
Ok ( ( remaining , source ) )
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-03 15:44:18 -04:00
fn dollar_char_fragment < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-18 22:21:52 -04:00
let ( _ , _ ) = pre ( context , input ) ? ;
let ( remaining , _ ) = tag ( " $ " ) ( input ) ? ;
let ( remaining , _ ) = verify ( none_of ( " .,?; \" " ) , | c | ! c . is_whitespace ( ) ) ( remaining ) ? ;
let ( remaining , _ ) = tag ( " $ " ) ( remaining ) ? ;
let ( _ , _ ) = peek ( parser_with_context! ( post ) ( context ) ) ( remaining ) ? ;
let source = get_consumed ( input , remaining ) ;
Ok ( ( remaining , source ) )
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-11 13:11:08 -04:00
fn pre < ' b , ' g , ' r , ' s > (
2023-09-03 15:44:18 -04:00
_context : RefContext < ' b , ' g , ' r , ' s > ,
2023-09-03 12:23:18 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , ( ) > {
2023-08-24 16:55:56 -04:00
let preceding_character = input . get_preceding_character ( ) ;
2023-07-18 22:21:52 -04:00
if let Some ( '$' ) = preceding_character {
return Err ( nom ::Err ::Error ( CustomError ::MyError ( MyError (
2023-08-23 00:30:26 -04:00
" Not a valid pre character for dollar char fragment. " . into ( ) ,
2023-07-18 22:21:52 -04:00
) ) ) ) ;
}
Ok ( ( input , ( ) ) )
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-11 13:11:08 -04:00
fn post < ' b , ' g , ' r , ' s > (
2023-09-03 15:44:18 -04:00
_context : RefContext < ' b , ' g , ' r , ' s > ,
2023-09-03 12:23:18 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , ( ) > {
2023-07-18 22:21:52 -04:00
// TODO: What about eof? Test to find out.
// TODO: Figure out which punctuation characters should be included.
let ( remaining , _ ) = alt ( ( recognize ( one_of ( " \t -.,;:!?' \" " ) ) , line_ending ) ) ( input ) ? ;
Ok ( ( remaining , ( ) ) )
}
2023-07-18 22:39:05 -04:00
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-03 15:44:18 -04:00
fn bordered_dollar_fragment < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-18 22:39:05 -04:00
let ( _ , _ ) = pre ( context , input ) ? ;
let ( remaining , _ ) = tag ( " $ " ) ( input ) ? ;
// TODO: I'm assuming I should be peeking at the borders but the documentation is not clear. Test to figure out.
let ( _ , _ ) = peek ( parser_with_context! ( open_border ) ( context ) ) ( remaining ) ? ;
2023-08-27 23:48:39 -04:00
let ( remaining , _ ) = recognize ( many_till (
anychar ,
peek ( alt ( (
parser_with_context! ( exit_matcher_parser ) ( context ) ,
tag ( " $ " ) ,
) ) ) ,
) ) ( remaining ) ? ;
2023-07-18 22:39:05 -04:00
let ( _ , _ ) = peek ( parser_with_context! ( close_border ) ( context ) ) ( remaining ) ? ;
let ( remaining , _ ) = tag ( " $ " ) ( remaining ) ? ;
let ( _ , _ ) = peek ( parser_with_context! ( post ) ( context ) ) ( remaining ) ? ;
let source = get_consumed ( input , remaining ) ;
Ok ( ( remaining , source ) )
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-11 13:11:08 -04:00
fn open_border < ' b , ' g , ' r , ' s > (
2023-09-03 15:44:18 -04:00
_context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-18 22:39:05 -04:00
recognize ( verify ( none_of ( " .,;$ " ) , | c | ! c . is_whitespace ( ) ) ) ( input )
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-11 13:11:08 -04:00
fn close_border < ' b , ' g , ' r , ' s > (
2023-09-03 15:44:18 -04:00
_context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , ( ) > {
2023-08-24 16:55:56 -04:00
let preceding_character = input . get_preceding_character ( ) ;
2023-07-18 22:39:05 -04:00
match preceding_character {
Some ( c ) if ! c . is_whitespace ( ) & & ! " .,;$ " . contains ( c ) = > Ok ( ( input , ( ) ) ) ,
_ = > {
return Err ( nom ::Err ::Error ( CustomError ::MyError ( MyError (
2023-08-23 00:30:26 -04:00
" Not a valid pre character for dollar char fragment. " . into ( ) ,
2023-07-18 22:39:05 -04:00
) ) ) ) ;
}
}
}