1
- use pear:: { parse_error, parsers:: * } ;
2
- use pear:: combinators:: * ;
3
- use pear:: macros:: { parse, parser, switch} ;
4
- use pear:: input:: { Pear , Text } ;
1
+ use std:: borrow:: Cow ;
5
2
6
3
use crate :: value:: { Value , Dict , escape:: escape} ;
7
4
8
- type Input < ' a > = Pear < Text < ' a > > ;
9
- type Result < ' a , T > = pear:: input:: Result < T , Input < ' a > > ;
5
+ use super :: Empty ;
10
6
11
- #[ inline( always) ]
12
- fn is_whitespace ( & byte: & char ) -> bool {
13
- byte. is_ascii_whitespace ( )
7
+ struct Parser < ' a > {
8
+ cursor : & ' a str ,
14
9
}
15
10
16
- #[ inline( always) ]
17
- fn is_not_separator ( & byte: & char ) -> bool {
18
- !matches ! ( byte, ',' | '{' | '}' | '[' | ']' )
11
+ #[ derive( Debug ) ]
12
+ #[ allow( dead_code) ]
13
+ pub enum Error {
14
+ Expected ( Value ) ,
15
+ Escape ( super :: escape:: Error ) ,
16
+ Eof ,
19
17
}
20
18
21
- // TODO: Be more permissive here?
22
- #[ inline( always) ]
23
- fn is_ident_char ( & byte: & char ) -> bool {
24
- byte. is_ascii_alphanumeric ( ) || byte == '_' || byte == '-'
25
- }
19
+ type Result < ' a , T > = std:: result:: Result < T , Error > ;
26
20
27
- #[ parser]
28
- fn string < ' a > ( input : & mut Input < ' a > ) -> Result < ' a , String > {
29
- let mut is_escaped = false ;
30
- let str_char = |& c: & char | -> bool {
31
- if is_escaped { is_escaped = false ; return true ; }
32
- if c == '\\' { is_escaped = true ; return true ; }
33
- c != '"'
34
- } ;
21
+ impl < ' a > Parser < ' a > {
22
+ fn new ( cursor : & ' a str ) -> Self {
23
+ Self { cursor }
24
+ }
35
25
36
- let inner = ( eat ( '"' ) ?, take_while ( str_char) ?, eat ( '"' ) ?) . 1 ;
37
- match escape ( inner) {
38
- Ok ( string) => string. into_owned ( ) ,
39
- Err ( e) => parse_error ! ( "invalid string: {}" , e) ?,
26
+ fn peek ( & self , c : char ) -> bool {
27
+ self . cursor . chars ( ) . next ( ) == Some ( c)
40
28
}
41
- }
42
29
43
- #[ parser]
44
- fn key < ' a > ( input : & mut Input < ' a > ) -> Result < ' a , String > {
45
- switch ! {
46
- peek( '"' ) => Ok ( string( ) ?) ,
47
- _ => Ok ( take_some_while( is_ident_char) ?. to_string( ) )
30
+ fn peek_next ( & self ) -> Option < char > {
31
+ self . cursor . chars ( ) . next ( )
48
32
}
49
- }
50
33
51
- #[ parser]
52
- fn key_value < ' a > ( input : & mut Input < ' a > ) -> Result < ' a , ( String , Value ) > {
53
- let key = ( surrounded ( key, is_whitespace) ?, eat ( '=' ) ?) . 0 ;
54
- ( key, surrounded ( value, is_whitespace) ?)
55
- }
34
+ #[ inline]
35
+ fn eat_if < F > ( & mut self , f : F ) -> Option < char >
36
+ where F : FnOnce ( & char ) -> bool ,
37
+ {
38
+ match self . cursor . chars ( ) . next ( ) {
39
+ Some ( ch) if f ( & ch) => {
40
+ self . cursor = & self . cursor [ ch. len_utf8 ( ) ..] ;
41
+ Some ( ch)
42
+ }
43
+ _ => None ,
44
+ }
45
+ }
56
46
57
- # [ parser ]
58
- fn array < ' a > ( input : & mut Input < ' a > ) -> Result < ' a , Vec < Value > > {
59
- Ok ( delimited_collect ( '[' , value , ',' , ']' ) ? )
60
- }
47
+ fn eat ( & mut self , c : char ) -> Result < char > {
48
+ self . eat_if ( | & ch| ch == c )
49
+ . ok_or_else ( || Error :: Expected ( Value :: from ( c ) ) )
50
+ }
61
51
62
- #[ parser]
63
- fn dict < ' a > ( input : & mut Input < ' a > ) -> Result < ' a , Dict > {
64
- Ok ( delimited_collect ( '{' , key_value, ',' , '}' ) ?)
65
- }
52
+ fn eat_any ( & mut self ) -> Result < char > {
53
+ self . eat_if ( |_| true ) . ok_or ( Error :: Eof )
54
+ }
66
55
67
- #[ parser]
68
- fn value < ' a > ( input : & mut Input < ' a > ) -> Result < ' a , Value > {
69
- skip_while ( is_whitespace) ?;
70
- let val = switch ! {
71
- eat_slice( "true" ) => Value :: from( true ) ,
72
- eat_slice( "false" ) => Value :: from( false ) ,
73
- peek( '{' ) => Value :: from( dict( ) ?) ,
74
- peek( '[' ) => Value :: from( array( ) ?) ,
75
- peek( '"' ) => Value :: from( string( ) ?) ,
76
- peek( '\'' ) => Value :: from( ( eat( '\'' ) ?, eat_any( ) ?, eat( '\'' ) ?) . 1 ) ,
77
- _ => {
78
- let value = take_while( is_not_separator) ?. trim( ) ;
79
- if value. contains( '.' ) {
80
- if let Ok ( float) = value. parse:: <f64 >( ) {
81
- return Ok ( Value :: from( float) ) ;
82
- }
56
+ fn skip_whitespace ( & mut self ) {
57
+ self . cursor = self . cursor . trim_start ( ) ;
58
+ }
59
+
60
+ fn substr < F > ( & mut self , f : F ) -> Result < & ' a str >
61
+ where F : FnMut ( & char ) -> bool ,
62
+ {
63
+ let len = self . cursor . chars ( )
64
+ . take_while ( f)
65
+ . map ( |c| c. len_utf8 ( ) )
66
+ . sum ( ) ;
67
+
68
+ let ( substring, rest) = self . cursor . split_at ( len) ;
69
+ self . cursor = rest;
70
+ Ok ( substring)
71
+ }
72
+
73
+ fn quoted_char ( & mut self ) -> Result < char > {
74
+ self . eat ( '\'' ) ?;
75
+ let ch = self . eat_any ( ) ?;
76
+ self . eat ( '\'' ) ?;
77
+ Ok ( ch)
78
+ }
79
+
80
+ fn quoted_str ( & mut self ) -> Result < Cow < ' a , str > > {
81
+ self . eat ( '"' ) ?;
82
+
83
+ let mut is_escaped = false ;
84
+ let inner = self . substr ( |& c: & char | -> bool {
85
+ if is_escaped { is_escaped = false ; return true ; }
86
+ if c == '\\' { is_escaped = true ; return true ; }
87
+ c != '"'
88
+ } ) ?;
89
+
90
+ self . eat ( '"' ) ?;
91
+ escape ( inner) . map_err ( Error :: Escape )
92
+ }
93
+
94
+ fn key ( & mut self ) -> Result < Cow < ' a , str > > {
95
+ #[ inline( always) ]
96
+ fn is_ident_char ( & byte: & char ) -> bool {
97
+ byte. is_ascii_alphanumeric ( ) || byte == '_' || byte == '-'
98
+ }
99
+
100
+ if self . peek ( '"' ) {
101
+ self . quoted_str ( )
102
+ } else {
103
+ self . substr ( is_ident_char) . map ( Cow :: Borrowed )
104
+ }
105
+ }
106
+
107
+ fn dict ( & mut self ) -> Result < Dict > {
108
+ self . eat ( '{' ) ?;
109
+
110
+ let mut dict = Dict :: new ( ) ;
111
+ loop {
112
+ self . skip_whitespace ( ) ;
113
+ if self . eat ( '}' ) . is_ok ( ) {
114
+ break ;
83
115
}
84
116
85
- if let Ok ( int) = value. parse:: <usize >( ) {
86
- Value :: from( int)
87
- } else if let Ok ( int) = value. parse:: <isize >( ) {
88
- Value :: from( int)
89
- } else {
90
- Value :: from( value. to_string( ) )
117
+ let key = self . key ( ) ?;
118
+ self . skip_whitespace ( ) ;
119
+ self . eat ( '=' ) ?;
120
+ self . skip_whitespace ( ) ;
121
+ let value = self . value ( ) ?;
122
+ dict. insert ( key. to_string ( ) , value) ;
123
+
124
+ self . skip_whitespace ( ) ;
125
+ let _ = self . eat ( ',' ) ;
126
+ }
127
+
128
+ Ok ( dict)
129
+ }
130
+
131
+ fn array ( & mut self ) -> Result < Vec < Value > > {
132
+ self . eat ( '[' ) ?;
133
+ let mut values = Vec :: new ( ) ;
134
+
135
+ loop {
136
+ self . skip_whitespace ( ) ;
137
+ if self . eat ( ']' ) . is_ok ( ) {
138
+ break ;
91
139
}
140
+
141
+ values. push ( self . value ( ) ?) ;
142
+ self . skip_whitespace ( ) ;
143
+ let _ = self . eat ( ',' ) ;
144
+ }
145
+
146
+ Ok ( values)
147
+ }
148
+
149
+ fn value ( & mut self ) -> Result < Value > {
150
+ #[ inline( always) ]
151
+ fn is_not_separator ( & byte: & char ) -> bool {
152
+ !matches ! ( byte, ',' | '{' | '}' | '[' | ']' )
92
153
}
93
- } ;
94
154
95
- skip_while ( is_whitespace) ?;
96
- val
155
+ let value = match self . peek_next ( ) {
156
+ Some ( '"' ) => Value :: from ( self . quoted_str ( ) ?. to_string ( ) ) ,
157
+ Some ( '\'' ) => Value :: from ( self . quoted_char ( ) ?) ,
158
+ Some ( '[' ) => Value :: from ( self . array ( ) ?) ,
159
+ Some ( '{' ) => Value :: from ( self . dict ( ) ?) ,
160
+ Some ( _) => match self . substr ( is_not_separator) ?. trim ( ) {
161
+ "true" => Value :: from ( true ) ,
162
+ "false" => Value :: from ( false ) ,
163
+ value => {
164
+ if value. contains ( '.' ) {
165
+ if let Ok ( float) = value. parse :: < f64 > ( ) {
166
+ Value :: from ( float)
167
+ } else {
168
+ Value :: from ( value. to_string ( ) )
169
+ }
170
+ } else if let Ok ( int) = value. parse :: < usize > ( ) {
171
+ Value :: from ( int)
172
+ } else if let Ok ( int) = value. parse :: < isize > ( ) {
173
+ Value :: from ( int)
174
+ } else {
175
+ Value :: from ( value. to_string ( ) )
176
+ }
177
+ }
178
+ } ,
179
+ None => Value :: from ( Empty :: Unit ) ,
180
+ } ;
181
+
182
+ self . skip_whitespace ( ) ;
183
+ Ok ( value)
184
+ }
97
185
}
98
186
99
187
impl std:: str:: FromStr for Value {
100
188
type Err = std:: convert:: Infallible ;
101
189
102
190
fn from_str ( s : & str ) -> std:: result:: Result < Self , std:: convert:: Infallible > {
103
- Ok ( parse ! ( value: Text :: from( s) )
104
- . unwrap_or_else ( |_| Value :: from ( s. to_string ( ) ) ) )
191
+ let mut parser = Parser :: new ( s. trim ( ) ) ;
192
+ match parser. value ( ) {
193
+ Ok ( value) => Ok ( value) ,
194
+ Err ( _) => Ok ( Value :: from ( s) ) ,
195
+ }
105
196
}
106
197
}
107
198
@@ -113,7 +204,9 @@ mod tests {
113
204
macro_rules! assert_parse_eq {
114
205
( $string: expr => $expected: expr) => ( {
115
206
let expected = Value :: from( $expected) ;
116
- let actual: Value = $string. parse( ) . unwrap( ) ;
207
+ let actual: Value = $string. parse( )
208
+ . unwrap_or_else( |e| panic!( "failed to parse {:?}: {:?}" , $string, e) ) ;
209
+
117
210
assert_eq!( actual, expected, "got {:?}, expected {:?}" , actual, expected) ;
118
211
} ) ;
119
212
@@ -168,7 +261,10 @@ mod tests {
168
261
169
262
assert_parse_eq ! {
170
263
"[1,2,3]" => vec![ 1u8 , 2u8 , 3u8 ] ,
264
+ "[ 1 , 2 ,3]" => vec![ 1u8 , 2u8 , 3u8 ] ,
265
+ " [ 1 , 2 , 3 ] " => vec![ 1u8 , 2u8 , 3u8 ] ,
171
266
"{a=b}" => map![ "a" => "b" ] ,
267
+ " { a = b } " => map![ "a" => "b" ] ,
172
268
"{\" a\" =b}" => map![ "a" => "b" ] ,
173
269
"{\" a.b.c\" =b}" => map![ "a.b.c" => "b" ] ,
174
270
"{a=1,b=3}" => map![ "a" => 1u8 , "b" => 3u8 ] ,
0 commit comments