@@ -87,18 +87,29 @@ pub fn symbols(input: TokenStream) -> TokenStream {
8787 let mut prefill_stream = quote ! { } ;
8888 let mut counter = 0u32 ;
8989 let mut keys = HashSet :: < String > :: new ( ) ;
90+ let mut prev_key: Option < String > = None ;
91+ let mut errors = Vec :: < String > :: new ( ) ;
9092
91- let mut check_dup = |str : & str | {
93+ let mut check_dup = |str : & str , errors : & mut Vec < String > | {
9294 if !keys. insert ( str. to_string ( ) ) {
93- panic ! ( "Symbol `{}` is duplicated" , str ) ;
95+ errors . push ( format ! ( "Symbol `{}` is duplicated" , str ) ) ;
9496 }
9597 } ;
9698
99+ let mut check_order = |str : & str , errors : & mut Vec < String > | {
100+ if let Some ( ref prev_str) = prev_key {
101+ if str < prev_str {
102+ errors. push ( format ! ( "Symbol `{}` must precede `{}`" , str , prev_str) ) ;
103+ }
104+ }
105+ prev_key = Some ( str. to_string ( ) ) ;
106+ } ;
107+
97108 // Generate the listed keywords.
98109 for keyword in & input. keywords . 0 {
99110 let name = & keyword. name ;
100111 let value = & keyword. value ;
101- check_dup ( & value. value ( ) ) ;
112+ check_dup ( & value. value ( ) , & mut errors ) ;
102113 prefill_stream. extend ( quote ! {
103114 #value,
104115 } ) ;
@@ -116,7 +127,8 @@ pub fn symbols(input: TokenStream) -> TokenStream {
116127 Some ( value) => value. value ( ) ,
117128 None => name. to_string ( ) ,
118129 } ;
119- check_dup ( & value) ;
130+ check_dup ( & value, & mut errors) ;
131+ check_order ( & name. to_string ( ) , & mut errors) ;
120132 prefill_stream. extend ( quote ! {
121133 #value,
122134 } ) ;
@@ -131,7 +143,7 @@ pub fn symbols(input: TokenStream) -> TokenStream {
131143 // Generate symbols for the strings "0", "1", ..., "9".
132144 for n in 0 ..10 {
133145 let n = n. to_string ( ) ;
134- check_dup ( & n) ;
146+ check_dup ( & n, & mut errors ) ;
135147 prefill_stream. extend ( quote ! {
136148 #n,
137149 } ) ;
@@ -141,6 +153,13 @@ pub fn symbols(input: TokenStream) -> TokenStream {
141153 counter += 1 ;
142154 }
143155
156+ if !errors. is_empty ( ) {
157+ for error in errors. into_iter ( ) {
158+ eprintln ! ( "error: {}" , error)
159+ }
160+ panic ! ( "errors in `Keywords` and/or `Symbols`" ) ;
161+ }
162+
144163 let tt = TokenStream :: from ( quote ! {
145164 macro_rules! keywords {
146165 ( ) => {
0 commit comments