1
1
use std:: fmt:: Write ;
2
+ use std:: iter;
2
3
use std:: iter:: Peekable ;
3
4
use std:: path:: Path ;
4
5
@@ -31,10 +32,10 @@ enum Def<'a> {
31
32
Module ( Module < ' a > ) ,
32
33
}
33
34
34
- /// A symbol, either a leaf or with modifiers.
35
+ /// A symbol, either a leaf or with modifiers with optional deprecation .
35
36
enum Symbol < ' a > {
36
37
Single ( char ) ,
37
- Multi ( Vec < ( ModifierSet < & ' a str > , char ) > ) ,
38
+ Multi ( Vec < ( ModifierSet < & ' a str > , char , Option < & ' a str > ) > ) ,
38
39
}
39
40
40
41
/// A single line during parsing.
@@ -46,6 +47,15 @@ enum Line<'a> {
46
47
ModuleEnd ,
47
48
Symbol ( & ' a str , Option < char > ) ,
48
49
Variant ( ModifierSet < & ' a str > , char ) ,
50
+ Eof ,
51
+ }
52
+
53
+ #[ derive( Debug , Copy , Clone ) ]
54
+ enum Declaration < ' a > {
55
+ ModuleStart ( & ' a str , Option < & ' a str > ) ,
56
+ ModuleEnd ,
57
+ Symbol ( & ' a str , Option < char > , Option < & ' a str > ) ,
58
+ Variant ( ModifierSet < & ' a str > , char , Option < & ' a str > ) ,
49
59
}
50
60
51
61
fn main ( ) {
@@ -66,11 +76,43 @@ fn process(buf: &mut String, file: &Path, name: &str, desc: &str) {
66
76
67
77
let text = std:: fs:: read_to_string ( file) . unwrap ( ) ;
68
78
let mut line_nr = 0 ;
79
+ let mut deprecation = None ;
69
80
let mut iter = text
70
81
. lines ( )
71
82
. inspect ( |_| line_nr += 1 )
72
83
. map ( tokenize)
73
- . filter ( |line| !matches ! ( line, Ok ( Line :: Blank ) ) )
84
+ . chain ( iter:: once ( Ok ( Line :: Eof ) ) )
85
+ . filter_map ( |line| match line {
86
+ Err ( message) => Some ( Err ( message) ) ,
87
+ Ok ( Line :: Blank ) => None ,
88
+ Ok ( Line :: Deprecated ( message) ) => {
89
+ if deprecation. is_some ( ) {
90
+ Some ( Err ( String :: from ( "duplicate `@deprecated:`" ) ) )
91
+ } else {
92
+ deprecation = Some ( message) ;
93
+ None
94
+ }
95
+ }
96
+ Ok ( Line :: ModuleStart ( name) ) => {
97
+ Some ( Ok ( Declaration :: ModuleStart ( name, deprecation. take ( ) ) ) )
98
+ }
99
+ Ok ( Line :: ModuleEnd ) => {
100
+ if deprecation. is_some ( ) {
101
+ Some ( Err ( String :: from ( "dangling `@deprecated:`" ) ) )
102
+ } else {
103
+ Some ( Ok ( Declaration :: ModuleEnd ) )
104
+ }
105
+ }
106
+ Ok ( Line :: Symbol ( name, c) ) => {
107
+ Some ( Ok ( Declaration :: Symbol ( name, c, deprecation. take ( ) ) ) )
108
+ }
109
+ Ok ( Line :: Variant ( modifiers, c) ) => {
110
+ Some ( Ok ( Declaration :: Variant ( modifiers, c, deprecation. take ( ) ) ) )
111
+ }
112
+ Ok ( Line :: Eof ) => {
113
+ deprecation. map ( |_| Err ( String :: from ( "dangling `@deprecated:`" ) ) )
114
+ }
115
+ } )
74
116
. peekable ( ) ;
75
117
76
118
let module = match parse ( & mut iter) {
@@ -150,29 +192,26 @@ fn decode_char(text: &str) -> StrResult<char> {
150
192
151
193
/// Turns a stream of lines into a list of definitions.
152
194
fn parse < ' a > (
153
- p : & mut Peekable < impl Iterator < Item = StrResult < Line < ' a > > > > ,
195
+ p : & mut Peekable < impl Iterator < Item = StrResult < Declaration < ' a > > > > ,
154
196
) -> StrResult < Vec < ( & ' a str , Binding < ' a > ) > > {
155
197
let mut defs = vec ! [ ] ;
156
- let mut deprecation = None ;
157
198
loop {
158
199
match p. next ( ) . transpose ( ) ? {
159
- None | Some ( Line :: ModuleEnd ) => {
160
- if let Some ( message) = deprecation {
161
- return Err ( format ! ( "dangling `@deprecated: {}`" , message) ) ;
162
- }
200
+ None | Some ( Declaration :: ModuleEnd ) => {
163
201
break ;
164
202
}
165
- Some ( Line :: Deprecated ( message) ) => deprecation = Some ( message) ,
166
- Some ( Line :: Symbol ( name, c) ) => {
203
+ Some ( Declaration :: Symbol ( name, c, deprecation) ) => {
167
204
let mut variants = vec ! [ ] ;
168
- while let Some ( Line :: Variant ( name, c) ) = p. peek ( ) . cloned ( ) . transpose ( ) ? {
169
- variants. push ( ( name, c) ) ;
205
+ while let Some ( Declaration :: Variant ( name, c, deprecation) ) =
206
+ p. peek ( ) . cloned ( ) . transpose ( ) ?
207
+ {
208
+ variants. push ( ( name, c, deprecation) ) ;
170
209
p. next ( ) ;
171
210
}
172
211
173
212
let symbol = if !variants. is_empty ( ) {
174
213
if let Some ( c) = c {
175
- variants. insert ( 0 , ( ModifierSet :: default ( ) , c) ) ;
214
+ variants. insert ( 0 , ( ModifierSet :: default ( ) , c, None ) ) ;
176
215
}
177
216
Symbol :: Multi ( variants)
178
217
} else {
@@ -181,9 +220,8 @@ fn parse<'a>(
181
220
} ;
182
221
183
222
defs. push ( ( name, Binding { def : Def :: Symbol ( symbol) , deprecation } ) ) ;
184
- deprecation = None ;
185
223
}
186
- Some ( Line :: ModuleStart ( name) ) => {
224
+ Some ( Declaration :: ModuleStart ( name, deprecation ) ) => {
187
225
let module_defs = parse ( p) ?;
188
226
defs. push ( (
189
227
name,
@@ -192,7 +230,6 @@ fn parse<'a>(
192
230
deprecation,
193
231
} ,
194
232
) ) ;
195
- deprecation = None ;
196
233
}
197
234
other => return Err ( format ! ( "expected definition, found {other:?}" ) ) ,
198
235
}
0 commit comments