Skip to main content

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                &macro_span,
937                "PP13",
938                format!(
939                    "Undefining {}, which has not been previously defined",
940                    macro_name
941                ),
942            )
943            .with_label(
944                &macro_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                    &timescale_span,
1070                    "PP20",
1071                    "Time precision is larger than the time unit",
1072                )
1073                .with_label(
1074                    &timescale_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}