@@ -2,12 +2,12 @@ use std::{error, fmt, str::FromStr};
2
2
3
3
use itertools:: Itertools ;
4
4
use pest:: {
5
- error:: Error as PestError ,
5
+ error:: { Error as PestError , ErrorVariant , LineColLocation } ,
6
6
iterators:: { Pair , Pairs } ,
7
7
Parser ,
8
8
} ;
9
9
10
- use crate :: load_file:: { AddressMode , Core , Field , Instruction , Modifier , Opcode } ;
10
+ use crate :: load_file:: { AddressMode , Core , Field , Instruction , Modifier , Opcode , Value } ;
11
11
12
12
#[ derive( Debug ) ]
13
13
pub struct Error {
@@ -30,13 +30,25 @@ impl Error {
30
30
}
31
31
}
32
32
33
- impl < Rule > From < PestError < Rule > > for Error {
33
+ impl From < PestError < Rule > > for Error {
34
34
fn from ( pest_error : PestError < Rule > ) -> Error {
35
35
Error {
36
36
details : format ! (
37
- "Error parsing rule '{}' at location '{:?}" ,
38
- stringify!( Rule ) ,
39
- pest_error. line_col
37
+ "Parse error: {} {}" ,
38
+ match pest_error. variant {
39
+ ErrorVariant :: ParsingError {
40
+ positives,
41
+ negatives,
42
+ } => format!( "expected one of {:?}, none of {:?}" , positives, negatives) ,
43
+ ErrorVariant :: CustomError { message } => message,
44
+ } ,
45
+ match pest_error. line_col {
46
+ LineColLocation :: Pos ( ( line, col) ) => format!( "at line {} column {}" , line, col) ,
47
+ LineColLocation :: Span ( ( start_line, start_col) , ( end_line, end_col) ) => format!(
48
+ "from line {} column {} to line {} column {}" ,
49
+ start_line, start_col, end_line, end_col
50
+ ) ,
51
+ }
40
52
) ,
41
53
}
42
54
}
@@ -59,7 +71,7 @@ pub fn parse(file_contents: &str) -> Result<Core, Error> {
59
71
60
72
let mut core = Core :: default ( ) ;
61
73
62
- let parse_result = RedcodeParser :: parse ( Rule :: AssemblyFile , file_contents) ?
74
+ let parse_result = RedcodeParser :: parse ( Rule :: RedcodeFile , file_contents) ?
63
75
. next ( )
64
76
. ok_or_else ( Error :: no_input) ?;
65
77
@@ -152,8 +164,12 @@ fn parse_field(field_pair: Pair<Rule>) -> Field {
152
164
}
153
165
}
154
166
155
- fn parse_value ( value_pair : Pair < Rule > ) -> i32 {
156
- i32:: from_str_radix ( value_pair. as_str ( ) , 10 ) . unwrap ( )
167
+ fn parse_value ( value_pair : Pair < Rule > ) -> Value {
168
+ if value_pair. as_rule ( ) == Rule :: Number {
169
+ Value :: Literal ( i32:: from_str_radix ( value_pair. as_str ( ) , 10 ) . unwrap ( ) )
170
+ } else {
171
+ Value :: Label ( value_pair. as_str ( ) . to_owned ( ) )
172
+ }
157
173
}
158
174
159
175
#[ cfg( test) ]
@@ -270,37 +286,31 @@ mod tests {
270
286
271
287
#[ test]
272
288
fn parse_label ( ) {
273
- parses_to ! {
274
- parser: RedcodeParser ,
275
- input: "some_label\n some_label2 dat 0, 0" ,
276
- rule: Rule :: Instruction ,
277
- tokens: [
278
- Label ( 0 , 10 ) ,
279
- Label ( 11 , 22 ) ,
280
- Operation ( 23 , 26 , [
281
- Opcode ( 23 , 26 )
282
- ] ) ,
283
- Field ( 27 , 28 , [
284
- Expr ( 27 , 28 , [
285
- Number ( 27 , 28 )
286
- ] )
287
- ] ) ,
288
- Field ( 30 , 31 , [
289
- Expr ( 30 , 31 , [
290
- Number ( 30 , 31 )
291
- ] )
292
- ] ) ,
293
- ]
289
+ for & ( label_input, start, end) in [
290
+ ( "some_label" , 0 , 10 ) ,
291
+ ( "some_label2" , 0 , 11 ) ,
292
+ ( "a: " , 0 , 1 ) ,
293
+ ( " a " , 1 , 2 ) ,
294
+ ( "a :" , 0 , 1 ) ,
295
+ ]
296
+ . iter ( )
297
+ {
298
+ parses_to ! {
299
+ parser: RedcodeParser ,
300
+ input: label_input,
301
+ rule: Rule :: LabelDeclaration ,
302
+ tokens: [ Label ( start, end) ]
303
+ }
294
304
}
295
305
}
296
306
297
307
#[ test]
298
308
fn parse_simple_file ( ) {
299
309
let simple_input = "
300
- begin
301
- mov 1, 3 ; make sure comments parse out
310
+ preload
311
+ begin: mov 1, 3 ; make sure comments parse out
302
312
mov 100, #12
303
- loop
313
+ loop:
304
314
main dat 0, 0
305
315
jmp 123, 45
306
316
" ;
@@ -317,15 +327,15 @@ mod tests {
317
327
) ;
318
328
expected_core. set (
319
329
2 ,
320
- Instruction :: new ( Opcode :: Dat , Field :: direct ( 0 ) , Field :: direct ( 0 ) ) ,
330
+ Instruction :: new ( Opcode :: Dat , Field :: immediate ( 0 ) , Field :: immediate ( 0 ) ) ,
321
331
) ;
322
332
expected_core. set (
323
333
3 ,
324
334
Instruction :: new ( Opcode :: Jmp , Field :: direct ( 123 ) , Field :: direct ( 45 ) ) ,
325
335
) ;
326
336
327
- expected_core. add_labels ( 0 , vec ! [ "begin" ] ) . unwrap ( ) ;
328
- expected_core. add_labels ( 2 , vec ! [ "main ", "loop " ] ) . unwrap ( ) ;
337
+ expected_core. add_labels ( 0 , & [ "preload" , "begin" ] ) . unwrap ( ) ;
338
+ expected_core. add_labels ( 2 , & [ "loop ", "main " ] ) . unwrap ( ) ;
329
339
330
340
assert_eq ! ( parse( simple_input) . unwrap( ) , expected_core) ;
331
341
}
0 commit comments