11use rusty_common:: Positioned ;
2- use rusty_pc:: and:: KeepRightCombiner ;
2+ use rusty_pc:: and:: KeepLeftCombiner ;
33use rusty_pc:: * ;
44
55use crate :: core:: statement:: statement_p;
66use crate :: core:: statement_separator:: { comment_separator, common_separator} ;
77use crate :: input:: StringView ;
88use crate :: pc_specific:: * ;
99use crate :: tokens:: { TokenMatcher , peek_token} ;
10- use crate :: * ;
10+ use crate :: { Keyword , ParserError , Statement , StatementPos , Statements } ;
1111
1212macro_rules! zero_or_more_statements {
1313 ( $exit: expr, ParserError :: $err: ident) => {
@@ -31,18 +31,17 @@ pub fn zero_or_more_statements_p(
3131 exit_keywords : & [ Keyword ] ,
3232 custom_err : Option < ParserError > ,
3333) -> impl Parser < StringView , Output = Statements , Error = ParserError > {
34- one_statement_p ( exit_keywords, custom_err)
35- . zero_or_more ( )
36- // Initialize the context before the loop of "zero_or_more" starts.
37- // The context indicates if the previous statement was a comment.
38- . init_context ( false )
34+ // parse the first separator
35+ common_separator ( )
36+ . or_expected ( "end-of-statement" )
37+ . and_keep_right ( one_statement_p ( exit_keywords, custom_err) . zero_or_more ( ) )
3938}
4039
4140/// Either parses one statement or detects the exit keyword and stops parsing.
4241fn one_statement_p (
4342 exit_keywords : & [ Keyword ] ,
4443 custom_err : Option < ParserError > ,
45- ) -> impl Parser < StringView , bool , Output = StatementPos , Error = ParserError > {
44+ ) -> impl Parser < StringView , Output = StatementPos , Error = ParserError > {
4645 one_statement_or_exit_keyword_p ( exit_keywords, custom_err) . and_then (
4746 |statement_or_exit_keyword| match statement_or_exit_keyword {
4847 // we parsed a statement, return it
@@ -60,40 +59,12 @@ fn one_statement_p(
6059fn one_statement_or_exit_keyword_p (
6160 exit_keywords : & [ Keyword ] ,
6261 custom_err : Option < ParserError > ,
63- ) -> impl Parser < StringView , bool , Output = StatementOrExitKeyword , Error = ParserError > {
64- ThenWithLeftParser :: new (
65- // must parse the separator
66- ctx_demand_separator_p ( ) ,
67- // must parse the statement or peek the exit keyword
68- find_exit_keyword_or_demand_statement_p ( exit_keywords, custom_err) ,
69- // populate the context of the separator for the next iteration
70- is_comment,
71- // keep only the statement or the peeked exit keyword
72- KeepRightCombiner ,
73- )
74- }
75-
76- fn is_comment ( statement_or_exit_keyword : & StatementOrExitKeyword ) -> bool {
77- matches ! (
78- statement_or_exit_keyword,
79- StatementOrExitKeyword :: Statement ( Positioned {
80- element: Statement :: Comment ( _) ,
81- ..
82- } )
83- )
84- }
85-
86- /// A statement separator that is aware if the previously parsed statement
87- /// was a comment or not.
88- fn ctx_demand_separator_p ( ) -> impl Parser < StringView , bool , Output = ( ) , Error = ParserError > {
89- // TODO consolidate the two separate separator functions, they are almost never used elsewhere
90- IifParser :: new (
91- // last statement was comment
92- comment_separator ( ) ,
93- // last statement was not comment
94- common_separator ( ) ,
62+ ) -> impl Parser < StringView , Output = StatementOrExitKeyword , Error = ParserError > {
63+ // must parse the statement or peek the exit keyword
64+ find_exit_keyword_or_demand_statement_p ( exit_keywords, custom_err) . then_with_in_context (
65+ ctx_demand_separator_p ( ) . map_ctx ( Context :: from) ,
66+ KeepLeftCombiner ,
9567 )
96- . or_expected ( "end-of-statement" )
9768}
9869
9970fn find_exit_keyword_or_demand_statement_p (
@@ -145,8 +116,42 @@ fn demand_statement_p()
145116 . or_expected ( "statement" )
146117}
147118
119+ /// A statement separator that is aware if the previously parsed statement
120+ /// was a comment or not.
121+ fn ctx_demand_separator_p ( ) -> impl Parser < StringView , Context , Output = ( ) , Error = ParserError > {
122+ // TODO consolidate the two separate separator functions, they are almost never used elsewhere
123+ ctx_parser ( )
124+ . map ( |ctx : Context | match ctx {
125+ Context :: Statement => common_separator ( ) . boxed ( ) ,
126+ Context :: Comment => comment_separator ( ) . boxed ( ) ,
127+ Context :: ExitKeyword => supplier ( || ( ) ) . boxed ( ) ,
128+ } )
129+ . flatten ( )
130+ . or_expected ( "end-of-statement" )
131+ }
132+
148133#[ allow( clippy:: large_enum_variant) ]
149134enum StatementOrExitKeyword {
150135 Statement ( StatementPos ) ,
151136 ExitKeyword ,
152137}
138+
139+ #[ derive( Clone , Copy ) ]
140+ enum Context {
141+ Statement ,
142+ Comment ,
143+ ExitKeyword ,
144+ }
145+
146+ impl Context {
147+ fn from ( s : & StatementOrExitKeyword ) -> Self {
148+ match s {
149+ StatementOrExitKeyword :: Statement ( Positioned {
150+ element : Statement :: Comment ( _) ,
151+ ..
152+ } ) => Self :: Comment ,
153+ StatementOrExitKeyword :: Statement ( _) => Self :: Statement ,
154+ StatementOrExitKeyword :: ExitKeyword => Self :: ExitKeyword ,
155+ }
156+ }
157+ }
0 commit comments