1- // Copyright 2024 Cornell University
2- // released under MIT License
3- // author: Nikil Shyamunder <nikil.shyamsunder@gmail.com>
4- // author: Kevin Laeufer <laeufer@cornell.edu>
5-
61use baa:: BitVecValue ;
72use pest:: error:: InputLocation ;
83use pest:: iterators:: Pairs ;
@@ -39,6 +34,36 @@ pub struct ParserContext<'a> {
3934}
4035
4136impl < ' a > ParserContext < ' a > {
37+ // Helper method for expected rule errors
38+ fn expect_rule < T > (
39+ & mut self ,
40+ option : Option < T > ,
41+ context_pair : & pest:: iterators:: Pair < Rule > ,
42+ message : & str ,
43+ ) -> Result < T , String > {
44+ option. ok_or_else ( || {
45+ let msg = message. to_string ( ) ;
46+ self . handler
47+ . emit_diagnostic_parsing ( & msg, self . fileid , context_pair, Level :: Error ) ;
48+ msg
49+ } )
50+ }
51+
52+ // Helper for getting symbol id from name with error handling
53+ fn get_symbol_id (
54+ & mut self ,
55+ name : & str ,
56+ context_pair : & pest:: iterators:: Pair < Rule > ,
57+ message : & str ,
58+ ) -> Result < SymbolId , String > {
59+ self . st . symbol_id_from_name ( name) . ok_or_else ( || {
60+ let msg = format ! ( "{}: {}" , message, name) ;
61+ self . handler
62+ . emit_diagnostic_parsing ( & msg, self . fileid , context_pair, Level :: Error ) ;
63+ msg
64+ } )
65+ }
66+
4267 pub fn parse_boxed_expr ( & mut self , pairs : Pairs < Rule > ) -> Result < BoxedExpr , String > {
4368 PRATT_PARSER
4469 . map_primary ( |primary| {
@@ -62,7 +87,7 @@ impl<'a> ParserContext<'a> {
6287 self . handler . emit_diagnostic_parsing (
6388 & msg,
6489 self . fileid ,
65- primary,
90+ & primary,
6691 Level :: Error ,
6792 ) ;
6893 Err ( msg)
@@ -71,8 +96,12 @@ impl<'a> ParserContext<'a> {
7196 }
7297 Rule :: dont_care => Ok ( BoxedExpr :: DontCare ( start, end) ) ,
7398 Rule :: slice => {
74- let mut inner_rules = primary. into_inner ( ) ;
75- let path_rule = inner_rules. next ( ) . unwrap ( ) ;
99+ let mut inner_rules = primary. clone ( ) . into_inner ( ) ;
100+ let path_rule = self . expect_rule (
101+ inner_rules. next ( ) ,
102+ & primary,
103+ "Expected path rule in slice expression" ,
104+ ) ?;
76105 let path_id = self . parse_boxed_expr ( Pairs :: single ( path_rule) ) ?;
77106 let idx1_rule = inner_rules. next ( ) . unwrap ( ) ;
78107 let idx1 = idx1_rule. as_str ( ) . parse :: < u32 > ( ) . unwrap ( ) ;
@@ -159,18 +188,22 @@ impl<'a> ParserContext<'a> {
159188 }
160189
161190 fn parse_struct ( & mut self , pair : pest:: iterators:: Pair < Rule > ) -> Result < StructId , String > {
162- let mut inner_rules = pair. into_inner ( ) ;
163- let struct_name = inner_rules. next ( ) . unwrap ( ) . as_str ( ) ;
164- let ( pins, _symbols) = self . parse_fields ( inner_rules. next ( ) . unwrap ( ) ) ?;
191+ let mut inner_rules = pair. clone ( ) . into_inner ( ) ;
192+ let struct_name = self
193+ . expect_rule ( inner_rules. next ( ) , & pair, "Expected struct name" ) ?
194+ . as_str ( ) ;
195+ let next_rule = self . expect_rule ( inner_rules. next ( ) , & pair, "Expected fields in struct" ) ?;
196+ let ( pins, _symbols) = self . parse_fields ( next_rule) ?;
165197 let struct_id = self . st . add_struct ( struct_name. to_string ( ) , pins) ;
166198 Ok ( struct_id)
167199 }
168200
169201 fn parse_transaction ( & mut self , pair : pest:: iterators:: Pair < Rule > ) -> Result < ( ) , String > {
170202 match pair. as_rule ( ) {
171203 Rule :: fun => {
172- let mut inner_rules = pair. into_inner ( ) ;
173- let id_pair = inner_rules. next ( ) . unwrap ( ) ;
204+ let mut inner_rules = pair. clone ( ) . into_inner ( ) ;
205+ let id_pair =
206+ self . expect_rule ( inner_rules. next ( ) , & pair, "Expected function identifier" ) ?;
174207 let id = id_pair. as_str ( ) ;
175208 self . tr . name = id. to_string ( ) ;
176209
@@ -202,7 +235,7 @@ impl<'a> ParserContext<'a> {
202235 self . handler . emit_diagnostic_parsing (
203236 & msg,
204237 self . fileid ,
205- inner_pair,
238+ & inner_pair,
206239 Level :: Error ,
207240 ) ;
208241 return Err ( msg) ;
@@ -212,7 +245,12 @@ impl<'a> ParserContext<'a> {
212245
213246 if let Some ( arglist_pair) = inner_rules. peek ( ) {
214247 if arglist_pair. as_rule ( ) == Rule :: arglist {
215- self . tr . args = self . parse_arglist ( inner_rules. next ( ) . unwrap ( ) ) ?;
248+ let arg_rules = self . expect_rule (
249+ inner_rules. next ( ) ,
250+ & arglist_pair,
251+ "Expected argument list" ,
252+ ) ?;
253+ self . tr . args = self . parse_arglist ( arg_rules) ?;
216254 } else {
217255 self . tr . args = Vec :: new ( ) ;
218256 }
@@ -229,7 +267,7 @@ impl<'a> ParserContext<'a> {
229267 pair. as_rule( )
230268 ) ;
231269 self . handler
232- . emit_diagnostic_parsing ( & msg, self . fileid , pair, Level :: Error ) ;
270+ . emit_diagnostic_parsing ( & msg, self . fileid , & pair, Level :: Error ) ;
233271 Err ( msg)
234272 }
235273 }
@@ -260,7 +298,7 @@ impl<'a> ParserContext<'a> {
260298 self . handler . emit_diagnostic_parsing (
261299 & msg,
262300 self . fileid ,
263- inner_pair,
301+ & inner_pair,
264302 Level :: Error ,
265303 ) ;
266304 return Err ( msg) ;
@@ -274,30 +312,38 @@ impl<'a> ParserContext<'a> {
274312 }
275313
276314 fn parse_assign ( & mut self , pair : pest:: iterators:: Pair < Rule > ) -> Result < Stmt , String > {
277- let mut inner_rules = pair. into_inner ( ) ;
278- let path_id_rule = inner_rules. next ( ) . unwrap ( ) ;
279- let expr_rule = inner_rules. next ( ) . unwrap ( ) ;
315+ let mut inner_rules = pair. clone ( ) . into_inner ( ) ;
316+ let path_id_rule = self . expect_rule (
317+ inner_rules. next ( ) ,
318+ & pair,
319+ "Expected path identifier in assignment" ,
320+ ) ?;
321+ let expr_rule = self . expect_rule (
322+ inner_rules. next ( ) ,
323+ & pair,
324+ "Expected expression in assignment" ,
325+ ) ?;
326+
280327 let path_id: & str = path_id_rule. as_str ( ) ;
281- let symbol_id = self . st . symbol_id_from_name ( path_id) . ok_or_else ( || {
282- let msg = format ! ( "Assigning to undeclared symbol: {}" , path_id) ;
283- self . handler
284- . emit_diagnostic_parsing ( & msg, self . fileid , path_id_rule, Level :: Error ) ;
285- msg
286- } ) ?;
328+ let symbol_id =
329+ self . get_symbol_id ( path_id, & path_id_rule, "Assigning to undeclared symbol" ) ?;
287330 let expr_id = self . parse_expr ( expr_rule. into_inner ( ) ) ?;
331+
288332 Ok ( Stmt :: Assign ( symbol_id, expr_id) )
289333 }
290334
291335 fn parse_cmd ( & mut self , pair : pest:: iterators:: Pair < Rule > ) -> Result < Stmt , String > {
292- let mut inner_rules = pair. into_inner ( ) ;
293- let cmd_rule = inner_rules. next ( ) . unwrap ( ) ;
336+ let mut inner_rules = pair. clone ( ) . into_inner ( ) ;
337+ let cmd_rule = self . expect_rule ( inner_rules. next ( ) , & pair , "Expected command" ) ? ;
294338 let cmd = cmd_rule. as_str ( ) ;
339+
295340 let arg = if let Some ( expr_rule) = inner_rules. next ( ) {
296341 let expr_id = self . parse_expr ( expr_rule. into_inner ( ) ) ?;
297342 Some ( expr_id)
298343 } else {
299344 None
300345 } ;
346+
301347 match cmd {
302348 "step" => match arg {
303349 Some ( expr_id) => Ok ( Stmt :: Step ( expr_id) ) ,
@@ -309,46 +355,66 @@ impl<'a> ParserContext<'a> {
309355 "fork" => {
310356 if arg. is_some ( ) {
311357 let msg = "Fork command should have no arguments." . to_string ( ) ;
312- self . handler
313- . emit_diagnostic_parsing ( & msg, self . fileid , cmd_rule, Level :: Error ) ;
358+ self . handler . emit_diagnostic_parsing (
359+ & msg,
360+ self . fileid ,
361+ & cmd_rule,
362+ Level :: Error ,
363+ ) ;
314364 return Err ( msg) ;
315365 }
316366 Ok ( Stmt :: Fork )
317367 }
318368 _ => {
319369 let msg = format ! ( "Unexpected command: {:?}" , cmd) ;
320370 self . handler
321- . emit_diagnostic_parsing ( & msg, self . fileid , cmd_rule, Level :: Error ) ;
371+ . emit_diagnostic_parsing ( & msg, self . fileid , & cmd_rule, Level :: Error ) ;
322372 Err ( msg)
323373 }
324374 }
325375 }
326376
327377 fn parse_while ( & mut self , pair : pest:: iterators:: Pair < Rule > ) -> Result < Stmt , String > {
328- let mut inner_rules = pair. into_inner ( ) ;
329- let expr_rule = inner_rules. next ( ) . unwrap ( ) ;
378+ let mut inner_rules = pair. clone ( ) . into_inner ( ) ;
379+ let expr_rule = self . expect_rule (
380+ inner_rules. next ( ) ,
381+ & pair,
382+ "Expected expression in while loop" ,
383+ ) ?;
330384 let guard = self . parse_expr ( expr_rule. into_inner ( ) ) ?;
331385 let body = self . parse_stmt_block ( inner_rules) ?;
332386 Ok ( Stmt :: While ( guard, body) )
333387 }
334388
335389 fn parse_assert_eq ( & mut self , pair : pest:: iterators:: Pair < Rule > ) -> Result < Stmt , String > {
336- let mut inner_rules = pair. into_inner ( ) ;
337- let lhs_rule = inner_rules. next ( ) . unwrap ( ) ;
338- let rhs_rule = inner_rules. next ( ) . unwrap ( ) ;
390+ let mut inner_rules = pair. clone ( ) . into_inner ( ) ;
391+ let lhs_rule = self . expect_rule (
392+ inner_rules. next ( ) ,
393+ & pair,
394+ "Expected left-hand side expression in assert_eq" ,
395+ ) ?;
396+ let rhs_rule = self . expect_rule (
397+ inner_rules. next ( ) ,
398+ & pair,
399+ "Expected right-hand side expression in assert_eq" ,
400+ ) ?;
339401 let lhs_id = self . parse_expr ( lhs_rule. into_inner ( ) ) ?;
340402 let rhs_id = self . parse_expr ( rhs_rule. into_inner ( ) ) ?;
341403 Ok ( Stmt :: AssertEq ( lhs_id, rhs_id) )
342404 }
343405
344406 fn parse_cond ( & mut self , pair : pest:: iterators:: Pair < Rule > ) -> Result < Stmt , String > {
345- let mut inner_rules = pair. into_inner ( ) ;
346- let if_rule = inner_rules. next ( ) . unwrap ( ) ;
407+ let mut inner_rules = pair. clone ( ) . into_inner ( ) ;
408+ let if_rule = self . expect_rule ( inner_rules. next ( ) , & pair , "Expected if condition" ) ? ;
347409 let mut inner_if = if_rule. into_inner ( ) ;
348- let expr_rule = inner_if. next ( ) . unwrap ( ) ;
410+ let expr_rule = self . expect_rule (
411+ inner_if. next ( ) ,
412+ & pair,
413+ "Expected expression in if condition" ,
414+ ) ?;
349415 let expr_id = self . parse_expr ( expr_rule. into_inner ( ) ) ?;
350416 let if_block = self . parse_stmt_block ( inner_if) ?;
351- let else_rule = inner_rules. next ( ) . unwrap ( ) ;
417+ let else_rule = self . expect_rule ( inner_rules. next ( ) , & pair , "Expected else block" ) ? ;
352418 let inner_else = else_rule. into_inner ( ) ;
353419 let else_block = self . parse_stmt_block ( inner_else) ?;
354420 Ok ( Stmt :: IfElse ( expr_id, if_block, else_block) )
@@ -359,10 +425,22 @@ impl<'a> ParserContext<'a> {
359425 for inner_pair in pair. into_inner ( ) {
360426 match inner_pair. as_rule ( ) {
361427 Rule :: arg => {
362- let mut arg_inner = inner_pair. into_inner ( ) ;
363- let dir_pair = arg_inner. next ( ) . unwrap ( ) ;
364- let id_pair = arg_inner. next ( ) . unwrap ( ) ;
365- let tpe_pair = arg_inner. next ( ) . unwrap ( ) ;
428+ let mut arg_inner = inner_pair. clone ( ) . into_inner ( ) ;
429+ let dir_pair = self . expect_rule (
430+ arg_inner. next ( ) ,
431+ & inner_pair,
432+ "Expected direction in argument" ,
433+ ) ?;
434+ let id_pair = self . expect_rule (
435+ arg_inner. next ( ) ,
436+ & inner_pair,
437+ "Expected identifier in argument" ,
438+ ) ?;
439+ let tpe_pair = self . expect_rule (
440+ arg_inner. next ( ) ,
441+ & inner_pair,
442+ "Expected type in argument" ,
443+ ) ?;
366444 let dir = self . parse_dir ( dir_pair) ?;
367445 let id = id_pair. as_str ( ) ;
368446 let tpe = self . parse_type ( tpe_pair) ?;
@@ -382,7 +460,7 @@ impl<'a> ParserContext<'a> {
382460 self . handler . emit_diagnostic_parsing (
383461 & msg,
384462 self . fileid ,
385- inner_pair,
463+ & inner_pair,
386464 Level :: Error ,
387465 ) ;
388466 return Err ( msg) ;
@@ -401,10 +479,19 @@ impl<'a> ParserContext<'a> {
401479 for inner_pair in pair. into_inner ( ) {
402480 match inner_pair. as_rule ( ) {
403481 Rule :: arg => {
404- let mut arg_inner = inner_pair. into_inner ( ) ;
405- let dir_pair = arg_inner. next ( ) . unwrap ( ) ;
406- let id_pair = arg_inner. next ( ) . unwrap ( ) ;
407- let tpe_pair = arg_inner. next ( ) . unwrap ( ) ;
482+ let mut arg_inner = inner_pair. clone ( ) . into_inner ( ) ;
483+ let dir_pair = self . expect_rule (
484+ arg_inner. next ( ) ,
485+ & inner_pair,
486+ "Expected direction in field" ,
487+ ) ?;
488+ let id_pair = self . expect_rule (
489+ arg_inner. next ( ) ,
490+ & inner_pair,
491+ "Expected identifier in field" ,
492+ ) ?;
493+ let tpe_pair =
494+ self . expect_rule ( arg_inner. next ( ) , & inner_pair, "Expected type in field" ) ?;
408495 let dir = self . parse_dir ( dir_pair) ?;
409496 let id = id_pair. as_str ( ) ;
410497 let tpe = self . parse_type ( tpe_pair) ?;
@@ -425,7 +512,7 @@ impl<'a> ParserContext<'a> {
425512 self . handler . emit_diagnostic_parsing (
426513 & msg,
427514 self . fileid ,
428- inner_pair,
515+ & inner_pair,
429516 Level :: Error ,
430517 ) ;
431518 return Err ( msg) ;
@@ -444,8 +531,12 @@ impl<'a> ParserContext<'a> {
444531 "out" => Ok ( Dir :: Out ) ,
445532 _ => {
446533 let msg = format ! ( "Unexpected direction string: {:?}" , dir_str) ;
447- self . handler
448- . emit_diagnostic_parsing ( & msg, self . fileid , pair, Level :: Error ) ;
534+ self . handler . emit_diagnostic_parsing (
535+ & msg,
536+ self . fileid ,
537+ & pair,
538+ Level :: Error ,
539+ ) ;
449540 Err ( msg)
450541 }
451542 }
@@ -456,7 +547,7 @@ impl<'a> ParserContext<'a> {
456547 pair. as_rule( )
457548 ) ;
458549 self . handler
459- . emit_diagnostic_parsing ( & msg, self . fileid , pair, Level :: Error ) ;
550+ . emit_diagnostic_parsing ( & msg, self . fileid , & pair, Level :: Error ) ;
460551 Err ( msg)
461552 }
462553 }
@@ -473,7 +564,7 @@ impl<'a> ParserContext<'a> {
473564 _ => {
474565 let msg = format ! ( "Unexpected rule while parsing type: {:?}" , pair. as_rule( ) ) ;
475566 self . handler
476- . emit_diagnostic_parsing ( & msg, self . fileid , pair, Level :: Error ) ;
567+ . emit_diagnostic_parsing ( & msg, self . fileid , & pair, Level :: Error ) ;
477568 Err ( msg)
478569 }
479570 }
0 commit comments