Skip to content

Commit eb2f213

Browse files
committed
Update conflict diagnostics to return string
1 parent 460585e commit eb2f213

File tree

2 files changed

+46
-43
lines changed

2 files changed

+46
-43
lines changed

lrpar/src/lib/diagnostics.rs

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
2235
fn pidx_prods_data<StorageT>(ast: &GrammarAST, pidx: PIdx<StorageT>) -> (Vec<String>, Vec<Span>)
2336
where
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

nimbleparse/src/main.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -305,12 +305,15 @@ fn main() {
305305
if (pp_rr || pp_sr) && !dump_state_graph {
306306
println!("Stategraph:\n{}\n", sgraph.pp_core_states(&grm));
307307
}
308-
yacc_diag.handle_conflicts::<DefaultLexerTypes<u32>>(
309-
&grm,
310-
ast_validation.ast(),
311-
c,
312-
&sgraph,
313-
&stable,
308+
eprintln!(
309+
"{}",
310+
yacc_diag.format_conflicts::<DefaultLexerTypes<u32>>(
311+
&grm,
312+
ast_validation.ast(),
313+
c,
314+
&sgraph,
315+
&stable,
316+
)
314317
);
315318
}
316319
}

0 commit comments

Comments
 (0)