Skip to content

Commit 0f15c0e

Browse files
committed
Make HeaderError convert into YaccGrammarError
1 parent 277ae03 commit 0f15c0e

12 files changed

Lines changed: 217 additions & 150 deletions

File tree

cfgrammar/src/lib/header.rs

Lines changed: 118 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::{
22
markmap::{Entry, MarkMap},
3-
yacc::{ParserError, YaccKind, YaccOriginalActionKind},
3+
yacc::{
4+
parser::SpansKind, YaccGrammarError, YaccGrammarErrorKind, YaccKind, YaccOriginalActionKind,
5+
},
46
Location, Span,
57
};
68
use lazy_static::lazy_static;
@@ -14,21 +16,36 @@ use std::{error::Error, fmt};
1416
/// * An error during parsing the section.
1517
/// * An error resulting from a value in the section having an invalid value.
1618
#[derive(Debug, Clone)]
17-
pub struct HeaderError {
19+
#[doc(hidden)]
20+
pub struct HeaderError<T> {
1821
pub kind: HeaderErrorKind,
19-
pub locations: Vec<Location>,
22+
pub locations: Vec<T>,
2023
}
2124

22-
impl Error for HeaderError {}
23-
impl fmt::Display for HeaderError {
25+
impl<T: fmt::Debug> Error for HeaderError<T> {}
26+
impl<T> fmt::Display for HeaderError<T> {
2427
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2528
write!(f, "{}", self.kind)
2629
}
2730
}
2831

29-
impl From<HeaderError> for ParserError {
30-
fn from(e: HeaderError) -> ParserError {
31-
ParserError::HeaderError(e)
32+
impl From<HeaderError<Span>> for YaccGrammarError {
33+
fn from(e: HeaderError<Span>) -> YaccGrammarError {
34+
YaccGrammarError {
35+
kind: YaccGrammarErrorKind::Header(e.kind, e.spanskind()),
36+
spans: e.locations,
37+
}
38+
}
39+
}
40+
41+
// This is essentially a tuple that needs a newtype so we can implement `From` for it.
42+
// Thus we aren't worried about it being `pub`.
43+
#[derive(Debug, PartialEq)]
44+
pub struct HeaderValue<T>(pub T, pub Value<T>);
45+
46+
impl From<HeaderValue<Span>> for HeaderValue<Location> {
47+
fn from(hv: HeaderValue<Span>) -> HeaderValue<Location> {
48+
HeaderValue(hv.0.into(), hv.1.into())
3249
}
3350
}
3451

@@ -60,6 +77,16 @@ impl fmt::Display for HeaderErrorKind {
6077
}
6178
}
6279

80+
impl<T> HeaderError<T> {
81+
/// Returns the [SpansKind] associated with this error.
82+
pub fn spanskind(&self) -> SpansKind {
83+
match self.kind {
84+
HeaderErrorKind::DuplicateEntry => SpansKind::DuplicationError,
85+
_ => SpansKind::Error,
86+
}
87+
}
88+
}
89+
6390
/// Indicates a value prefixed by an optional namespace.
6491
/// `Foo::Bar` with optional `Foo` specified being
6592
/// ```rust,ignore
@@ -78,24 +105,24 @@ impl fmt::Display for HeaderErrorKind {
78105
/// ```
79106
#[derive(Debug, Eq, PartialEq)]
80107
#[doc(hidden)]
81-
pub struct Namespaced {
82-
pub namespace: Option<(String, Location)>,
83-
pub member: (String, Location),
108+
pub struct Namespaced<T> {
109+
pub namespace: Option<(String, T)>,
110+
pub member: (String, T),
84111
}
85112

86113
#[derive(Debug, Eq, PartialEq)]
87114
#[doc(hidden)]
88-
pub enum Setting {
115+
pub enum Setting<T> {
89116
/// A value like `YaccKind::Grmtools`
90-
Unitary(Namespaced),
117+
Unitary(Namespaced<T>),
91118
/// A value like `YaccKind::Original(UserActions)`.
92119
/// In that example the field ctor would be: `Namespaced { namespace: "YaccKind", member: "Original" }`.
93120
/// The field would be `Namespaced{ None, UserActions }`.
94121
Constructor {
95-
ctor: Namespaced,
96-
arg: Namespaced,
122+
ctor: Namespaced<T>,
123+
arg: Namespaced<T>,
97124
},
98-
Num(u64, Location),
125+
Num(u64, T),
99126
}
100127

101128
/// Parser for the `%grmtools` section
@@ -111,9 +138,48 @@ pub struct GrmtoolsSectionParser<'input> {
111138
/// like booleans, numeric types, and string values.
112139
#[derive(Debug, Eq, PartialEq)]
113140
#[doc(hidden)]
114-
pub enum Value {
115-
Flag(bool, Location),
116-
Setting(Setting),
141+
pub enum Value<T> {
142+
Flag(bool, T),
143+
Setting(Setting<T>),
144+
}
145+
146+
impl From<Value<Span>> for Value<Location> {
147+
fn from(v: Value<Span>) -> Value<Location> {
148+
match v {
149+
Value::Flag(flag, u) => Value::Flag(flag, u.into()),
150+
Value::Setting(s) => Value::Setting(match s {
151+
Setting::Unitary(Namespaced {
152+
namespace,
153+
member: (m, ml),
154+
}) => Setting::Unitary(Namespaced {
155+
namespace: namespace.map(|(n, nl)| (n, nl.into())),
156+
member: (m, ml.into()),
157+
}),
158+
Setting::Constructor {
159+
ctor:
160+
Namespaced {
161+
namespace: ctor_ns,
162+
member: (ctor_m, ctor_ml),
163+
},
164+
arg:
165+
Namespaced {
166+
namespace: arg_ns,
167+
member: (arg_m, arg_ml),
168+
},
169+
} => Setting::Constructor {
170+
ctor: Namespaced {
171+
namespace: ctor_ns.map(|(ns, ns_l)| (ns, ns_l.into())),
172+
member: (ctor_m, ctor_ml.into()),
173+
},
174+
arg: Namespaced {
175+
namespace: arg_ns.map(|(ns, ns_l)| (ns, ns_l.into())),
176+
member: (arg_m, arg_ml.into()),
177+
},
178+
},
179+
Setting::Num(num, num_loc) => Setting::Num(num, num_loc.into()),
180+
}),
181+
}
182+
}
117183
}
118184

119185
lazy_static! {
@@ -127,11 +193,11 @@ lazy_static! {
127193

128194
const MAGIC: &str = "%grmtools";
129195

130-
fn add_duplicate_occurrence(
131-
errs: &mut Vec<HeaderError>,
196+
fn add_duplicate_occurrence<T: Eq + PartialEq + Clone>(
197+
errs: &mut Vec<HeaderError<T>>,
132198
kind: HeaderErrorKind,
133-
orig_loc: Location,
134-
dup_loc: Location,
199+
orig_loc: T,
200+
dup_loc: T,
135201
) {
136202
if !errs.iter_mut().any(|e| {
137203
if e.kind == kind && e.locations[0] == orig_loc {
@@ -152,18 +218,18 @@ impl<'input> GrmtoolsSectionParser<'input> {
152218
pub fn parse_value(
153219
&'_ self,
154220
mut i: usize,
155-
) -> Result<(String, Location, Value, usize), HeaderError> {
221+
) -> Result<(String, Span, Value<Span>, usize), HeaderError<Span>> {
156222
if let Some(j) = self.lookahead_is("!", i) {
157223
let (flag_name, k) = self.parse_name(j)?;
158224
Ok((
159225
flag_name,
160-
Location::Span(Span::new(j, k)),
161-
Value::Flag(false, Location::Span(Span::new(i, k))),
226+
Span::new(j, k),
227+
Value::Flag(false, Span::new(i, k)),
162228
self.parse_ws(k),
163229
))
164230
} else {
165231
let (key_name, j) = self.parse_name(i)?;
166-
let key_span = Location::Span(Span::new(i, j));
232+
let key_span = Span::new(i, j);
167233
i = self.parse_ws(j);
168234
if let Some(j) = self.lookahead_is(":", i) {
169235
i = self.parse_ws(j);
@@ -173,7 +239,7 @@ impl<'input> GrmtoolsSectionParser<'input> {
173239
let num_str = &self.src[num_span.start()..num_span.end()];
174240
// If the above regex matches we expect this to succeed.
175241
let num = str::parse::<u64>(num_str).unwrap();
176-
let val = Setting::Num(num, Location::Span(num_span));
242+
let val = Setting::Num(num, num_span);
177243
i = self.parse_ws(num_span.end());
178244
Ok((key_name, key_span, Value::Setting(val), i))
179245
}
@@ -197,7 +263,7 @@ impl<'input> GrmtoolsSectionParser<'input> {
197263
} else {
198264
Err(HeaderError {
199265
kind: HeaderErrorKind::ExpectedToken(')'),
200-
locations: vec![Location::Span(Span::new(i, i))],
266+
locations: vec![Span::new(i, i)],
201267
})
202268
}
203269
} else {
@@ -211,20 +277,23 @@ impl<'input> GrmtoolsSectionParser<'input> {
211277
}
212278
}
213279
} else {
214-
Ok((key_name, key_span.clone(), Value::Flag(true, key_span), i))
280+
Ok((key_name, key_span, Value::Flag(true, key_span), i))
215281
}
216282
}
217283
}
218284

219-
fn parse_namespaced(&self, mut i: usize) -> Result<(Namespaced, usize), HeaderError> {
285+
fn parse_namespaced(
286+
&self,
287+
mut i: usize,
288+
) -> Result<(Namespaced<Span>, usize), HeaderError<Span>> {
220289
// Either a name alone, or a namespace which will be followed by a member.
221290
let (name, j) = self.parse_name(i)?;
222-
let name_span = Location::Span(Span::new(i, j));
291+
let name_span = Span::new(i, j);
223292
i = self.parse_ws(j);
224293
if let Some(j) = self.lookahead_is("::", i) {
225294
i = self.parse_ws(j);
226295
let (member_val, j) = self.parse_name(i)?;
227-
let member_val_span = Location::Span(Span::new(i, j));
296+
let member_val_span = Span::new(i, j);
228297
i = self.parse_ws(j);
229298
Ok((
230299
Namespaced {
@@ -258,7 +327,7 @@ impl<'input> GrmtoolsSectionParser<'input> {
258327
}
259328

260329
#[allow(clippy::type_complexity)]
261-
pub fn parse(&'_ self) -> Result<(Header, usize), Vec<HeaderError>> {
330+
pub fn parse(&'_ self) -> Result<(Header<Span>, usize), Vec<HeaderError<Span>>> {
262331
let mut errs = Vec::new();
263332
if let Some(mut i) = self.lookahead_is(MAGIC, self.parse_ws(0)) {
264333
let mut ret = Header::new();
@@ -276,16 +345,16 @@ impl<'input> GrmtoolsSectionParser<'input> {
276345
};
277346
match ret.entry(key) {
278347
Entry::Occupied(orig) => {
279-
let (orig_loc, _): &(Location, Value) = orig.get();
348+
let HeaderValue(orig_loc, _): &HeaderValue<Span> = orig.get();
280349
add_duplicate_occurrence(
281350
&mut errs,
282351
HeaderErrorKind::DuplicateEntry,
283-
orig_loc.clone(),
352+
*orig_loc,
284353
key_loc,
285354
)
286355
}
287356
Entry::Vacant(entry) => {
288-
entry.insert((key_loc, val));
357+
entry.insert(HeaderValue(key_loc, val));
289358
}
290359
}
291360
if let Some(j) = self.lookahead_is(",", j) {
@@ -305,32 +374,29 @@ impl<'input> GrmtoolsSectionParser<'input> {
305374
} else {
306375
errs.push(HeaderError {
307376
kind: HeaderErrorKind::ExpectedToken('}'),
308-
locations: vec![Location::Span(Span::new(
309-
section_start_pos,
310-
self.src.len(),
311-
))],
377+
locations: vec![Span::new(section_start_pos, self.src.len())],
312378
});
313379
Err(errs)
314380
}
315381
} else {
316382
errs.push(HeaderError {
317383
kind: HeaderErrorKind::ExpectedToken('{'),
318-
locations: vec![Location::Span(Span::new(i, i))],
384+
locations: vec![Span::new(i, i)],
319385
});
320386
Err(errs)
321387
}
322388
} else if self.required {
323389
errs.push(HeaderError {
324390
kind: HeaderErrorKind::MissingGrmtoolsSection,
325-
locations: vec![Location::Span(Span::new(0, 0))],
391+
locations: vec![Span::new(0, 0)],
326392
});
327393
Err(errs)
328394
} else {
329395
Ok((Header::new(), 0))
330396
}
331397
}
332398

333-
fn parse_name(&self, i: usize) -> Result<(String, usize), HeaderError> {
399+
fn parse_name(&self, i: usize) -> Result<(String, usize), HeaderError<Span>> {
334400
match RE_NAME.find(&self.src[i..]) {
335401
Some(m) => {
336402
assert_eq!(m.start(), 0);
@@ -341,7 +407,7 @@ impl<'input> GrmtoolsSectionParser<'input> {
341407
}
342408
None => Err(HeaderError {
343409
kind: HeaderErrorKind::IllegalName,
344-
locations: vec![Location::Span(Span::new(i, i))],
410+
locations: vec![Span::new(i, i)],
345411
}),
346412
}
347413
}
@@ -363,11 +429,11 @@ impl<'input> GrmtoolsSectionParser<'input> {
363429
}
364430

365431
/// A data structure representation of the %grmtools section.
366-
pub type Header = MarkMap<String, (Location, Value)>;
432+
pub type Header<T> = MarkMap<String, HeaderValue<T>>;
367433

368-
impl TryFrom<YaccKind> for Value {
369-
type Error = HeaderError;
370-
fn try_from(kind: YaccKind) -> Result<Value, HeaderError> {
434+
impl TryFrom<YaccKind> for Value<Location> {
435+
type Error = HeaderError<Location>;
436+
fn try_from(kind: YaccKind) -> Result<Value<Location>, HeaderError<Location>> {
371437
let from_loc = Location::Other("From<YaccKind>".to_string());
372438
Ok(match kind {
373439
YaccKind::Grmtools => Value::Setting(Setting::Unitary(Namespaced {
@@ -402,9 +468,9 @@ impl TryFrom<YaccKind> for Value {
402468
}
403469
}
404470

405-
impl TryFrom<&Value> for YaccKind {
406-
type Error = HeaderError;
407-
fn try_from(value: &Value) -> Result<YaccKind, HeaderError> {
471+
impl<T: Clone> TryFrom<&Value<T>> for YaccKind {
472+
type Error = HeaderError<T>;
473+
fn try_from(value: &Value<T>) -> Result<YaccKind, HeaderError<T>> {
408474
let mut err_locs = Vec::new();
409475
match value {
410476
Value::Flag(_, loc) => Err(HeaderError {

cfgrammar/src/lib/markmap.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,10 @@ impl<K: Ord + Clone, V> MarkMap<K, V> {
383383
/// For the behavior of exclusive or mark the behavior as also `Mark::Required`, then after merge call `missing()`
384384
/// to check all required values.
385385
#[doc(hidden)]
386-
pub fn merge_from(&mut self, mut other: Self) -> Result<(), MergeError<K, Box<V>>> {
386+
pub fn merge_from<U>(&mut self, mut other: MarkMap<K, U>) -> Result<(), MergeError<K, Box<V>>>
387+
where
388+
U: Into<V>,
389+
{
387390
for (their_key, their_mark, their_val) in other.contents.drain(..) {
388391
let pos = self.contents.binary_search_by(|x| x.0.cmp(&their_key));
389392
match pos {
@@ -402,21 +405,21 @@ impl<K: Ord + Clone, V> MarkMap<K, V> {
402405
if my_val.is_some() && their_val.is_some() {
403406
return Err(MergeError::Exclusivity(
404407
their_key,
405-
Box::new(their_val.unwrap()),
408+
Box::new(their_val.unwrap().into()),
406409
));
407410
} else if my_val.is_none() {
408-
*my_val = their_val;
411+
*my_val = their_val.map(|u| u.into());
409412
}
410413
} else if merge_behavior == theirs_mark && their_val.is_some()
411414
|| merge_behavior == ours_mark && my_val.is_none()
412415
{
413416
*my_mark = their_mark;
414-
*my_val = their_val;
417+
*my_val = their_val.map(|u| u.into());
415418
}
416419
}
417420
Err(pos) => {
418421
self.contents
419-
.insert(pos, (their_key, their_mark, their_val));
422+
.insert(pos, (their_key, their_mark, their_val.map(|u| u.into())));
420423
}
421424
}
422425
}
@@ -710,7 +713,7 @@ mod test {
710713
fn test_merge_empty() {
711714
{
712715
let mut ours: MarkMap<&str, &str> = MarkMap::new();
713-
let theirs = MarkMap::new();
716+
let theirs: MarkMap<&str, &str> = MarkMap::new();
714717
assert!(ours.merge_from(theirs).is_ok());
715718
}
716719
{

0 commit comments

Comments
 (0)