3030mod combined;
3131mod date;
3232mod ordinal;
33+ mod primitive;
3334mod relative;
3435mod time;
3536mod weekday;
3637
3738mod epoch {
3839 use winnow:: { combinator:: preceded, ModalResult , Parser } ;
3940
40- use super :: { dec_int, s} ;
41+ use super :: primitive:: { dec_int, s} ;
42+
4143 pub fn parse ( input : & mut & str ) -> ModalResult < i32 > {
4244 s ( preceded ( "@" , dec_int) ) . parse_next ( input)
4345 }
4446}
4547
4648mod timezone {
47- use super :: time;
4849 use winnow:: ModalResult ;
4950
51+ use super :: time;
52+
5053 pub ( crate ) fn parse ( input : & mut & str ) -> ModalResult < time:: Offset > {
5154 time:: timezone ( input)
5255 }
@@ -55,12 +58,11 @@ mod timezone {
5558use chrono:: NaiveDate ;
5659use chrono:: { DateTime , Datelike , FixedOffset , TimeZone , Timelike } ;
5760
61+ use primitive:: space;
5862use winnow:: {
59- ascii:: { digit1, multispace0} ,
60- combinator:: { alt, delimited, not, opt, peek, preceded, repeat, separated, trace} ,
61- error:: { AddContext , ContextError , ErrMode , ParserError , StrContext , StrContextValue } ,
62- stream:: { AsChar , Stream } ,
63- token:: { none_of, one_of, take_while} ,
63+ combinator:: { alt, trace} ,
64+ error:: { AddContext , ContextError , ErrMode , StrContext , StrContextValue } ,
65+ stream:: Stream ,
6466 ModalResult , Parser ,
6567} ;
6668
@@ -78,121 +80,6 @@ pub enum Item {
7880 TimeZone ( time:: Offset ) ,
7981}
8082
81- /// Allow spaces and comments before a parser
82- ///
83- /// Every token parser should be wrapped in this to allow spaces and comments.
84- /// It is only preceding, because that allows us to check mandatory whitespace
85- /// after running the parser.
86- fn s < ' a , O , E > ( p : impl Parser < & ' a str , O , E > ) -> impl Parser < & ' a str , O , E >
87- where
88- E : ParserError < & ' a str > ,
89- {
90- preceded ( space, p)
91- }
92-
93- /// Parse the space in-between tokens
94- ///
95- /// You probably want to use the [`s`] combinator instead.
96- fn space < ' a , E > ( input : & mut & ' a str ) -> winnow:: Result < ( ) , E >
97- where
98- E : ParserError < & ' a str > ,
99- {
100- separated ( 0 .., multispace0, alt ( ( comment, ignored_hyphen_or_plus) ) ) . parse_next ( input)
101- }
102-
103- /// A hyphen or plus is ignored when it is not followed by a digit
104- ///
105- /// This includes being followed by a comment! Compare these inputs:
106- /// ```txt
107- /// - 12 weeks
108- /// - (comment) 12 weeks
109- /// ```
110- /// The last comment should be ignored.
111- ///
112- /// The plus is undocumented, but it seems to be ignored.
113- fn ignored_hyphen_or_plus < ' a , E > ( input : & mut & ' a str ) -> winnow:: Result < ( ) , E >
114- where
115- E : ParserError < & ' a str > ,
116- {
117- (
118- alt ( ( '-' , '+' ) ) ,
119- multispace0,
120- peek ( not ( take_while ( 1 , AsChar :: is_dec_digit) ) ) ,
121- )
122- . void ( )
123- . parse_next ( input)
124- }
125-
126- /// Parse a comment
127- ///
128- /// A comment is given between parentheses, which must be balanced. Any other
129- /// tokens can be within the comment.
130- fn comment < ' a , E > ( input : & mut & ' a str ) -> winnow:: Result < ( ) , E >
131- where
132- E : ParserError < & ' a str > ,
133- {
134- delimited (
135- '(' ,
136- repeat ( 0 .., alt ( ( none_of ( [ '(' , ')' ] ) . void ( ) , comment) ) ) ,
137- ')' ,
138- )
139- . parse_next ( input)
140- }
141-
142- /// Parse a signed decimal integer.
143- ///
144- /// Rationale for not using `winnow::ascii::dec_int`: When upgrading winnow from
145- /// 0.5 to 0.7, we discovered that `winnow::ascii::dec_int` now accepts only the
146- /// following two forms:
147- ///
148- /// - 0
149- /// - [+-]?[1-9][0-9]*
150- ///
151- /// Inputs like [+-]?0[0-9]* (e.g., `+012`) are therefore rejected. We provide a
152- /// custom implementation to support such zero-prefixed integers.
153- fn dec_int < ' a , E > ( input : & mut & ' a str ) -> winnow:: Result < i32 , E >
154- where
155- E : ParserError < & ' a str > ,
156- {
157- ( opt ( one_of ( [ '+' , '-' ] ) ) , digit1)
158- . void ( )
159- . take ( )
160- . verify_map ( |s : & str | s. parse ( ) . ok ( ) )
161- . parse_next ( input)
162- }
163-
164- /// Parse an unsigned decimal integer.
165- ///
166- /// See the rationale for `dec_int` for why we don't use
167- /// `winnow::ascii::dec_uint`.
168- fn dec_uint < ' a , E > ( input : & mut & ' a str ) -> winnow:: Result < u32 , E >
169- where
170- E : ParserError < & ' a str > ,
171- {
172- digit1
173- . void ( )
174- . take ( )
175- . verify_map ( |s : & str | s. parse ( ) . ok ( ) )
176- . parse_next ( input)
177- }
178-
179- /// Parse a float number.
180- ///
181- /// Rationale for not using `winnow::ascii::float`: the `float` parser provided
182- /// by winnow accepts E-notation numbers (e.g., `1.23e4`), whereas GNU date
183- /// rejects such numbers. To remain compatible with GNU date, we provide a
184- /// custom implementation that only accepts inputs like [+-]?[0-9]+(\.[0-9]+)?.
185- fn float < ' a , E > ( input : & mut & ' a str ) -> winnow:: Result < f64 , E >
186- where
187- E : ParserError < & ' a str > ,
188- {
189- ( opt ( one_of ( [ '+' , '-' ] ) ) , digit1, opt ( preceded ( '.' , digit1) ) )
190- . void ( )
191- . take ( )
192- . verify_map ( |s : & str | s. parse ( ) . ok ( ) )
193- . parse_next ( input)
194- }
195-
19683// Parse an item
19784pub fn parse_one ( input : & mut & str ) -> ModalResult < Item > {
19885 trace (
0 commit comments