1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
use miette::{Diagnostic, SourceSpan};
use nom_tracable::TracableInfo;
use std::cell::RefCell;
use thiserror::Error;
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct FilterExpressionParseErrors {
pub input: String,
pub errors: Vec<ParseSingleError>,
}
impl FilterExpressionParseErrors {
pub(crate) fn new(input: impl Into<String>, errors: Vec<ParseSingleError>) -> Self {
Self {
input: input.into(),
errors,
}
}
}
#[derive(Clone, Debug, Error, Diagnostic, PartialEq, Eq)]
#[non_exhaustive]
pub enum ParseSingleError {
#[error("invalid regex")]
InvalidRegex {
#[label("{}", message)]
span: SourceSpan,
message: String,
},
#[error("invalid regex")]
InvalidRegexWithoutMessage(#[label("invalid regex")] SourceSpan),
#[error("expected close regex")]
ExpectedCloseRegex(#[label("missing `/`")] SourceSpan),
#[error("unexpected argument")]
UnexpectedArgument(#[label("this set doesn't take an argument")] SourceSpan),
#[error("unexpected comma")]
UnexpectedComma(#[label("this set doesn't take multiple arguments")] SourceSpan),
#[error("invalid string")]
InvalidString(#[label("invalid string")] SourceSpan),
#[error("expected open parenthesis")]
ExpectedOpenParenthesis(#[label("missing `(`")] SourceSpan),
#[error("expected close parenthesis")]
ExpectedCloseParenthesis(#[label("missing `)`")] SourceSpan),
#[error("expected expression")]
ExpectedExpr(#[label("missing expression")] SourceSpan),
#[error("expected end of expression")]
ExpectedEndOfExpression(#[label("unparsed input")] SourceSpan),
#[error("operator didn't match any packages")]
NoPackageMatch(#[label("no packages matched this")] SourceSpan),
#[error("invalid argument for platform")]
InvalidPlatformArgument(#[label("expected \"target\" or \"host\"")] SourceSpan),
#[error("unknown parsing error")]
Unknown,
}
impl ParseSingleError {
pub(crate) fn invalid_regex(input: &str, start: usize, end: usize) -> Self {
match regex_syntax::Parser::new().parse(input) {
Ok(_) => {
Self::InvalidRegexWithoutMessage((start, end - start).into())
}
Err(err) => {
let (message, span) = match &err {
regex_syntax::Error::Parse(err) => (format!("{}", err.kind()), err.span()),
regex_syntax::Error::Translate(err) => (format!("{}", err.kind()), err.span()),
_ => return Self::InvalidRegexWithoutMessage((start, end - start).into()),
};
let err_start = start + span.start.offset;
let err_end = start + span.end.offset;
Self::InvalidRegex {
span: (err_start, err_end - err_start).into(),
message,
}
}
}
}
}
#[derive(Debug, Clone)]
pub(crate) struct State<'a> {
errors: &'a RefCell<Vec<ParseSingleError>>,
tracable_info: TracableInfo,
}
impl<'a> State<'a> {
pub fn new(errors: &'a RefCell<Vec<ParseSingleError>>) -> Self {
let tracable_info = nom_tracable::TracableInfo::new()
.forward(true)
.backward(true);
Self {
errors,
tracable_info,
}
}
pub fn report_error(&self, error: ParseSingleError) {
self.errors.borrow_mut().push(error);
}
}
impl<'a> nom_tracable::HasTracableInfo for State<'a> {
fn get_tracable_info(&self) -> TracableInfo {
self.tracable_info.get_tracable_info()
}
fn set_tracable_info(mut self, info: TracableInfo) -> Self {
self.tracable_info = self.tracable_info.set_tracable_info(info);
self
}
}
pub(crate) trait ToSourceSpan {
fn to_span(&self) -> SourceSpan;
}