2
2
3
3
use std:: {
4
4
collections:: { BTreeSet , VecDeque } ,
5
- fs, io, io:: prelude:: * ,
5
+ fs, io,
6
+ io:: prelude:: * ,
6
7
path:: { Path , PathBuf } ,
7
8
time:: { Duration , Instant } ,
8
9
} ;
9
- use gll:: runtime:: { MoreThanOne , ParseNodeKind , ParseNodeShape } ;
10
+
11
+ use derive_more:: Add ;
12
+ use gll:: {
13
+ forest:: { MoreThanOne , GrammarReflector } ,
14
+ parse_node:: ParseNodeShape ,
15
+ } ;
10
16
use rayon:: prelude:: * ;
11
17
use rust_grammar:: parse;
18
+ use serde:: { Deserialize , Serialize } ;
12
19
use structopt:: StructOpt ;
13
20
use walkdir:: WalkDir ;
14
- use derive_more:: Add ;
15
- use serde:: { Serialize , Deserialize } ;
16
21
17
22
#[ derive( Debug , Default , Serialize , Deserialize ) ]
18
23
struct Blacklist {
@@ -67,36 +72,44 @@ enum Command {
67
72
} ,
68
73
}
69
74
70
- type ModuleContentsResult < ' a , ' i > = parse:: ParseResult <
71
- ' a ,
72
- ' i ,
73
- proc_macro2:: TokenStream ,
74
- parse:: ModuleContents < ' a , ' i , proc_macro2:: TokenStream > ,
75
- > ;
75
+ type ModuleContentsResult = Result < ModuleContentsHandle , Error < proc_macro2:: Span > > ;
76
76
77
- type ModuleContentsHandle < ' a , ' i > = parse:: Handle <
78
- ' a ,
79
- ' i ,
77
+ type ModuleContentsHandle = parse:: OwnedHandle <
80
78
proc_macro2:: TokenStream ,
81
- parse:: ModuleContents < ' a , ' i , proc_macro2:: TokenStream > ,
79
+ parse:: ModuleContents < ' static , ' static , proc_macro2:: TokenStream > ,
82
80
> ;
83
81
82
+ enum Error < A > {
83
+ Lex ( proc_macro2:: LexError ) ,
84
+ Parse ( gll:: parser:: ParseError < A > ) ,
85
+ }
86
+
87
+ impl < A > From < proc_macro2:: LexError > for Error < A > {
88
+ fn from ( error : proc_macro2:: LexError ) -> Self {
89
+ Error :: Lex ( error)
90
+ }
91
+ }
92
+
93
+ impl < A > From < gll:: parser:: ParseError < A > > for Error < A > {
94
+ fn from ( error : gll:: parser:: ParseError < A > ) -> Self {
95
+ Error :: Parse ( error)
96
+ }
97
+ }
98
+
84
99
/// Read the contents of the file at the given `path`, parse it
85
100
/// using the `ModuleContents` rule, and pass the result to `f`.
86
- fn parse_file_with < R > ( path : & Path , f : impl FnOnce ( ModuleContentsResult < ' _ , ' _ > ) -> R ) -> R {
101
+ fn parse_file ( path : & Path ) -> ModuleContentsResult {
87
102
let src = fs:: read_to_string ( path) . unwrap ( ) ;
88
- match src. parse :: < proc_macro2:: TokenStream > ( ) {
89
- Ok ( tts) => parse:: ModuleContents :: parse_with ( tts, |_, result| f ( result) ) ,
90
- // FIXME(eddyb) provide more information in this error case.
91
- Err ( _) => f ( Err ( parse:: ParseError :: NoParse ) ) ,
92
- }
103
+ let tts = src. parse :: < proc_macro2:: TokenStream > ( ) ?;
104
+ let res = parse:: ModuleContents :: parse ( tts) ?;
105
+ Ok ( res)
93
106
}
94
107
95
108
/// Output the result of a single file to stderr,
96
109
/// optionally prefixed by a given `path`.
97
110
fn report_file_result (
98
111
path : Option < & Path > ,
99
- result : ModuleContentsResult < ' _ , ' _ > ,
112
+ result : & ModuleContentsResult ,
100
113
ambiguity_result : Result < ( ) , MoreThanOne > ,
101
114
duration : Option < Duration > ,
102
115
) {
@@ -111,60 +124,62 @@ fn report_file_result(
111
124
match ( result, ambiguity_result) {
112
125
( Ok ( _) , Ok ( _) ) => eprintln ! ( "OK" ) ,
113
126
( Ok ( _) , Err ( _) ) => eprintln ! ( "OK (ambiguous)" ) ,
114
- ( Err ( parse :: ParseError :: TooShort ( handle ) ) , _) => {
127
+ ( Err ( Error :: Parse ( error ) ) , _) => {
115
128
eprint ! ( "FAIL after " ) ;
116
129
117
130
#[ cfg( procmacro2_semver_exempt) ]
118
131
{
119
132
// HACK(eddyb) work around `proc-macro2` `Span` printing limitation
120
- let end_location = handle . source_info ( ) . end . end ( ) ;
133
+ let end_location = error . at . end ( ) ;
121
134
eprintln ! ( "{}:{}" , end_location. line, end_location. column) ;
122
135
}
123
136
#[ cfg( not( procmacro2_semver_exempt) ) ]
124
137
{
125
- let _ = handle;
126
138
eprintln ! (
127
139
"(missing location information; \
128
140
set `RUSTFLAGS='--cfg procmacro2_semver_exempt'`)"
129
141
) ;
130
142
}
143
+ eprintln ! ( "Expected: {:?}" , error. expected) ;
131
144
}
132
- ( Err ( parse :: ParseError :: NoParse ) , _) => eprintln ! ( "FAIL (lexer error?)" ) ,
145
+ ( Err ( Error :: Lex ( e ) ) , _) => eprintln ! ( "FAIL ({:?})" , e ) ,
133
146
}
134
147
}
135
148
136
- fn ambiguity_check ( handle : ModuleContentsHandle < ' _ , ' _ > ) -> Result < ( ) , MoreThanOne > {
137
- let sppf = & handle. parser . sppf ;
149
+ fn ambiguity_check ( handle : & ModuleContentsHandle ) -> Result < ( ) , MoreThanOne > {
150
+ handle. with ( |handle| {
151
+ let forest = & handle. forest ;
138
152
139
- let mut queue = VecDeque :: new ( ) ;
140
- queue. push_back ( handle. node ) ;
141
- let mut seen: BTreeSet < _ > = queue. iter ( ) . cloned ( ) . collect ( ) ;
153
+ let mut queue = VecDeque :: new ( ) ;
154
+ queue. push_back ( handle. node ) ;
155
+ let mut seen: BTreeSet < _ > = queue. iter ( ) . cloned ( ) . collect ( ) ;
142
156
143
- while let Some ( source) = queue. pop_front ( ) {
144
- let mut add_children = |children : & [ _ ] | {
145
- for & child in children {
146
- if seen. insert ( child) {
147
- queue. push_back ( child) ;
157
+ while let Some ( source) = queue. pop_front ( ) {
158
+ let mut add_children = |children : & [ _ ] | {
159
+ for & child in children {
160
+ if seen. insert ( child) {
161
+ queue. push_back ( child) ;
162
+ }
148
163
}
149
- }
150
- } ;
151
- match source. kind . shape ( ) {
152
- ParseNodeShape :: Opaque => { }
153
- ParseNodeShape :: Alias ( _) => add_children ( & [ source. unpack_alias ( ) ] ) ,
154
- ParseNodeShape :: Opt ( _) => {
155
- if let Some ( child) = source. unpack_opt ( ) {
156
- add_children ( & [ child] ) ;
164
+ } ;
165
+ match forest. grammar . parse_node_shape ( source. kind ) {
166
+ ParseNodeShape :: Opaque => { }
167
+ ParseNodeShape :: Alias ( _) => add_children ( & [ forest. unpack_alias ( source) ] ) ,
168
+ ParseNodeShape :: Opt ( _) => {
169
+ if let Some ( child) = forest. unpack_opt ( source) {
170
+ add_children ( & [ child] ) ;
171
+ }
172
+ }
173
+ ParseNodeShape :: Choice => add_children ( & [ forest. one_choice ( source) ?] ) ,
174
+ ParseNodeShape :: Split ( ..) => {
175
+ let ( left, right) = forest. one_split ( source) ?;
176
+ add_children ( & [ left, right] )
157
177
}
158
- }
159
- ParseNodeShape :: Choice => add_children ( & [ sppf. one_choice ( source) ?] ) ,
160
- ParseNodeShape :: Split ( ..) => {
161
- let ( left, right) = sppf. one_split ( source) ?;
162
- add_children ( & [ left, right] )
163
178
}
164
179
}
165
- }
166
180
167
- Ok ( ( ) )
181
+ Ok ( ( ) )
182
+ } )
168
183
}
169
184
170
185
#[ derive( Debug , Default , Add ) ]
@@ -199,30 +214,29 @@ fn process(file: walkdir::DirEntry, verbose: bool) -> ParseResult {
199
214
let mut stdout = io:: stdout ( ) ;
200
215
let path = file. into_path ( ) ;
201
216
202
- parse_file_with ( & path, |result| {
203
- let mut ambiguity_result = Ok ( ( ) ) ;
204
- let start = Instant :: now ( ) ;
205
- let status = match result {
206
- Ok ( handle) => {
207
- ambiguity_result = ambiguity_check ( handle) ;
208
- if ambiguity_result. is_ok ( ) {
209
- ParseResult :: Unambiguous
210
- } else {
211
- ParseResult :: Ambiguous
212
- }
217
+ let result = parse_file ( & path) ;
218
+ let mut ambiguity_result = Ok ( ( ) ) ;
219
+ let start = Instant :: now ( ) ;
220
+ let status = match & result {
221
+ Ok ( handle) => {
222
+ ambiguity_result = ambiguity_check ( handle) ;
223
+ if ambiguity_result. is_ok ( ) {
224
+ ParseResult :: Unambiguous
225
+ } else {
226
+ ParseResult :: Ambiguous
213
227
}
214
- Err ( parse:: ParseError :: TooShort ( _) ) => ParseResult :: Partial ,
215
- Err ( parse:: ParseError :: NoParse ) => ParseResult :: Error ,
216
- } ;
217
- let duration = start. elapsed ( ) ;
218
- if verbose {
219
- report_file_result ( Some ( & path) , result, ambiguity_result, Some ( duration) ) ;
220
- } else {
221
- print ! ( "{}" , status. compact_display( ) ) ;
222
- stdout. flush ( ) . unwrap ( ) ;
223
228
}
224
- status
225
- } )
229
+ Err ( Error :: Parse ( _) ) => ParseResult :: Partial ,
230
+ Err ( Error :: Lex ( _) ) => ParseResult :: Error ,
231
+ } ;
232
+ let duration = start. elapsed ( ) ;
233
+ if verbose {
234
+ report_file_result ( Some ( & path) , & result, ambiguity_result, Some ( duration) ) ;
235
+ } else {
236
+ print ! ( "{}" , status. compact_display( ) ) ;
237
+ stdout. flush ( ) . unwrap ( ) ;
238
+ }
239
+ status
226
240
}
227
241
228
242
fn print_statistics ( counters : Counters ) {
@@ -253,24 +267,21 @@ fn main() -> Result<(), failure::Error> {
253
267
file,
254
268
} => {
255
269
// Not much to do, try to parse the file and report the result.
256
- parse_file_with ( & file, |result| {
257
- let mut ambiguity_result = Ok ( ( ) ) ;
258
- match result {
259
- Ok ( handle) | Err ( parse:: ParseError :: TooShort ( handle) ) => {
260
- ambiguity_result = ambiguity_check ( handle) ;
261
-
262
- if let Some ( out_path) = graphviz_forest {
263
- handle
264
- . parser
265
- . sppf
266
- . dump_graphviz ( & mut fs:: File :: create ( out_path) . unwrap ( ) )
267
- . unwrap ( ) ;
268
- }
269
- }
270
- Err ( parse:: ParseError :: NoParse ) => { }
270
+ let result = parse_file ( & file) ;
271
+ let mut ambiguity_result = Ok ( ( ) ) ;
272
+ if let Ok ( handle) = & result {
273
+ ambiguity_result = ambiguity_check ( handle) ;
274
+
275
+ if let Some ( out_path) = graphviz_forest {
276
+ handle. with ( |handle| {
277
+ handle
278
+ . forest
279
+ . dump_graphviz ( & mut fs:: File :: create ( out_path) . unwrap ( ) )
280
+ . unwrap ( ) ;
281
+ } )
271
282
}
272
- report_file_result ( None , result , ambiguity_result , None ) ;
273
- } ) ;
283
+ }
284
+ report_file_result ( None , & result , ambiguity_result , None ) ;
274
285
}
275
286
Command :: Dir { verbose, dir } => {
276
287
let config = Config :: load ( ) ?;
@@ -288,27 +299,24 @@ fn main() -> Result<(), failure::Error> {
288
299
let counters: Counters = files
289
300
. par_bridge ( )
290
301
. map ( |f| process ( f, verbose) )
291
- . fold (
292
- Counters :: default,
293
- |mut acc, x| {
294
- acc. total_count += 1 ;
295
- match x {
296
- ParseResult :: Ambiguous => {
297
- acc. ambiguous_count += 1 ;
298
- }
299
- ParseResult :: Unambiguous => {
300
- acc. unambiguous_count += 1 ;
301
- }
302
- ParseResult :: Partial => {
303
- acc. too_short_count += 1 ;
304
- }
305
- ParseResult :: Error => {
306
- acc. no_parse_count += 1 ;
307
- }
308
- } ;
309
- acc
310
- } ,
311
- )
302
+ . fold ( Counters :: default, |mut acc, x| {
303
+ acc. total_count += 1 ;
304
+ match x {
305
+ ParseResult :: Ambiguous => {
306
+ acc. ambiguous_count += 1 ;
307
+ }
308
+ ParseResult :: Unambiguous => {
309
+ acc. unambiguous_count += 1 ;
310
+ }
311
+ ParseResult :: Partial => {
312
+ acc. too_short_count += 1 ;
313
+ }
314
+ ParseResult :: Error => {
315
+ acc. no_parse_count += 1 ;
316
+ }
317
+ } ;
318
+ acc
319
+ } )
312
320
. reduce ( Counters :: default, |a, b| a + b) ;
313
321
314
322
// We're done, time to print out stats!
0 commit comments