@@ -19,6 +19,19 @@ pub struct SpannedDiagnosticFormatter<'a> {
1919 nlc : OnceCell < NewlineCache > ,
2020}
2121
22+ /// Implements a `pushln` convenience function to `String`
23+ trait PushLine {
24+ /// Appends a given string slice and a newline to the end of this `String`.
25+ fn pushln < S : AsRef < str > > ( & mut self , s : S ) ;
26+ }
27+
28+ impl PushLine for String {
29+ fn pushln < S : AsRef < str > > ( & mut self , s : S ) {
30+ self . push_str ( s. as_ref ( ) ) ;
31+ self . push ( '\n' ) ;
32+ }
33+ }
34+
2235fn pidx_prods_data < StorageT > ( ast : & GrammarAST , pidx : PIdx < StorageT > ) -> ( Vec < String > , Vec < Span > )
2336where
2437 usize : num_traits:: AsPrimitive < StorageT > ,
@@ -237,16 +250,19 @@ impl<'a> SpannedDiagnosticFormatter<'a> {
237250 out
238251 }
239252
240- pub fn handle_conflicts < LexerTypesT : LexerTypes < StorageT = u32 > > (
253+ pub fn format_conflicts < LexerTypesT > (
241254 & self ,
242- grm : & YaccGrammar ,
255+ grm : & YaccGrammar < LexerTypesT :: StorageT > ,
243256 ast : & GrammarAST ,
244257 c : & Conflicts < LexerTypesT :: StorageT > ,
245258 _sgraph : & lrtable:: StateGraph < LexerTypesT :: StorageT > ,
246259 _stable : & lrtable:: StateTable < LexerTypesT :: StorageT > ,
247- ) where
260+ ) -> String
261+ where
262+ LexerTypesT : LexerTypes ,
248263 usize : num_traits:: AsPrimitive < LexerTypesT :: StorageT > ,
249264 {
265+ let mut out = String :: new ( ) ;
250266 for ( t_idx, r1_prod_idx, r2_prod_idx, _st_idx) in c. rr_conflicts ( ) {
251267 let ( _r1_prod_names, _r1_prod_spans) = pidx_prods_data ( ast, * r1_prod_idx) ;
252268 let ( _r2_prod_names, _r2_prod_spans) = pidx_prods_data ( ast, * r2_prod_idx) ;
@@ -259,26 +275,19 @@ impl<'a> SpannedDiagnosticFormatter<'a> {
259275 let r1_name = grm. rule_name_str ( r1_rule_idx) ;
260276 let r2_name = grm. rule_name_str ( r2_rule_idx) ;
261277
262- eprintln ! (
263- "{}" ,
278+ out. pushln (
264279 self . file_location_msg (
265280 format ! (
266281 "Reduce/Reduce conflict, can reduce '{}' or '{}' with lookahead '{}'" ,
267282 r1_name, r2_name, t_name,
268283 )
269284 . as_str ( ) ,
270- Some ( r1_span)
271- )
272- ) ;
273- eprintln ! (
274- "{}" ,
275- self . underline_span_with_text( r1_span, "First reduce" . to_string( ) , '^' )
276- ) ;
277- eprintln ! (
278- "{}" ,
279- self . underline_span_with_text( r2_span, "Second reduce" . to_string( ) , '-' )
285+ Some ( r1_span) ,
286+ ) ,
280287 ) ;
281- eprintln ! ( ) ;
288+ out. pushln ( self . underline_span_with_text ( r1_span, "First reduce" . to_string ( ) , '^' ) ) ;
289+ out. pushln ( self . underline_span_with_text ( r2_span, "Second reduce" . to_string ( ) , '-' ) ) ;
290+ out. push ( '\n' ) ;
282291 }
283292 for ( s_tok_idx, r_prod_idx, _st_idx) in c. sr_conflicts ( ) {
284293 let r_rule_idx = grm. prod_to_rule ( * r_prod_idx) ;
@@ -288,26 +297,19 @@ impl<'a> SpannedDiagnosticFormatter<'a> {
288297 let reduce_name = grm. rule_name_str ( r_rule_idx) ;
289298 let ( _r_prod_names, mut r_prod_spans) = pidx_prods_data ( ast, * r_prod_idx) ;
290299 let fallback_span = ast. prods [ usize:: from ( * r_prod_idx) ] . prod_span ;
291- eprintln ! (
292- "{}" ,
300+ out. pushln (
293301 self . file_location_msg (
294302 format ! (
295303 "Shift/Reduce conflict, can shift '{}' or reduce '{}'" ,
296304 shift_name, reduce_name
297305 )
298306 . as_str ( ) ,
299- Some ( r_rule_span)
300- )
307+ Some ( r_rule_span) ,
308+ ) ,
301309 ) ;
302310
303- eprintln ! (
304- "{}" ,
305- self . underline_span_with_text( s_tok_span, "Shift" . to_string( ) , '^' )
306- ) ;
307- eprintln ! (
308- "{}" ,
309- self . underline_span_with_text( r_rule_span, "Reduced rule" . to_string( ) , '+' )
310- ) ;
311+ out. pushln ( self . underline_span_with_text ( s_tok_span, "Shift" . to_string ( ) , '^' ) ) ;
312+ out. pushln ( self . underline_span_with_text ( r_rule_span, "Reduced rule" . to_string ( ) , '+' ) ) ;
311313
312314 if r_prod_spans. is_empty ( ) {
313315 r_prod_spans. push ( fallback_span) ;
@@ -338,17 +340,15 @@ impl<'a> SpannedDiagnosticFormatter<'a> {
338340 // but we lack an `Ord` impl to easily ensure it.
339341 //
340342 // We could convert to tuples, then back to spans or add the impl
341- eprintln ! (
342- "{}" ,
343- self . underline_spans_on_line_with_text(
344- spans_on_line. iter( ) . copied( ) ,
345- msg. to_string( ) ,
346- '-'
347- )
348- ) ;
343+ out. pushln ( self . underline_spans_on_line_with_text (
344+ spans_on_line. iter ( ) . copied ( ) ,
345+ msg. to_string ( ) ,
346+ '-' ,
347+ ) ) ;
349348 }
350- eprintln ! ( )
349+ out . push ( '\n' ) ;
351350 }
351+ out
352352 }
353353}
354354
0 commit comments