scarf_parser/preprocessor/error.rs
1// =======================================================================
2// error.rs
3// =======================================================================
4//! Warnings/errors that are thrown by the preprocessor
5
6use crate::{preprocessor::include::MAX_INCLUDE_DEPTH, report::Report, *};
7use std::io;
8
9const NOTE_COLOR: Color = Color::Fixed(81);
10const NOTE_KIND: ariadne::ReportKind<'static> =
11 crate::report::ReportKind::Custom("note", NOTE_COLOR);
12
13/// An error encountered during preprocessing
14///
15/// As preprocessing can affect the interpretation of later
16/// source code, these errors are often irrecoverable
17///
18/// Errors marked with **INTERNAL** are meant for use inside the
19/// preprocessor for passing information, and should not be returned
20#[derive(Debug, Clone, PartialEq)]
21pub enum PreprocessorError<'a> {
22 /// An `` `endif `` encountered outside a conditional preprocessor block
23 ///
24 /// ```rust
25 /// # use scarf_parser::*;
26 /// # let mut state = PreprocessorState::new(vec![], vec![]);
27 /// # let cache = PreprocessorCache::new();
28 /// let source = "
29 /// `endif
30 /// ";
31 /// let input = lex(source, "test.v").tokens();
32 /// let preprocess_result = preprocess(
33 /// input,
34 /// &mut state,
35 /// &cache,
36 /// );
37 /// assert!(preprocess_result.is_err());
38 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::Endif{ .. })));
39 /// ```
40 Endif {
41 /// The [`Span`] of the `` `endif ``
42 endif_span: Span<'a>,
43 },
44 /// No terminating `` `endif `` for a conditional preprocessor block
45 ///
46 /// ```rust
47 /// # use scarf_parser::*;
48 /// # let mut state = PreprocessorState::new(vec![], vec![]);
49 /// # let cache = PreprocessorCache::new();
50 /// let source = "
51 /// `ifdef TEST
52 /// ";
53 /// let input = lex(source, "test.v").tokens();
54 /// let preprocess_result = preprocess(
55 /// input,
56 /// &mut state,
57 /// &cache,
58 /// );
59 /// assert!(preprocess_result.is_err());
60 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::NoEndif{
61 /// cond_token: Token::DirIfdef,
62 /// ..
63 /// })));
64 /// ```
65 NoEndif {
66 /// The conditional token (either [`Token::DirIfdef`], [`Token::DirIfndef`],
67 /// [`Token::DirElsif`], or [`Token::DirElse`]) with no matching `` `endif ``
68 cond_token: Token<'a>,
69 /// The [`Span`] of the conditional token
70 cond_token_span: Span<'a>,
71 },
72 /// An `` `elsif `` encountered outside a conditional preprocessor block
73 ///
74 /// ```rust
75 /// # use scarf_parser::*;
76 /// # let mut state = PreprocessorState::new(vec![], vec![]);
77 /// # let cache = PreprocessorCache::new();
78 /// let source = "
79 /// `elsif
80 /// ";
81 /// let input = lex(source, "test.v").tokens();
82 /// let preprocess_result = preprocess(
83 /// input,
84 /// &mut state,
85 /// &cache,
86 /// );
87 /// assert!(preprocess_result.is_err());
88 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::Elsif{ .. })));
89 /// ```
90 Elsif {
91 /// The [`Span`] of the `` `elsif ``
92 elsif_span: Span<'a>,
93 },
94 /// An `` `else `` encountered outside a conditional preprocessor block
95 ///
96 /// ```rust
97 /// # use scarf_parser::*;
98 /// # let mut state = PreprocessorState::new(vec![], vec![]);
99 /// # let cache = PreprocessorCache::new();
100 /// let source = "
101 /// `else
102 /// ";
103 /// let input = lex(source, "test.v").tokens();
104 /// let preprocess_result = preprocess(
105 /// input,
106 /// &mut state,
107 /// &cache,
108 /// );
109 /// assert!(preprocess_result.is_err());
110 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::Else{ .. })));
111 /// ```
112 Else {
113 /// The [`Span`] of the `` `else ``
114 else_span: Span<'a>,
115 },
116 /// An `` `end_keywords `` encountered outside a `` `begin_keywords `` block
117 ///
118 /// ```rust
119 /// # use scarf_parser::*;
120 /// # let mut state = PreprocessorState::new(vec![], vec![]);
121 /// # let cache = PreprocessorCache::new();
122 /// let source = "
123 /// `end_keywords
124 /// ";
125 /// let input = lex(source, "test.v").tokens();
126 /// let preprocess_result = preprocess(
127 /// input,
128 /// &mut state,
129 /// &cache,
130 /// );
131 /// assert!(preprocess_result.is_err());
132 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::EndKeywords{ .. })));
133 /// ```
134 EndKeywords {
135 /// The [`Span`] of the `` `end_keywords ``
136 end_keywords_span: Span<'a>,
137 },
138 /// No terminating `` `end_keywords `` for a `` `begin_keywords `` block
139 ///
140 /// ```rust
141 /// # use scarf_parser::*;
142 /// # let mut state = PreprocessorState::new(vec![], vec![]);
143 /// # let cache = PreprocessorCache::new();
144 /// let source = "
145 /// `begin_keywords \"1800-2009\"
146 /// ";
147 /// let input = lex(source, "test.v").tokens();
148 /// let preprocess_result = preprocess(
149 /// input,
150 /// &mut state,
151 /// &cache,
152 /// );
153 /// assert!(preprocess_result.is_err());
154 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::NoEndKeywords{ .. })));
155 /// ```
156 NoEndKeywords {
157 /// The [`Span`] of the unterminated `` `begin_keywords ``
158 begin_keywords_span: Span<'a>,
159 },
160 /// A missing parameter in a `` `define `` function declaration where one is expected
161 ///
162 /// ```rust
163 /// # use scarf_parser::*;
164 /// # let mut state = PreprocessorState::new(vec![], vec![]);
165 /// # let cache = PreprocessorCache::new();
166 /// let source = "
167 /// `define TEST()
168 /// ";
169 /// let input = lex(source, "test.v").tokens();
170 /// let preprocess_result = preprocess(
171 /// input,
172 /// &mut state,
173 /// &cache,
174 /// );
175 /// assert!(preprocess_result.is_err());
176 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::InvalidDefineParameter{
177 /// other_token: Token::EParen,
178 /// ..
179 /// })));
180 /// ```
181 InvalidDefineParameter {
182 /// The [`Token`] found instead of the `` `define `` parameter
183 other_token: Token<'a>,
184 /// The [`Span`] of the token found instead
185 other_span: Span<'a>,
186 },
187 /// A missing or invalid argument specification in a `` `define `` function
188 ///
189 /// ```rust
190 /// # use scarf_parser::*;
191 /// # let mut state = PreprocessorState::new(vec![], vec![]);
192 /// # let cache = PreprocessorCache::new();
193 /// let source = "
194 /// `define TEST(a, b c)
195 /// ";
196 /// let input = lex(source, "test.v").tokens();
197 /// let preprocess_result = preprocess(
198 /// input,
199 /// &mut state,
200 /// &cache,
201 /// );
202 /// assert!(preprocess_result.is_err());
203 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::InvalidDefineArgument{
204 /// other_token: Token::SimpleIdentifier("c"),
205 /// ..
206 /// })));
207 /// ```
208 InvalidDefineArgument {
209 /// The [`Token`] found instead of the valid `` `define `` argument
210 other_token: Token<'a>,
211 /// The [`Span`] of the token found instead
212 other_span: Span<'a>,
213 },
214 /// An invalid version specifier for a `` `begin_keywords `` directive
215 ///
216 /// ```rust
217 /// # use scarf_parser::*;
218 /// # let mut state = PreprocessorState::new(vec![], vec![]);
219 /// # let cache = PreprocessorCache::new();
220 /// let source = "
221 /// `begin_keywords \"MyVersion\"
222 /// ";
223 /// let input = lex(source, "test.v").tokens();
224 /// let preprocess_result = preprocess(
225 /// input,
226 /// &mut state,
227 /// &cache,
228 /// );
229 /// assert!(preprocess_result.is_err());
230 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::InvalidVersionSpecifier{
231 /// invalid_version: Token::StringLiteral("MyVersion"),
232 /// ..
233 /// })));
234 /// ```
235 InvalidVersionSpecifier {
236 /// The [`Token`] provided instead of a valid version specifier
237 ///
238 /// If the token is a [`Token::StringLiteral`], the string isn't a version recognized
239 /// by 1800-2023
240 invalid_version: Token<'a>,
241 /// The [`Span`] of the invalid version specifier
242 invalid_version_span: Span<'a>,
243 },
244 /// A directive that doesn't have all of the required components
245 ///
246 /// In general, [`PreprocessorError::VerboseError`] is preferred, but may
247 /// not be suitable due to a lack of subsequent tokens
248 ///
249 /// ```rust
250 /// # use scarf_parser::*;
251 /// # let mut state = PreprocessorState::new(vec![], vec![]);
252 /// # let cache = PreprocessorCache::new();
253 /// let source = "`line";
254 /// let input = lex(source, "test.v").tokens();
255 /// let preprocess_result = preprocess(
256 /// input,
257 /// &mut state,
258 /// &cache,
259 /// );
260 /// assert!(preprocess_result.is_err());
261 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::IncompleteDirective{ .. })));
262 /// ```
263 IncompleteDirective {
264 /// The [`Span`] of the incomplete preprocessor directive
265 ///
266 /// This is usually the primary directive, but can be other more indicative
267 /// tokens as well, such as an unmatched opening parenthesis
268 directive_span: Span<'a>,
269 },
270 /// An incomplete preprocessor definition, specifically with function macro arguments
271 ///
272 /// ```rust
273 /// # use scarf_parser::*;
274 /// # let mut state = PreprocessorState::new(vec![], vec![]);
275 /// # let cache = PreprocessorCache::new();
276 /// let source = "
277 /// `define TEST(
278 /// ";
279 /// let input = lex(source, "test.v").tokens();
280 /// let preprocess_result = preprocess(
281 /// input,
282 /// &mut state,
283 /// &cache,
284 /// );
285 /// assert!(preprocess_result.is_err());
286 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::IncompleteDefine{
287 /// other_token: Token::Paren,
288 /// ..
289 /// })));
290 /// ```
291 IncompleteDefine {
292 /// If known, the [`Token`] found instead of a valid function macro argument specification
293 ///
294 /// In the case that the token wasn't tracked, the opening [`Token::Paren`] is referenced
295 /// instead
296 other_token: Token<'a>,
297 /// The [`Span`] of the token found instead
298 other_span: Span<'a>,
299 },
300 /// Use of a text macro that wasn't previously defined
301 ///
302 /// ```rust
303 /// # use scarf_parser::*;
304 /// # let mut state = PreprocessorState::new(vec![], vec![]);
305 /// # let cache = PreprocessorCache::new();
306 /// let source = "
307 /// `TEST
308 /// ";
309 /// let input = lex(source, "test.v").tokens();
310 /// let preprocess_result = preprocess(
311 /// input,
312 /// &mut state,
313 /// &cache,
314 /// );
315 /// assert!(preprocess_result.is_err());
316 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::UndefinedMacro{
317 /// undefined_name: "TEST",
318 /// ..
319 /// })));
320 /// ```
321 UndefinedMacro {
322 /// The name of the undefined macro
323 undefined_name: &'a str,
324 /// The [`Span`] of the undefined macro
325 undefined_span: Span<'a>,
326 },
327 /// Specifying a macro parameter that was already specified
328 ///
329 /// ```rust
330 /// # use scarf_parser::*;
331 /// # let mut state = PreprocessorState::new(vec![], vec![]);
332 /// # let cache = PreprocessorCache::new();
333 /// let source = "
334 /// `define TEST(a, b, a) a + b
335 /// ";
336 /// let input = lex(source, "test.v").tokens();
337 /// let preprocess_result = preprocess(
338 /// input,
339 /// &mut state,
340 /// &cache,
341 /// );
342 /// assert!(preprocess_result.is_err());
343 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::DuplicateMacroParameter{
344 /// define_name: "TEST",
345 /// param_name: "a",
346 /// ..
347 /// })));
348 /// ```
349 DuplicateMacroParameter {
350 /// The name of the macro for which duplicate parameters were specified
351 define_name: &'a str,
352 /// The name of the parameter that was specified multiple times
353 param_name: &'a str,
354 /// The [`Span`] of the duplicate specification
355 dup_span: Span<'a>,
356 /// The [`Span`] of the previous/original specification
357 prev_span: Span<'a>,
358 },
359 /// Attempting to have a macro parameter with no default value after one that does
360 ///
361 /// ```rust
362 /// # use scarf_parser::*;
363 /// # let mut state = PreprocessorState::new(vec![], vec![]);
364 /// # let cache = PreprocessorCache::new();
365 /// let source = "
366 /// `define TEST(a = 1, b) a + b
367 /// ";
368 /// let input = lex(source, "test.v").tokens();
369 /// let preprocess_result = preprocess(
370 /// input,
371 /// &mut state,
372 /// &cache,
373 /// );
374 /// assert!(preprocess_result.is_err());
375 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::NoDefaultAfterDefault{
376 /// default_param: "a",
377 /// non_default_param: "b",
378 /// ..
379 /// })));
380 /// ```
381 NoDefaultAfterDefault {
382 /// The name of the previously-specified default parameter
383 default_param: &'a str,
384 /// The [`Span`] of the previously-specified default parameter
385 default_param_span: Span<'a>,
386 /// The name of the non-default parameter
387 non_default_param: &'a str,
388 /// The [`Span`] of the non-default parameter
389 non_default_param_span: Span<'a>,
390 },
391 /// Specifying no arguments for a macro function that takes arguments
392 ///
393 /// ```rust
394 /// # use scarf_parser::*;
395 /// # let mut state = PreprocessorState::new(vec![], vec![]);
396 /// # let cache = PreprocessorCache::new();
397 /// let source = "
398 /// `define TEST(a, b) a + b
399 /// `TEST
400 /// ";
401 /// let input = lex(source, "test.v").tokens();
402 /// let preprocess_result = preprocess(
403 /// input,
404 /// &mut state,
405 /// &cache,
406 /// );
407 /// assert!(preprocess_result.is_err());
408 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::NoMacroArguments{
409 /// macro_name: "TEST",
410 /// ..
411 /// })));
412 /// ```
413 NoMacroArguments {
414 /// The name of the macro
415 macro_name: &'a str,
416 /// The [`Span`] of the macro definition (with arguments)
417 define_span: Span<'a>,
418 /// The [`Span`] where the macro was used with no arguments
419 use_span: Span<'a>,
420 },
421 /// Specifying too many arguments for a macro function
422 ///
423 /// ```rust
424 /// # use scarf_parser::*;
425 /// # let mut state = PreprocessorState::new(vec![], vec![]);
426 /// # let cache = PreprocessorCache::new();
427 /// let source = "
428 /// `define TEST(a, b) a + b
429 /// `TEST(1, 2, 3)
430 /// ";
431 /// let input = lex(source, "test.v").tokens();
432 /// let preprocess_result = preprocess(
433 /// input,
434 /// &mut state,
435 /// &cache,
436 /// );
437 /// assert!(preprocess_result.is_err());
438 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::TooManyMacroArguments{
439 /// macro_name: "TEST",
440 /// expected: 2,
441 /// found: 3,
442 /// ..
443 /// })));
444 /// ```
445 TooManyMacroArguments {
446 /// The name of the macro
447 macro_name: &'a str,
448 /// The [`Span`] of the macro definition
449 define_span: Span<'a>,
450 /// The [`Span`] where the macro was used with too many arguments
451 use_span: Span<'a>,
452 /// How many arguments were expected
453 expected: usize,
454 /// How many arguments were found
455 found: usize,
456 },
457 /// Missing an argument in a macro function use
458 ///
459 /// ```rust
460 /// # use scarf_parser::*;
461 /// # let mut state = PreprocessorState::new(vec![], vec![]);
462 /// # let cache = PreprocessorCache::new();
463 /// let source = "
464 /// `define TEST(a, b) a + b
465 /// `TEST(1)
466 /// ";
467 /// let input = lex(source, "test.v").tokens();
468 /// let preprocess_result = preprocess(
469 /// input,
470 /// &mut state,
471 /// &cache,
472 /// );
473 /// assert!(preprocess_result.is_err());
474 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::MissingMacroArgument{
475 /// param_name: "b",
476 /// ..
477 /// })));
478 /// ```
479 MissingMacroArgument {
480 /// The [`Span`] of the macro definition
481 define_span: Span<'a>,
482 /// The [`Span`] where the macro was used with a missing argument
483 use_span: Span<'a>,
484 /// The name of the missing parameter
485 param_name: &'a str,
486 },
487 /// An invalid preprocessor identifier specification
488 ///
489 /// ```rust
490 /// # use scarf_parser::*;
491 /// # let mut state = PreprocessorState::new(vec![], vec![]);
492 /// # let cache = PreprocessorCache::new();
493 /// let source = "
494 /// `define TEST(a, b) a``_with_``b
495 /// `TEST(\"one\", \"two\")
496 /// ";
497 /// let input = lex(source, "test.v").tokens();
498 /// let preprocess_result = preprocess(
499 /// input,
500 /// &mut state,
501 /// &cache,
502 /// );
503 /// assert!(preprocess_result.is_err());
504 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::InvalidIdentifierFormation{
505 /// param_name: "a",
506 /// ..
507 /// })));
508 /// ```
509 InvalidIdentifierFormation {
510 /// The name of the parameter used in a preprocessor identifier
511 param_name: &'a str,
512 /// The [`Span`] of the invalid argument
513 arg_span: Span<'a>,
514 },
515 /// A precision that is less precise than the unit in a `` `timescale `` directive
516 ///
517 /// ```rust
518 /// # use scarf_parser::*;
519 /// # let mut state = PreprocessorState::new(vec![], vec![]);
520 /// # let cache = PreprocessorCache::new();
521 /// let source = "
522 /// `timescale 100 fs / 1 s
523 /// ";
524 /// let input = lex(source, "test.v").tokens();
525 /// let preprocess_result = preprocess(
526 /// input,
527 /// &mut state,
528 /// &cache,
529 /// );
530 /// assert!(preprocess_result.is_err());
531 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::InvalidRelativeTimescales{ .. })));
532 /// ```
533 InvalidRelativeTimescales {
534 /// The [`Span`] of the `` `timescale `` directive
535 timescale_span: Span<'a>,
536 },
537 /// An incomplete macro due to mismatching grouping tokens (`[]`, `()`, or `{}`)
538 ///
539 /// ```rust
540 /// # use scarf_parser::*;
541 /// # let mut state = PreprocessorState::new(vec![], vec![]);
542 /// # let cache = PreprocessorCache::new();
543 /// let source = "
544 /// `define TEST(a, b) a + b
545 /// `TEST(a = 1, b = 2])
546 /// ";
547 /// let input = lex(source, "test.v").tokens();
548 /// let preprocess_result = preprocess(
549 /// input,
550 /// &mut state,
551 /// &cache,
552 /// );
553 /// assert!(preprocess_result.is_err());
554 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::IncompleteMacroWithToken{
555 /// error_token: Token::EBracket,
556 /// ..
557 /// })));
558 /// ```
559 IncompleteMacroWithToken {
560 /// The error-causing [`Token`] (either [`Token::EParen`],
561 /// [`Token::EBracket`], or [`Token::EBrace`])
562 error_token: Token<'a>,
563 /// The error-causing [`Span`]
564 error_span: Span<'a>,
565 },
566 /// An error reading a file specified by an `` `include `` macro
567 ///
568 /// ```rust
569 /// # use scarf_parser::*;
570 /// # let mut state = PreprocessorState::new(vec![], vec![]);
571 /// # let cache = PreprocessorCache::new();
572 /// let source = "
573 /// `include \"other.v\"
574 /// ";
575 /// let input = lex(source, "test.v").tokens();
576 /// let preprocess_result = preprocess(
577 /// input,
578 /// &mut state,
579 /// &cache,
580 /// );
581 /// assert!(preprocess_result.is_err());
582 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::Include{
583 /// include_path: "other.v",
584 /// ..
585 /// })));
586 /// ```
587 Include {
588 /// The path for the `` `include `` directive
589 include_path: &'a str,
590 /// The [`Span`] of the include path
591 include_path_span: Span<'a>,
592 /// The [`io::ErrorKind`] raised when attempting to read the file
593 read_err: io::ErrorKind,
594 },
595 /// The maximum include depth was hit, likely as a result of a self-referential
596 /// `` `include `` sequence
597 ///
598 /// ```no_run
599 /// # // No test.v in the file system
600 /// # use scarf_parser::*;
601 /// # let mut state = PreprocessorState::new(vec![], vec![]);
602 /// # let cache = PreprocessorCache::new();
603 /// let source = "
604 /// `include \"test.v\"
605 /// ";
606 /// state.retain_file(
607 /// "test.v".to_string(),
608 /// source.to_string(),
609 /// &cache,
610 /// );
611 /// let input = lex(source, "test.v").tokens();
612 /// let preprocess_result = preprocess(
613 /// input,
614 /// &mut state,
615 /// &cache,
616 /// );
617 /// assert!(preprocess_result.is_err());
618 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::IncludeDepth{ .. })));
619 /// ```
620 IncludeDepth {
621 /// The [`Span`] of the `` `include `` directive that exceeded the limit
622 include_span: Span<'a>,
623 },
624 /// A [`VerboseError`] detailing the expected and found tokens, for a case not covered above
625 ///
626 /// This is most commonly used when we can provide the user with a bit more context
627 ///
628 /// ```rust
629 /// # use scarf_parser::*;
630 /// # let mut state = PreprocessorState::new(vec![], vec![]);
631 /// # let cache = PreprocessorCache::new();
632 /// let source = "
633 /// `line
634 /// ";
635 /// let input = lex(source, "test.v").tokens();
636 /// let preprocess_result = preprocess(
637 /// input,
638 /// &mut state,
639 /// &cache,
640 /// );
641 /// // Expects a line number
642 /// assert!(preprocess_result.is_err());
643 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::VerboseError{
644 /// err: VerboseError{
645 /// found: Some(Token::Newline),
646 /// ..
647 /// }
648 /// })));
649 /// ```
650 VerboseError {
651 /// The [`VerboseError`] for the preprocessor error
652 err: VerboseError<'a>,
653 },
654 /// Attempted to `` `undef `` a macro that had no previous definition
655 ///
656 /// ```rust
657 /// # use scarf_parser::*;
658 /// # let mut state = PreprocessorState::new(vec![], vec![]);
659 /// # let cache = PreprocessorCache::new();
660 /// let source = "
661 /// `undef TEST
662 /// ";
663 /// let input = lex(source, "test.v").tokens();
664 /// let preprocess_result = preprocess(
665 /// input,
666 /// &mut state,
667 /// &cache,
668 /// );
669 /// assert!(preprocess_result.is_ok());
670 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::NotPreviouslyDefinedMacro{
671 /// macro_name: "TEST",
672 /// ..
673 /// })))
674 /// ```
675 NotPreviouslyDefinedMacro {
676 /// The name that wasn't previously defined
677 macro_name: &'a str,
678 /// The [`Span`] where the not-previously-defined name was specified
679 macro_span: Span<'a>,
680 },
681 /// A redefinition of a text macro that was previously defined
682 ///
683 /// ```rust
684 /// # use scarf_parser::*;
685 /// # let mut state = PreprocessorState::new(vec![], vec![]);
686 /// # let cache = PreprocessorCache::new();
687 /// let source = "
688 /// `define TEST definition_one
689 /// `define TEST definition_two
690 /// ";
691 /// let input = lex(source, "test.v").tokens();
692 /// let preprocess_result = preprocess(
693 /// input,
694 /// &mut state,
695 /// &cache,
696 /// );
697 /// assert!(preprocess_result.is_ok());
698 /// assert!(matches!(state.errors.first(), Some(PreprocessorError::RedefinedMacro{
699 /// macro_name: "TEST",
700 /// ..
701 /// })))
702 /// ```
703 RedefinedMacro {
704 /// The name of the macro being redefined
705 macro_name: &'a str,
706 /// The [`Span`] of the redefinition
707 redef_span: Span<'a>,
708 /// The [`Span`] where the macro was previously defined
709 prev_def_span: Span<'a>,
710 },
711 // Internal "errors" used for communication
712 // - Should not be exposed outside of main preprocess function
713 /// **INTERNAL**: A newline encountered in a `` `define `` directive
714 NewlineInDefine(Span<'a>),
715 /// **INTERNAL**: The end of a function argument was encountered
716 EndOfFunctionArgument(SpannedToken<'a>),
717}
718
719impl<'a> PreprocessorError<'a> {
720 /// Whether the given [`PreprocessorError`] is just a warning
721 ///
722 /// Warnings reflect an irregularity in the source code, but are
723 /// still well-defined and allow preprocessing to continue
724 pub fn is_warning(&self) -> bool {
725 match self {
726 PreprocessorError::NotPreviouslyDefinedMacro { .. }
727 | PreprocessorError::RedefinedMacro { .. } => true,
728 _ => false,
729 }
730 }
731}
732
733impl<'s> From<&PreprocessorError<'s>> for Report {
734 fn from(s: &PreprocessorError<'s>) -> Self {
735 match s {
736 PreprocessorError::Endif { endif_span } => Report::new(
737 report::ReportKind::Error,
738 &endif_span,
739 "PP1",
740 "Unexpected `endif",
741 )
742 .with_label(
743 &endif_span,
744 report::ReportKind::Error,
745 "Unexpected `endif",
746 ),
747 PreprocessorError::NoEndif {
748 cond_token,
749 cond_token_span,
750 } => Report::new(
751 report::ReportKind::Error,
752 &cond_token_span,
753 "PP2",
754 format!("No matching `endif for {cond_token}"),
755 )
756 .with_label(
757 &cond_token_span,
758 report::ReportKind::Error,
759 "No matching `endif",
760 ),
761 PreprocessorError::Elsif { elsif_span } => Report::new(
762 report::ReportKind::Error,
763 &elsif_span,
764 "PP3",
765 "Unexpected `elsif",
766 )
767 .with_label(
768 &elsif_span,
769 report::ReportKind::Error,
770 "Unexpected `elsif",
771 ),
772 PreprocessorError::Else { else_span } => Report::new(
773 report::ReportKind::Error,
774 &else_span,
775 "PP4",
776 "Unexpected `else",
777 )
778 .with_label(
779 &else_span,
780 report::ReportKind::Error,
781 "Unexpected `else",
782 ),
783 PreprocessorError::EndKeywords { end_keywords_span } => {
784 Report::new(
785 report::ReportKind::Error,
786 &end_keywords_span,
787 "PP5",
788 "`end_keywords with no previous `begin_keywords",
789 )
790 .with_label(
791 &end_keywords_span,
792 report::ReportKind::Error,
793 "No matching `begin_keywords",
794 )
795 }
796 PreprocessorError::NoEndKeywords {
797 begin_keywords_span,
798 } => Report::new(
799 report::ReportKind::Error,
800 &begin_keywords_span,
801 "PP6",
802 "`begin_keywords with no matching `end_keywords",
803 )
804 .with_label(
805 &begin_keywords_span,
806 report::ReportKind::Error,
807 "No matching `end_keywords",
808 ),
809 PreprocessorError::InvalidDefineParameter {
810 other_token,
811 other_span,
812 } => Report::new(
813 report::ReportKind::Error,
814 &other_span,
815 "PP7",
816 format!(
817 concat!(
818 "Found {}, expected a preprocessor ",
819 "macro parameter/identifier"
820 ),
821 other_token
822 ),
823 )
824 .with_label(
825 &other_span,
826 report::ReportKind::Error,
827 format!("Unexpected {}", other_token),
828 ),
829 PreprocessorError::InvalidDefineArgument {
830 other_token,
831 other_span,
832 } => Report::new(
833 report::ReportKind::Error,
834 &other_span,
835 "PP7",
836 format!(
837 concat!(
838 "Found {}, expected a comma, ), ",
839 "or a preprocessor macro argument"
840 ),
841 other_token
842 ),
843 )
844 .with_label(
845 &other_span,
846 report::ReportKind::Error,
847 format!("Unexpected {}", other_token),
848 ),
849 PreprocessorError::InvalidVersionSpecifier {
850 invalid_version,
851 invalid_version_span,
852 } => Report::new(
853 report::ReportKind::Error,
854 &invalid_version_span,
855 "PP8",
856 match invalid_version {
857 Token::StringLiteral(invalid_version_str) => format!(
858 "{} is not a valid version specifier",
859 invalid_version_str
860 ),
861 _ => {
862 format!("{} isn't a version specifier", invalid_version)
863 }
864 },
865 )
866 .with_label(
867 &invalid_version_span,
868 report::ReportKind::Error,
869 "Invalid version specifier",
870 ),
871 PreprocessorError::IncompleteDirective { directive_span } => {
872 Report::new(
873 report::ReportKind::Error,
874 &directive_span,
875 "PP9",
876 "Incomplete directive",
877 )
878 .with_label(
879 &directive_span,
880 report::ReportKind::Error,
881 "Expected a complete directive",
882 )
883 }
884 PreprocessorError::IncompleteDefine {
885 other_token,
886 other_span,
887 } => Report::new(
888 report::ReportKind::Error,
889 &other_span,
890 "PP10",
891 format!(
892 "Found {}, expected more in the preprocessor definition",
893 other_token
894 ),
895 )
896 .with_label(
897 &other_span,
898 report::ReportKind::Error,
899 "Expected more after",
900 ),
901 PreprocessorError::UndefinedMacro {
902 undefined_name,
903 undefined_span,
904 } => Report::new(
905 report::ReportKind::Error,
906 &undefined_span,
907 "PP11",
908 format!("{undefined_name} has not been previously defined"),
909 )
910 .with_label(
911 &undefined_span,
912 report::ReportKind::Error,
913 "Not previously defined",
914 ),
915 PreprocessorError::RedefinedMacro {
916 macro_name,
917 redef_span,
918 prev_def_span,
919 } => Report::new(
920 report::ReportKind::Warning,
921 &redef_span,
922 "PP12",
923 format!("Redefining {macro_name}"),
924 )
925 .with_label(&prev_def_span, NOTE_KIND, "Previously defined here")
926 .with_label(
927 &redef_span,
928 report::ReportKind::Warning,
929 "Redefined here",
930 ),
931 PreprocessorError::NotPreviouslyDefinedMacro {
932 macro_name,
933 macro_span,
934 } => Report::new(
935 report::ReportKind::Warning,
936 ¯o_span,
937 "PP13",
938 format!(
939 "Undefining {}, which has not been previously defined",
940 macro_name
941 ),
942 )
943 .with_label(
944 ¯o_span,
945 report::ReportKind::Warning,
946 "Not previously defined",
947 ),
948 PreprocessorError::DuplicateMacroParameter {
949 define_name,
950 param_name,
951 dup_span,
952 prev_span,
953 } => Report::new(
954 report::ReportKind::Error,
955 &dup_span,
956 "PP14",
957 format!(
958 "'{}' was already declared as a macro parameter for {}",
959 param_name, define_name
960 ),
961 )
962 .with_label(&prev_span, NOTE_KIND, "Previously declared here")
963 .with_label(
964 &dup_span,
965 report::ReportKind::Error,
966 "Duplicate parameter declaration",
967 ),
968 PreprocessorError::NoDefaultAfterDefault {
969 default_param,
970 default_param_span,
971 non_default_param,
972 non_default_param_span,
973 } => Report::new(
974 report::ReportKind::Error,
975 &non_default_param_span,
976 "PP15",
977 "No default specified for argument after one with a default",
978 )
979 .with_label(
980 &default_param_span,
981 NOTE_KIND,
982 format!("{} had a default specified", default_param),
983 )
984 .with_label(
985 &non_default_param_span,
986 report::ReportKind::Error,
987 format!("No default specified for {}", non_default_param),
988 ),
989 PreprocessorError::NoMacroArguments {
990 macro_name,
991 define_span,
992 use_span,
993 } => Report::new(
994 report::ReportKind::Error,
995 &use_span,
996 "PP16",
997 format!("Expected arguments when using {macro_name}"),
998 )
999 .with_label(&define_span, NOTE_KIND, "Macro defined here")
1000 .with_label(
1001 &use_span,
1002 report::ReportKind::Error,
1003 "Expected arguments not present",
1004 ),
1005 PreprocessorError::TooManyMacroArguments {
1006 macro_name,
1007 define_span,
1008 use_span,
1009 expected,
1010 found,
1011 } => Report::new(
1012 report::ReportKind::Error,
1013 &use_span,
1014 "PP17",
1015 format!(
1016 "{} expected {} arguments, but {} were provided",
1017 macro_name, expected, found
1018 ),
1019 )
1020 .with_label(
1021 &define_span,
1022 NOTE_KIND,
1023 format!("Macro definition expects {expected} arguments"),
1024 )
1025 .with_label(
1026 &use_span,
1027 report::ReportKind::Error,
1028 format!("{found} arguments provided"),
1029 ),
1030 PreprocessorError::MissingMacroArgument {
1031 define_span,
1032 use_span,
1033 param_name,
1034 } => Report::new(
1035 report::ReportKind::Error,
1036 &use_span,
1037 "PP18",
1038 format!("'{param_name}' wasn't specified and has no default"),
1039 )
1040 .with_label(&define_span, NOTE_KIND, "Macro defined here")
1041 .with_label(
1042 &use_span,
1043 report::ReportKind::Error,
1044 "Missing argument",
1045 ),
1046 PreprocessorError::InvalidIdentifierFormation {
1047 param_name,
1048 arg_span,
1049 } => Report::new(
1050 report::ReportKind::Error,
1051 &arg_span,
1052 "PP19",
1053 format!(
1054 concat!(
1055 "The argument for '{}' cannot be ",
1056 "concatenated into an identifier"
1057 ),
1058 param_name
1059 ),
1060 )
1061 .with_label(
1062 &arg_span,
1063 report::ReportKind::Error,
1064 "No valid conversion to identifier",
1065 ),
1066 PreprocessorError::InvalidRelativeTimescales { timescale_span } => {
1067 Report::new(
1068 report::ReportKind::Error,
1069 ×cale_span,
1070 "PP20",
1071 "Time precision is larger than the time unit",
1072 )
1073 .with_label(
1074 ×cale_span,
1075 report::ReportKind::Error,
1076 "Cannot have delay unit be smaller than precision",
1077 )
1078 }
1079 PreprocessorError::IncompleteMacroWithToken {
1080 error_token,
1081 error_span,
1082 } => Report::new(
1083 report::ReportKind::Error,
1084 &error_span,
1085 "PP21",
1086 format!(
1087 "Usage of {} resulted in an incomplete macro",
1088 error_token
1089 ),
1090 )
1091 .with_label(
1092 &error_span,
1093 report::ReportKind::Error,
1094 "Expected a complete macro argument or escaped newline after",
1095 ),
1096 PreprocessorError::Include {
1097 include_path,
1098 include_path_span,
1099 read_err,
1100 } => Report::new(
1101 report::ReportKind::Error,
1102 &include_path_span,
1103 "PP22",
1104 format!("Error when reading {}", include_path),
1105 )
1106 .with_label(
1107 &include_path_span,
1108 report::ReportKind::Error,
1109 read_err.to_string(),
1110 ),
1111 PreprocessorError::IncludeDepth { include_span } => Report::new(
1112 report::ReportKind::Error,
1113 &include_span,
1114 "PP23",
1115 format!("Max include depth of {} reached", MAX_INCLUDE_DEPTH),
1116 )
1117 .with_label(
1118 &include_span,
1119 report::ReportKind::Error,
1120 "Check for an `include loop",
1121 ),
1122 PreprocessorError::VerboseError { err } => err.report("PP24"),
1123 PreprocessorError::NewlineInDefine(newline_span) => Report::new(
1124 report::ReportKind::Error,
1125 &newline_span,
1126 "PPX",
1127 "(Internal Error) Newline in define not handled correctly",
1128 )
1129 .with_label(
1130 &newline_span,
1131 report::ReportKind::Error,
1132 "(Internal Error) Newline in define not handled correctly",
1133 ),
1134 PreprocessorError::EndOfFunctionArgument(err_spanned_token) => {
1135 Report::new(
1136 report::ReportKind::Error,
1137 &err_spanned_token.1,
1138 "PPX",
1139 concat!(
1140 "(Internal Error) End of function argument ",
1141 "not handled correctly"
1142 ),
1143 )
1144 .with_label(
1145 &err_spanned_token.1,
1146 report::ReportKind::Error,
1147 concat!(
1148 "(Internal Error) End of function argument ",
1149 "not handled correctly"
1150 ),
1151 )
1152 }
1153 }
1154 }
1155}