scarf_parser/preprocessor/error.rs
1// =======================================================================
2// error.rs
3// =======================================================================
4//! Warnings/errors that are thrown by the preprocessor
5
6use crate::{include::MAX_INCLUDE_DEPTH, *};
7use ariadne::ReportBuilder;
8use std::io;
9
10const NOTE_COLOR: Color = Color::Fixed(81);
11
12/// An error encountered during preprocessing
13///
14/// As preprocessing can affect the interpretation of later
15/// source code, these errors are often irrecoverable
16///
17/// Errors marked with **INTERNAL** are meant for use inside the
18/// preprocessor for passing information, and should not be returned
19#[derive(Debug)]
20pub enum PreprocessorError<'a> {
21 /// An `` `endif `` encountered outside a conditional preprocessor block
22 ///
23 /// ```rust
24 /// # use scarf_parser::*;
25 /// # let mut state = PreprocessorState::new(vec![], vec![]);
26 /// # let cache = PreprocessorCache::new();
27 /// let source = "
28 /// `endif
29 /// ";
30 /// let input = lex(source, "test.v").tokens();
31 /// let preprocess_result = preprocess(
32 /// &mut TokenIterator::new(input.into_iter()),
33 /// &mut state,
34 /// &cache,
35 /// );
36 /// assert!(matches!(preprocess_result, Err(PreprocessorError::Endif(_))));
37 /// ```
38 Endif(Span<'a>),
39 /// No terminating `` `endif `` for a conditional preprocessor block
40 ///
41 /// ```rust
42 /// # use scarf_parser::*;
43 /// # let mut state = PreprocessorState::new(vec![], vec![]);
44 /// # let cache = PreprocessorCache::new();
45 /// let source = "
46 /// `ifdef TEST
47 /// ";
48 /// let input = lex(source, "test.v").tokens();
49 /// let preprocess_result = preprocess(
50 /// &mut TokenIterator::new(input.into_iter()),
51 /// &mut state,
52 /// &cache,
53 /// );
54 /// assert!(matches!(preprocess_result, Err(PreprocessorError::NoEndif(Token::DirIfdef, _))));
55 /// ```
56 NoEndif(Token<'a>, Span<'a>),
57 /// An `` `elsif `` encountered outside a conditional preprocessor block
58 ///
59 /// ```rust
60 /// # use scarf_parser::*;
61 /// # let mut state = PreprocessorState::new(vec![], vec![]);
62 /// # let cache = PreprocessorCache::new();
63 /// let source = "
64 /// `elsif
65 /// ";
66 /// let input = lex(source, "test.v").tokens();
67 /// let preprocess_result = preprocess(
68 /// &mut TokenIterator::new(input.into_iter()),
69 /// &mut state,
70 /// &cache,
71 /// );
72 /// assert!(matches!(preprocess_result, Err(PreprocessorError::Elsif(_))));
73 /// ```
74 Elsif(Span<'a>),
75 /// An `` `else `` encountered outside a conditional preprocessor block
76 ///
77 /// ```rust
78 /// # use scarf_parser::*;
79 /// # let mut state = PreprocessorState::new(vec![], vec![]);
80 /// # let cache = PreprocessorCache::new();
81 /// let source = "
82 /// `else
83 /// ";
84 /// let input = lex(source, "test.v").tokens();
85 /// let preprocess_result = preprocess(
86 /// &mut TokenIterator::new(input.into_iter()),
87 /// &mut state,
88 /// &cache,
89 /// );
90 /// assert!(matches!(preprocess_result, Err(PreprocessorError::Else(_))));
91 /// ```
92 Else(Span<'a>),
93 /// An `` `end_keywords `` encountered outside a `` `begin_keywords `` block
94 ///
95 /// ```rust
96 /// # use scarf_parser::*;
97 /// # let mut state = PreprocessorState::new(vec![], vec![]);
98 /// # let cache = PreprocessorCache::new();
99 /// let source = "
100 /// `end_keywords
101 /// ";
102 /// let input = lex(source, "test.v").tokens();
103 /// let preprocess_result = preprocess(
104 /// &mut TokenIterator::new(input.into_iter()),
105 /// &mut state,
106 /// &cache,
107 /// );
108 /// assert!(matches!(preprocess_result, Err(PreprocessorError::EndKeywords(_))));
109 /// ```
110 EndKeywords(Span<'a>),
111 /// No terminating `` `end_keywords `` for a `` `begin_keywords `` block
112 ///
113 /// ```rust
114 /// # use scarf_parser::*;
115 /// # let mut state = PreprocessorState::new(vec![], vec![]);
116 /// # let cache = PreprocessorCache::new();
117 /// let source = "
118 /// `begin_keywords \"1800-2009\"
119 /// ";
120 /// let input = lex(source, "test.v").tokens();
121 /// let preprocess_result = preprocess(
122 /// &mut TokenIterator::new(input.into_iter()),
123 /// &mut state,
124 /// &cache,
125 /// );
126 /// assert!(matches!(preprocess_result, Err(PreprocessorError::NoEndKeywords(_))));
127 /// ```
128 NoEndKeywords(Span<'a>),
129 /// A missing parameter in a `` `define `` function declaration where one is expected
130 ///
131 /// ```rust
132 /// # use scarf_parser::*;
133 /// # let mut state = PreprocessorState::new(vec![], vec![]);
134 /// # let cache = PreprocessorCache::new();
135 /// let source = "
136 /// `define TEST()
137 /// ";
138 /// let input = lex(source, "test.v").tokens();
139 /// let preprocess_result = preprocess(
140 /// &mut TokenIterator::new(input.into_iter()),
141 /// &mut state,
142 /// &cache,
143 /// );
144 /// assert!(matches!(preprocess_result, Err(PreprocessorError::InvalidDefineParameter(_))));
145 /// ```
146 InvalidDefineParameter(SpannedToken<'a>),
147 /// A missing or invalid argument specification in a `` `define `` function
148 ///
149 /// ```rust
150 /// # use scarf_parser::*;
151 /// # let mut state = PreprocessorState::new(vec![], vec![]);
152 /// # let cache = PreprocessorCache::new();
153 /// let source = "
154 /// `define TEST(a, b c)
155 /// ";
156 /// let input = lex(source, "test.v").tokens();
157 /// let preprocess_result = preprocess(
158 /// &mut TokenIterator::new(input.into_iter()),
159 /// &mut state,
160 /// &cache,
161 /// );
162 /// assert!(matches!(preprocess_result, Err(PreprocessorError::InvalidDefineArgument(_))));
163 /// ```
164 InvalidDefineArgument(SpannedToken<'a>),
165 /// An invalid version specifier for a `` `begin_keywords `` directive
166 ///
167 /// ```rust
168 /// # use scarf_parser::*;
169 /// # let mut state = PreprocessorState::new(vec![], vec![]);
170 /// # let cache = PreprocessorCache::new();
171 /// let source = "
172 /// `begin_keywords \"MyVersion\"
173 /// ";
174 /// let input = lex(source, "test.v").tokens();
175 /// let preprocess_result = preprocess(
176 /// &mut TokenIterator::new(input.into_iter()),
177 /// &mut state,
178 /// &cache,
179 /// );
180 /// assert!(matches!(preprocess_result, Err(PreprocessorError::InvalidVersionSpecifier(_))));
181 /// ```
182 InvalidVersionSpecifier((Option<&'a str>, Span<'a>)),
183 /// A directive that doesn't have all of the required components
184 ///
185 /// In general, [`PreprocessorError::VerboseError`] is preferred, but may
186 /// not be suitable due to a lack of subsequent tokens
187 ///
188 /// ```rust
189 /// # use scarf_parser::*;
190 /// # let mut state = PreprocessorState::new(vec![], vec![]);
191 /// # let cache = PreprocessorCache::new();
192 /// let source = "`line";
193 /// let input = lex(source, "test.v").tokens();
194 /// let preprocess_result = preprocess(
195 /// &mut TokenIterator::new(input.into_iter()),
196 /// &mut state,
197 /// &cache,
198 /// );
199 /// assert!(matches!(preprocess_result, Err(PreprocessorError::IncompleteDirective(_))));
200 /// ```
201 IncompleteDirective(Span<'a>),
202 /// An incomplete preprocessor definition, specifically with function macro arguments
203 ///
204 /// ```rust
205 /// # use scarf_parser::*;
206 /// # let mut state = PreprocessorState::new(vec![], vec![]);
207 /// # let cache = PreprocessorCache::new();
208 /// let source = "
209 /// `define TEST(
210 /// ";
211 /// let input = lex(source, "test.v").tokens();
212 /// let preprocess_result = preprocess(
213 /// &mut TokenIterator::new(input.into_iter()),
214 /// &mut state,
215 /// &cache,
216 /// );
217 /// assert!(matches!(preprocess_result, Err(PreprocessorError::IncompleteDefine(_))));
218 /// ```
219 IncompleteDefine(SpannedToken<'a>),
220 /// Use of a text macro that wasn't previously defined
221 ///
222 /// ```rust
223 /// # use scarf_parser::*;
224 /// # let mut state = PreprocessorState::new(vec![], vec![]);
225 /// # let cache = PreprocessorCache::new();
226 /// let source = "
227 /// `TEST
228 /// ";
229 /// let input = lex(source, "test.v").tokens();
230 /// let preprocess_result = preprocess(
231 /// &mut TokenIterator::new(input.into_iter()),
232 /// &mut state,
233 /// &cache,
234 /// );
235 /// assert!(matches!(preprocess_result, Err(PreprocessorError::UndefinedMacro(_))));
236 /// ```
237 UndefinedMacro((&'a str, Span<'a>)),
238 /// Specifying a macro parameter that was already specified
239 ///
240 /// ```rust
241 /// # use scarf_parser::*;
242 /// # let mut state = PreprocessorState::new(vec![], vec![]);
243 /// # let cache = PreprocessorCache::new();
244 /// let source = "
245 /// `define TEST(a, b, a) a + b
246 /// ";
247 /// let input = lex(source, "test.v").tokens();
248 /// let preprocess_result = preprocess(
249 /// &mut TokenIterator::new(input.into_iter()),
250 /// &mut state,
251 /// &cache,
252 /// );
253 /// assert!(matches!(preprocess_result, Err(PreprocessorError::DuplicateMacroParameter(_))));
254 /// ```
255 DuplicateMacroParameter((&'a str, &'a str, Span<'a>, Span<'a>)),
256 /// Attempting to have a macro parameter with no default value after one that does
257 ///
258 /// ```rust
259 /// # use scarf_parser::*;
260 /// # let mut state = PreprocessorState::new(vec![], vec![]);
261 /// # let cache = PreprocessorCache::new();
262 /// let source = "
263 /// `define TEST(a = 1, b) a + b
264 /// ";
265 /// let input = lex(source, "test.v").tokens();
266 /// let preprocess_result = preprocess(
267 /// &mut TokenIterator::new(input.into_iter()),
268 /// &mut state,
269 /// &cache,
270 /// );
271 /// assert!(matches!(preprocess_result, Err(PreprocessorError::NoDefaultAfterDefault(_))));
272 /// ```
273 NoDefaultAfterDefault((SpannedString<'a>, SpannedString<'a>)),
274 /// Specifying no arguments for a macro function that takes arguments
275 ///
276 /// ```rust
277 /// # use scarf_parser::*;
278 /// # let mut state = PreprocessorState::new(vec![], vec![]);
279 /// # let cache = PreprocessorCache::new();
280 /// let source = "
281 /// `define TEST(a, b) a + b
282 /// `TEST
283 /// ";
284 /// let input = lex(source, "test.v").tokens();
285 /// let preprocess_result = preprocess(
286 /// &mut TokenIterator::new(input.into_iter()),
287 /// &mut state,
288 /// &cache,
289 /// );
290 /// assert!(matches!(preprocess_result, Err(PreprocessorError::NoMacroArguments(_))));
291 /// ```
292 NoMacroArguments((Span<'a>, (&'a str, Span<'a>))),
293 /// Specifying too many arguments for a macro function
294 ///
295 /// ```rust
296 /// # use scarf_parser::*;
297 /// # let mut state = PreprocessorState::new(vec![], vec![]);
298 /// # let cache = PreprocessorCache::new();
299 /// let source = "
300 /// `define TEST(a, b) a + b
301 /// `TEST(1, 2, 3)
302 /// ";
303 /// let input = lex(source, "test.v").tokens();
304 /// let preprocess_result = preprocess(
305 /// &mut TokenIterator::new(input.into_iter()),
306 /// &mut state,
307 /// &cache,
308 /// );
309 /// assert!(matches!(preprocess_result, Err(PreprocessorError::TooManyMacroArguments(_))));
310 /// ```
311 TooManyMacroArguments((Span<'a>, (&'a str, usize, usize, Span<'a>))),
312 /// Missing an argument in a macro function use
313 ///
314 /// ```rust
315 /// # use scarf_parser::*;
316 /// # let mut state = PreprocessorState::new(vec![], vec![]);
317 /// # let cache = PreprocessorCache::new();
318 /// let source = "
319 /// `define TEST(a, b) a + b
320 /// `TEST(1)
321 /// ";
322 /// let input = lex(source, "test.v").tokens();
323 /// let preprocess_result = preprocess(
324 /// &mut TokenIterator::new(input.into_iter()),
325 /// &mut state,
326 /// &cache,
327 /// );
328 /// assert!(matches!(preprocess_result, Err(PreprocessorError::MissingMacroArgument(_))));
329 /// ```
330 MissingMacroArgument((Span<'a>, (&'a str, Span<'a>))),
331 /// An invalid preprocessor identifier specification
332 ///
333 /// ```rust
334 /// # use scarf_parser::*;
335 /// # let mut state = PreprocessorState::new(vec![], vec![]);
336 /// # let cache = PreprocessorCache::new();
337 /// let source = "
338 /// `define TEST(a, b) a``_with_``b
339 /// `TEST(\"one\", \"two\")
340 /// ";
341 /// let input = lex(source, "test.v").tokens();
342 /// let preprocess_result = preprocess(
343 /// &mut TokenIterator::new(input.into_iter()),
344 /// &mut state,
345 /// &cache,
346 /// );
347 /// assert!(matches!(preprocess_result, Err(PreprocessorError::InvalidIdentifierFormation(_))));
348 /// ```
349 InvalidIdentifierFormation((&'a str, Span<'a>)),
350 /// A precision that is less precise than the unit in a `` `timescale `` directive
351 ///
352 /// ```rust
353 /// # use scarf_parser::*;
354 /// # let mut state = PreprocessorState::new(vec![], vec![]);
355 /// # let cache = PreprocessorCache::new();
356 /// let source = "
357 /// `timescale 100 fs / 1 s
358 /// ";
359 /// let input = lex(source, "test.v").tokens();
360 /// let preprocess_result = preprocess(
361 /// &mut TokenIterator::new(input.into_iter()),
362 /// &mut state,
363 /// &cache,
364 /// );
365 /// assert!(matches!(preprocess_result, Err(PreprocessorError::InvalidRelativeTimescales(_))));
366 /// ```
367 InvalidRelativeTimescales(Span<'a>),
368 /// An incomplete macro due to mismatching grouping tokens (`[]`, `()`, or `{}`)
369 ///
370 /// ```rust
371 /// # use scarf_parser::*;
372 /// # let mut state = PreprocessorState::new(vec![], vec![]);
373 /// # let cache = PreprocessorCache::new();
374 /// let source = "
375 /// `define TEST(a, b) a + b
376 /// `TEST(a = 1, b = 2])
377 /// ";
378 /// let input = lex(source, "test.v").tokens();
379 /// let preprocess_result = preprocess(
380 /// &mut TokenIterator::new(input.into_iter()),
381 /// &mut state,
382 /// &cache,
383 /// );
384 /// assert!(matches!(preprocess_result, Err(PreprocessorError::IncompleteMacroWithToken(_))));
385 /// ```
386 IncompleteMacroWithToken(SpannedToken<'a>),
387 /// An error reading a file specified by an `` `include `` macro
388 ///
389 /// ```rust
390 /// # use scarf_parser::*;
391 /// # let mut state = PreprocessorState::new(vec![], vec![]);
392 /// # let cache = PreprocessorCache::new();
393 /// let source = "
394 /// `include \"other.v\"
395 /// ";
396 /// let input = lex(source, "test.v").tokens();
397 /// let preprocess_result = preprocess(
398 /// &mut TokenIterator::new(input.into_iter()),
399 /// &mut state,
400 /// &cache,
401 /// );
402 /// assert!(matches!(preprocess_result, Err(PreprocessorError::Include(_, _, _))));
403 /// ```
404 Include(Span<'a>, String, io::Error),
405 /// The maximum include depth was hit, likely as a result of a self-referential
406 /// `` `include `` sequence
407 ///
408 /// ```rust
409 /// # use scarf_parser::*;
410 /// # let mut state = PreprocessorState::new(vec![], vec![]);
411 /// # let cache = PreprocessorCache::new();
412 /// let source = "
413 /// `include \"test.v\"
414 /// ";
415 /// state.retain_file(
416 /// "test.v".to_string(),
417 /// source.to_string(),
418 /// &cache,
419 /// );
420 /// let input = lex(source, "test.v").tokens();
421 /// let preprocess_result = preprocess(
422 /// &mut TokenIterator::new(input.into_iter()),
423 /// &mut state,
424 /// &cache,
425 /// );
426 /// assert!(matches!(preprocess_result, Err(PreprocessorError::IncludeDepth(_, _))));
427 /// ```
428 IncludeDepth(Span<'a>, Vec<Span<'a>>),
429 /// A [`VerboseError`] detailing the expected and found tokens, for a case not covered above
430 ///
431 /// This is most commonly used when we can provide the user with a bit more context
432 ///
433 /// ```rust
434 /// # use scarf_parser::*;
435 /// # let mut state = PreprocessorState::new(vec![], vec![]);
436 /// # let cache = PreprocessorCache::new();
437 /// let source = "
438 /// `line
439 /// ";
440 /// let input = lex(source, "test.v").tokens();
441 /// let preprocess_result = preprocess(
442 /// &mut TokenIterator::new(input.into_iter()),
443 /// &mut state,
444 /// &cache,
445 /// );
446 /// // Expects a line number
447 /// assert!(matches!(preprocess_result, Err(PreprocessorError::VerboseError(_))));
448 /// ```
449 VerboseError(VerboseError<'a>),
450 // Internal "errors" used for communication
451 // - Should not be exposed outside of main preprocess function
452 /// **INTERNAL**: A newline encountered in a `` `define `` directive
453 NewlineInDefine(Span<'a>),
454 /// **INTERNAL**: The end of a function argument was encountered
455 EndOfFunctionArgument(SpannedToken<'a>),
456}
457
458fn make_report<'s>(
459 span: &Span<'s>,
460 code: &str,
461 reason: String,
462 code_label: String,
463 kind: ariadne::ReportKind<'s>,
464) -> ReportBuilder<'s, (String, std::ops::Range<usize>)> {
465 let report =
466 Report::build(kind, (span.file.to_string(), span.bytes.clone()))
467 .with_code(code)
468 .with_config(
469 ariadne::Config::new()
470 .with_index_type(ariadne::IndexType::Byte),
471 )
472 .with_message(reason);
473 attach_span_label(span, kind_color(&kind), code_label, report)
474}
475
476impl<'s> From<&PreprocessorError<'s>>
477 for Report<'s, (String, std::ops::Range<usize>)>
478{
479 fn from(s: &PreprocessorError<'s>) -> Self {
480 match s {
481 PreprocessorError::Endif(endif_span) => make_report(
482 endif_span,
483 "PP1",
484 "Unexpected `endif".to_string(),
485 "Unexpected `endif".to_string(),
486 ReportKind::Error,
487 ).finish(),
488 PreprocessorError::NoEndif(token, ifdef_span) => make_report(
489 ifdef_span,
490 "PP2",
491 format!("No matching `endif for {token}"),
492 "No matching `endif".to_owned(),
493 ReportKind::Error,
494 ).finish(),
495 PreprocessorError::Elsif(elsif_span) => make_report(
496 elsif_span,
497 "PP3",
498 "Unexpected `elsif".to_string(),
499 "Unexpected `elsif".to_string(),
500 ReportKind::Error,
501 ).finish(),
502 PreprocessorError::Else(else_span) => make_report(
503 else_span,
504 "PP4",
505 "Unexpected `else".to_string(),
506 "Unexpected `else".to_string(),
507 ReportKind::Error,
508 ).finish(),
509 PreprocessorError::EndKeywords(end_keywords_span) => make_report(
510 end_keywords_span,
511 "PP5",
512 "`end_keywords with no previous `begin_keywords".to_string(),
513 "No matching `begin_keywords".to_string(),
514 ReportKind::Error,
515 ).finish(),
516 PreprocessorError::NoEndKeywords(begin_span) => make_report(
517 begin_span,
518 "PP6",
519 "`begin_keywords with no matching `end_keywords".to_string(),
520 "No matching `end_keywords".to_string(),
521 ReportKind::Error,
522 ).finish(),
523 PreprocessorError::InvalidDefineParameter(err_spanned_token) => {
524 make_report(
525 &err_spanned_token.1,
526 "PP7",
527 format!(
528 "Found {}, expected a preprocessor macro parameter/identifier",
529 err_spanned_token.0
530 ),
531 format!("Unexpected {}", err_spanned_token.0),
532 ReportKind::Error,
533 ).finish()
534 }
535 PreprocessorError::InvalidDefineArgument(err_spanned_token) => {
536 make_report(
537 &err_spanned_token.1,
538 "PP7",
539 format!(
540 "Found {}, expected a comma, ), or a preprocessor macro argument",
541 err_spanned_token.0
542 ),
543 format!("Unexpected {}", err_spanned_token.0),
544 ReportKind::Error,
545 ).finish()
546 }
547 PreprocessorError::InvalidVersionSpecifier((
548 spec_string,
549 spec_span,
550 )) => make_report(
551 spec_span,
552 "PP8",
553 match spec_string {
554 Some(version_string) => format!("{version_string} is not a valid version specifier"),
555 None => "Not a valid version specifier".to_string()
556 },
557 "Invalid version specifier".to_string(),
558 ReportKind::Error,
559 ).finish(),
560 PreprocessorError::IncompleteDirective(span) => make_report(
561 span,
562 "PP9",
563 "Incomplete directive".to_string(),
564 "Expected a complete directive".to_string(),
565 ReportKind::Error,
566 ).finish(),
567 PreprocessorError::IncompleteDefine(
568 err_spanned_token,
569 ) => make_report(
570 &err_spanned_token.1,
571 "PP10",
572 format!(
573 "Found {}, expected more in the preprocessor definition",
574 err_spanned_token.0
575 ),
576 "Expected more after".to_string(),
577 ReportKind::Error,
578 ).finish(),
579 PreprocessorError::UndefinedMacro((macro_name, macro_span)) => {
580 make_report(
581 macro_span,
582 "PP11",
583 format!("{macro_name} has not been previously defined"),
584 "Not previously defined".to_string(),
585 ReportKind::Error,
586 ).finish()
587 }
588 PreprocessorError::DuplicateMacroParameter((define_name, arg_name, arg_span, prev_span)) => {
589 attach_span_label(prev_span, NOTE_COLOR, "Previously declared here", make_report(
590 arg_span,
591 "PP14",
592 format!("'{arg_name}' was already declared as a macro parameter for {define_name}"),
593 "Duplicate parameter declaration".to_string(),
594 ReportKind::Error,
595 )).finish()
596 }
597 PreprocessorError::NoDefaultAfterDefault((last_default_arg, no_default_arg)) => {
598 attach_span_label(&last_default_arg.1, NOTE_COLOR, format!("{} had a default specified", last_default_arg.0), make_report(
599 &no_default_arg.1,
600 "PP15",
601 format!("No default specified for argument after one with a default"),
602 "No default specified".to_string(),
603 ReportKind::Error,
604 )).finish()
605 }
606 PreprocessorError::NoMacroArguments((define_span, (macro_name, macro_span))) => {
607 attach_span_label(define_span, NOTE_COLOR, "Macro defined here", make_report(
608 macro_span,
609 "PP16",
610 format!("Expected arguments when using {macro_name}"),
611 "Expected arguments not present".to_string(),
612 ReportKind::Error,
613 )).finish()
614 }
615 PreprocessorError::TooManyMacroArguments((define_span, (macro_name, expected, found, macro_span))) => {
616 attach_span_label(define_span, NOTE_COLOR, format!("Macro definition expects {expected} arguments"), make_report(
617 macro_span,
618 "PP17",
619 format!("{} expected {} arguments, but {} were provided", macro_name, expected, found),
620 format!("{found} arguments provided"),
621 ReportKind::Error,
622 )).finish()
623 }
624 PreprocessorError::MissingMacroArgument((define_span, (arg_name, macro_span))) => {
625 attach_span_label(define_span, NOTE_COLOR, "Macro defined here", make_report(
626 macro_span,
627 "PP18",
628 format!("'{arg_name}' wasn't specified and has no default"),
629 "Missing argument".to_string(),
630 ReportKind::Error,
631 )).finish()
632 }
633 PreprocessorError::InvalidIdentifierFormation((arg_name, arg_span)) => {
634 make_report(
635 arg_span,
636 "PP19",
637 format!("The argument for '{arg_name}' cannot be concatenated into an identifier"),
638 "No valid conversion to identifier".to_string(),
639 ReportKind::Error,
640 ).finish()
641 }
642 PreprocessorError::InvalidRelativeTimescales(timescale_span) => {
643 make_report(
644 timescale_span,
645 "PP20",
646 "Time precision is larger than the time unit".to_string(),
647 "Cannot have delay unit be smaller than precision".to_string(),
648 ReportKind::Error,
649 ).finish()
650 }
651 PreprocessorError::IncompleteMacroWithToken(err_spanned_token) => {
652 make_report(
653 &err_spanned_token.1,
654 "PP21",
655 format!("Usage of {} is incomplete", err_spanned_token.0),
656 "Expected a complete macro argument or escaped newline after".to_string(),
657 ReportKind::Error,
658 ).finish()
659 }
660 PreprocessorError::Include(span, path, io_error) => {
661 make_report(
662 span,
663 "PP22",
664 format!("Error when reading {}", path),
665 io_error.to_string(),
666 ReportKind::Error,
667 ).finish()
668 }
669 PreprocessorError::IncludeDepth(span, _prev_include_spans) => {
670 make_report(
671 span,
672 "PP23",
673 format!("Include depth of {} reached", MAX_INCLUDE_DEPTH),
674 "Check for an `include loop".to_string(),
675 ReportKind::Error,
676 ).finish()
677 }
678 PreprocessorError::VerboseError(verbose_error) => {
679 verbose_error.report("PP24")
680 },
681 PreprocessorError::NewlineInDefine(newline_span) => make_report(
682 newline_span,
683 "PPX",
684 "(Internal Error) Newline in define not handled correctly".to_string(),
685 "(Internal Error) Newline in define not handled correctly".to_string(),
686 ReportKind::Error,
687 ).finish(),
688 PreprocessorError::EndOfFunctionArgument(err_spanned_token) => {
689 make_report(
690 &err_spanned_token.1,
691 "PPX",
692 "(Internal Error) End of function argument not handled correctly".to_string(),
693 "(Internal Error) End of function argument not handled correctly".to_string(),
694 ReportKind::Error,
695 ).finish()
696 }
697 }
698 }
699}
700
701/// A warning encountered during preprocessing
702///
703/// Warnings reflect an irregularity in the source code, but are
704/// still well-defined and allow preprocessing to continue
705#[derive(Debug, Clone, PartialEq)]
706pub enum PreprocessorWarning<'a> {
707 /// Attempted to `` `undef `` a macro that had no previous definition
708 ///
709 /// ```rust
710 /// # use scarf_parser::*;
711 /// # let mut state = PreprocessorState::new(vec![], vec![]);
712 /// # let cache = PreprocessorCache::new();
713 /// let source = "
714 /// `undef TEST
715 /// ";
716 /// let input = lex(source, "test.v").tokens();
717 /// let preprocess_result = preprocess(
718 /// &mut TokenIterator::new(input.into_iter()),
719 /// &mut state,
720 /// &cache,
721 /// );
722 /// assert!(matches!(preprocess_result, Ok(_)));
723 /// assert!(matches!(state.warnings.first(), Some(PreprocessorWarning::NotPreviouslyDefinedMacro(_))))
724 /// ```
725 NotPreviouslyDefinedMacro((&'a str, Span<'a>)),
726 /// A redefinition of a text macro that was previously defined
727 ///
728 /// ```rust
729 /// # use scarf_parser::*;
730 /// # let mut state = PreprocessorState::new(vec![], vec![]);
731 /// # let cache = PreprocessorCache::new();
732 /// let source = "
733 /// `define TEST definition_one
734 /// `define TEST definition_two
735 /// ";
736 /// let input = lex(source, "test.v").tokens();
737 /// let preprocess_result = preprocess(
738 /// &mut TokenIterator::new(input.into_iter()),
739 /// &mut state,
740 /// &cache,
741 /// );
742 /// assert!(matches!(preprocess_result, Ok(_)));
743 /// assert!(matches!(state.warnings.first(), Some(PreprocessorWarning::RedefinedMacro(_))))
744 /// ```
745 RedefinedMacro((&'a str, Span<'a>, Span<'a>)),
746}
747
748impl<'s> From<&PreprocessorWarning<'s>>
749 for Report<'s, (String, std::ops::Range<usize>)>
750{
751 fn from(s: &PreprocessorWarning<'s>) -> Self {
752 match s {
753 PreprocessorWarning::RedefinedMacro((macro_name, macro_span, prev_span)) => {
754 attach_span_label(prev_span, NOTE_COLOR, "Previously defined here", make_report(
755 macro_span,
756 "PP12",
757 format!("Redefining {macro_name}"),
758 "Redefined here".to_string(),
759 ReportKind::Warning,
760 )).finish()
761 }
762 PreprocessorWarning::NotPreviouslyDefinedMacro((
763 macro_name,
764 macro_span,
765 )) => make_report(
766 macro_span,
767 "PP13",
768 format!("Undefining {macro_name}, which has not been previously defined"),
769 "Not previously defined".to_string(),
770 ReportKind::Warning,
771 ).finish(),
772 }
773 }
774}