Skip to main content

parol/parser/
errors.rs

1use std::path::PathBuf;
2
3use anyhow::anyhow;
4use parol_runtime::Location;
5use thiserror::Error;
6
7///
8/// Error types used by the [crate::parser::ParolGrammar]'s semantic actions
9#[derive(Error, Debug)]
10pub enum ParolParserError {
11    /// Undeclared scanner found. Please declare a scanner via %scanner name {{...}}
12    #[error("{context} - Unknown scanner {name}")]
13    UnknownScanner {
14        /// Context (semantic action) where the error was issued
15        context: String,
16        /// Name of the unknown scanner state
17        name: String,
18        /// Source
19        input: PathBuf,
20        /// Location
21        token: Location,
22    },
23
24    /// Empty Groups () are not allowed.
25    #[error("{context} - Empty Group not allowed")]
26    EmptyGroup {
27        /// Context (semantic action) where the error was issued
28        context: String,
29        /// Source
30        input: PathBuf,
31        /// Start location
32        start: Location,
33        /// End location
34        end: Location,
35    },
36
37    /// Empty Optionals [] are not allowed.
38    #[error("{context} - Empty Optionals not allowed")]
39    EmptyOptional {
40        /// Context (semantic action) where the error was issued
41        context: String,
42        /// Source
43        input: PathBuf,
44        /// Start location
45        start: Location,
46        /// End location
47        end: Location,
48    },
49
50    /// Empty Repetitions {{}} are not allowed.
51    #[error("{context} - Empty Repetitions not allowed")]
52    EmptyRepetition {
53        /// Context (semantic action) where the error was issued
54        context: String,
55        /// Source
56        input: PathBuf,
57        /// Start location
58        start: Location,
59        /// End location
60        end: Location,
61    },
62
63    /// Multiple token aliases that expand to the same text will produce a terminal conflict.
64    #[error(
65        r"Multiple token aliases that expand to the same text:
66'{first_alias}' and '{second_alias}' expand both to '{expanded}'."
67    )]
68    ConflictingTokenAliases {
69        /// First
70        first_alias: String,
71        /// Second
72        second_alias: String,
73        /// Expanded
74        expanded: String,
75        /// Source
76        input: PathBuf,
77        /// First alias
78        first: Location,
79        /// Second alias
80        second: Location,
81    },
82
83    /// Empty Scanner states are not allowed.
84    #[error("Empty scanner states ({empty_scanners:?}) found")]
85    EmptyScanners {
86        /// Names of the empty scanner states
87        empty_scanners: Vec<String>,
88    },
89
90    /// Unsupported grammar type
91    #[error("{grammar_type} - Unsupported grammar type")]
92    UnsupportedGrammarType {
93        /// The grammar type found
94        grammar_type: String,
95        /// Source
96        input: PathBuf,
97        /// Location
98        token: Location,
99    },
100
101    /// Unsupported feature
102    #[error("{feature} - Unsupported feature")]
103    UnsupportedFeature {
104        /// The feature found
105        feature: String,
106        /// Hint
107        hint: String,
108        /// Source
109        input: PathBuf,
110        /// Location
111        token: Location,
112    },
113
114    /// Invalid token in transition, e.g. a token that is not defined in the grammar
115    /// is used in a transition. Use a primary non-terminal for the token.
116    #[error(
117        "{context} - Invalid token '{token}' in transition. Use a primary non-terminal for the token."
118    )]
119    InvalidTokenInTransition {
120        /// Context where the error was issued
121        context: String,
122        /// Token that is not defined matched against a valid primary non-terminal
123        token: String,
124        /// Source file
125        input: PathBuf,
126        /// Location of the token
127        location: Location,
128    },
129
130    /// The token that is used to initiate a transition is not defined in this scanner.
131    #[error("{context} - Token '{token}' is not defined in scanner '{scanner}'")]
132    TokenIsNotInScanner {
133        /// Context where the error was issued
134        context: String,
135        /// The scanner where the token is not defined
136        scanner: String,
137        /// Token that is not defined in the scanner
138        token: String,
139        /// Source file
140        input: PathBuf,
141        /// Location of the token
142        location: Location,
143    },
144
145    /// Mixed scanner switching is not allowed - use either parser-based or scanner-based switching.
146    /// Parser-based switching is done via the %sc, %push and %pop directives productions.
147    /// Scanner-based switching is done via the %on directive in the header of the grammar file.
148    ///
149    /// This error can no more occur as of Parol 4, because scanner switching directives
150    /// have been removed from the grammar syntax.
151    #[deprecated(
152        since = "4.0.0",
153        note = "Scanner switching directives have been removed from the grammar syntax."
154    )]
155    #[error("{context} - Mixed scanner switching is not allowed")]
156    MixedScannerSwitching {
157        /// Context where the error was issued
158        context: String,
159        /// Source file
160        input: PathBuf,
161        /// Location of the token
162        location: Location,
163    },
164}
165
166impl From<ParolParserError> for parol_runtime::ParolError {
167    fn from(err: ParolParserError) -> Self {
168        parol_runtime::ParolError::UserError(anyhow!(err))
169    }
170}