11use crate :: {
22 markmap:: { Entry , MarkMap } ,
3- yacc:: { ParserError , YaccKind , YaccOriginalActionKind } ,
3+ yacc:: {
4+ parser:: SpansKind , YaccGrammarError , YaccGrammarErrorKind , YaccKind , YaccOriginalActionKind ,
5+ } ,
46 Location , Span ,
57} ;
68use 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
119185lazy_static ! {
@@ -127,11 +193,11 @@ lazy_static! {
127193
128194const 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 {
0 commit comments