11use crate :: error:: ParseError ;
2- use crate :: pc:: { AllowNoneIf , And , AndWithoutUndo , Chain , Errors , Parser , RcStringView , ToOption } ;
2+ use crate :: pc:: boxed:: boxed;
3+ use crate :: pc:: { And , AndWithoutUndo , Chain , Errors , Map , Parser , RcStringView , ToOption , Token } ;
34use crate :: specific:: core:: expression:: ws_expr_pos_p;
4- use crate :: specific:: pc_specific:: { keyword, whitespace} ;
5+ use crate :: specific:: pc_specific:: { keyword, opt_whitespace , whitespace} ;
56use crate :: specific:: { ExpressionPos , ExpressionTrait , Keyword } ;
67
78/// Finds the rightmost expression of a given type,
89/// so that it can be determined if it ended in parenthesis or not.
10+ #[ deprecated]
911pub trait ExtractExpression {
1012 fn to_expression ( & self ) -> & ExpressionPos ;
1113}
@@ -16,15 +18,21 @@ impl ExtractExpression for ExpressionPos {
1618 }
1719}
1820
21+ /// Parses an optional second expression that follows the first expression
22+ /// and a keyword.
23+ ///
24+ /// If the keyword is present, the second expression is mandatory.
25+ ///
26+ /// Example: `FOR I = 1 TO 100 [STEP 5]`
1927pub fn opt_second_expression_after_keyword < P > (
20- parser : P ,
28+ first_expression_parser : P ,
2129 keyword : Keyword ,
2230) -> impl Parser < RcStringView , Output = ( P :: Output , Option < ExpressionPos > ) >
2331where
2432 P : Parser < RcStringView > ,
2533 P :: Output : ExtractExpression ,
2634{
27- parser . chain (
35+ first_expression_parser . chain (
2836 move |first| {
2937 let first_expr = first. to_expression ( ) ;
3038 let is_paren = first_expr. is_parenthesis ( ) ;
@@ -38,8 +46,7 @@ fn parse_second(
3846 k : Keyword ,
3947 is_paren : bool ,
4048) -> impl Parser < RcStringView , Output = Option < ExpressionPos > > {
41- whitespace ( )
42- . allow_none_if ( is_paren)
49+ conditionally_opt_whitespace ( is_paren)
4350 . and_tuple ( keyword ( k) )
4451 . and_without_undo_keep_right ( ws_expr_pos_p ( ) . or_fail ( err ( k) ) )
4552 . to_option ( )
@@ -48,3 +55,24 @@ fn parse_second(
4855fn err ( keyword : Keyword ) -> ParseError {
4956 ParseError :: SyntaxError ( format ! ( "Expected: expression after {}" , keyword) )
5057}
58+
59+ /// Creates a parser that parses whitespace,
60+ /// conditionally allowing it to be missing.
61+ /// When [allow_none] is false, whitespace is mandatory.
62+ /// When [allow_none] is true, the whitespace can be missing.
63+ /// This is typically the case when the previously parsed
64+ /// token was a right side parenthesis.
65+ ///
66+ /// Examples
67+ ///
68+ /// * `(1 + 2)AND` no whitespace is required before `AND`
69+ /// * `1 + 2AND` the lack of whitespace before `AND` is an error
70+ pub ( super ) fn conditionally_opt_whitespace (
71+ allow_none : bool ,
72+ ) -> impl Parser < RcStringView , Output = Option < Token > > {
73+ if allow_none {
74+ boxed ( opt_whitespace ( ) )
75+ } else {
76+ boxed ( whitespace ( ) . map ( Some ) )
77+ }
78+ }
0 commit comments