@@ -87,18 +87,29 @@ pub fn symbols(input: TokenStream) -> TokenStream {
87
87
let mut prefill_stream = quote ! { } ;
88
88
let mut counter = 0u32 ;
89
89
let mut keys = HashSet :: < String > :: new ( ) ;
90
+ let mut prev_key: Option < String > = None ;
91
+ let mut errors = Vec :: < String > :: new ( ) ;
90
92
91
- let mut check_dup = |str : & str | {
93
+ let mut check_dup = |str : & str , errors : & mut Vec < String > | {
92
94
if !keys. insert ( str. to_string ( ) ) {
93
- panic ! ( "Symbol `{}` is duplicated" , str ) ;
95
+ errors . push ( format ! ( "Symbol `{}` is duplicated" , str ) ) ;
94
96
}
95
97
} ;
96
98
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
+
97
108
// Generate the listed keywords.
98
109
for keyword in & input. keywords . 0 {
99
110
let name = & keyword. name ;
100
111
let value = & keyword. value ;
101
- check_dup ( & value. value ( ) ) ;
112
+ check_dup ( & value. value ( ) , & mut errors ) ;
102
113
prefill_stream. extend ( quote ! {
103
114
#value,
104
115
} ) ;
@@ -116,7 +127,8 @@ pub fn symbols(input: TokenStream) -> TokenStream {
116
127
Some ( value) => value. value ( ) ,
117
128
None => name. to_string ( ) ,
118
129
} ;
119
- check_dup ( & value) ;
130
+ check_dup ( & value, & mut errors) ;
131
+ check_order ( & name. to_string ( ) , & mut errors) ;
120
132
prefill_stream. extend ( quote ! {
121
133
#value,
122
134
} ) ;
@@ -131,7 +143,7 @@ pub fn symbols(input: TokenStream) -> TokenStream {
131
143
// Generate symbols for the strings "0", "1", ..., "9".
132
144
for n in 0 ..10 {
133
145
let n = n. to_string ( ) ;
134
- check_dup ( & n) ;
146
+ check_dup ( & n, & mut errors ) ;
135
147
prefill_stream. extend ( quote ! {
136
148
#n,
137
149
} ) ;
@@ -141,6 +153,13 @@ pub fn symbols(input: TokenStream) -> TokenStream {
141
153
counter += 1 ;
142
154
}
143
155
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
+
144
163
let tt = TokenStream :: from ( quote ! {
145
164
macro_rules! keywords {
146
165
( ) => {
0 commit comments