@@ -344,21 +344,26 @@ STATIC void push_result_rule(parser_t *parser, int src_line, const rule_t *rule,
344344
345345mp_parse_node_t mp_parse (mp_lexer_t * lex , mp_parse_input_kind_t input_kind , mp_parse_error_kind_t * parse_error_kind_out ) {
346346
347- // allocate memory for the parser and its stacks
347+ // initialise parser and allocate memory for its stacks
348348
349- parser_t * parser = m_new_obj ( parser_t ) ;
349+ parser_t parser ;
350350
351- parser -> had_memory_error = false;
351+ parser . had_memory_error = false;
352352
353- parser -> rule_stack_alloc = MP_ALLOC_PARSE_RULE_INIT ;
354- parser -> rule_stack_top = 0 ;
355- parser -> rule_stack = m_new (rule_stack_t , parser -> rule_stack_alloc );
353+ parser . rule_stack_alloc = MP_ALLOC_PARSE_RULE_INIT ;
354+ parser . rule_stack_top = 0 ;
355+ parser . rule_stack = m_new_maybe (rule_stack_t , parser . rule_stack_alloc );
356356
357- parser -> result_stack_alloc = MP_ALLOC_PARSE_RESULT_INIT ;
358- parser -> result_stack_top = 0 ;
359- parser -> result_stack = m_new (mp_parse_node_t , parser -> result_stack_alloc );
357+ parser . result_stack_alloc = MP_ALLOC_PARSE_RESULT_INIT ;
358+ parser . result_stack_top = 0 ;
359+ parser . result_stack = m_new_maybe (mp_parse_node_t , parser . result_stack_alloc );
360360
361- parser -> lexer = lex ;
361+ parser .lexer = lex ;
362+
363+ // check if we could allocate the stacks
364+ if (parser .rule_stack == NULL || parser .result_stack == NULL ) {
365+ goto memory_error ;
366+ }
362367
363368 // work out the top-level rule to use, and push it on the stack
364369 int top_level_rule ;
@@ -367,7 +372,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
367372 case MP_PARSE_EVAL_INPUT : top_level_rule = RULE_eval_input ; break ;
368373 default : top_level_rule = RULE_file_input ;
369374 }
370- push_rule (parser , mp_lexer_cur (lex )-> src_line , rules [top_level_rule ], 0 );
375+ push_rule (& parser , mp_lexer_cur (lex )-> src_line , rules [top_level_rule ], 0 );
371376
372377 // parse!
373378
@@ -381,17 +386,17 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
381386
382387 for (;;) {
383388 next_rule :
384- if (parser -> rule_stack_top == 0 || parser -> had_memory_error ) {
389+ if (parser . rule_stack_top == 0 || parser . had_memory_error ) {
385390 break ;
386391 }
387392
388- pop_rule (parser , & rule , & i , & rule_src_line );
393+ pop_rule (& parser , & rule , & i , & rule_src_line );
389394 n = rule -> act & RULE_ACT_ARG_MASK ;
390395
391396 /*
392397 // debugging
393- printf("depth=%d ", parser-> rule_stack_top);
394- for (int j = 0; j < parser-> rule_stack_top; ++j) {
398+ printf("depth=%d ", parser. rule_stack_top);
399+ for (int j = 0; j < parser. rule_stack_top; ++j) {
395400 printf(" ");
396401 }
397402 printf("%s n=%d i=%d bt=%d\n", rule->rule_name, n, i, backtrack);
@@ -408,29 +413,29 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
408413 switch (rule -> arg [i ] & RULE_ARG_KIND_MASK ) {
409414 case RULE_ARG_TOK :
410415 if (mp_lexer_is_kind (lex , rule -> arg [i ] & RULE_ARG_ARG_MASK )) {
411- push_result_token (parser , lex );
416+ push_result_token (& parser , lex );
412417 mp_lexer_to_next (lex );
413418 goto next_rule ;
414419 }
415420 break ;
416421 case RULE_ARG_RULE :
417- push_rule (parser , rule_src_line , rule , i + 1 ); // save this or-rule
418- push_rule_from_arg (parser , rule -> arg [i ]); // push child of or-rule
422+ push_rule (& parser , rule_src_line , rule , i + 1 ); // save this or-rule
423+ push_rule_from_arg (& parser , rule -> arg [i ]); // push child of or-rule
419424 goto next_rule ;
420425 default :
421426 assert (0 );
422427 }
423428 }
424429 if ((rule -> arg [i ] & RULE_ARG_KIND_MASK ) == RULE_ARG_TOK ) {
425430 if (mp_lexer_is_kind (lex , rule -> arg [i ] & RULE_ARG_ARG_MASK )) {
426- push_result_token (parser , lex );
431+ push_result_token (& parser , lex );
427432 mp_lexer_to_next (lex );
428433 } else {
429434 backtrack = true;
430435 goto next_rule ;
431436 }
432437 } else {
433- push_rule_from_arg (parser , rule -> arg [i ]);
438+ push_rule_from_arg (& parser , rule -> arg [i ]);
434439 }
435440 break ;
436441
@@ -441,7 +446,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
441446 assert (i > 0 );
442447 if ((rule -> arg [i - 1 ] & RULE_ARG_KIND_MASK ) == RULE_ARG_OPT_RULE ) {
443448 // an optional rule that failed, so continue with next arg
444- push_result_node (parser , MP_PARSE_NODE_NULL );
449+ push_result_node (& parser , MP_PARSE_NODE_NULL );
445450 backtrack = false;
446451 } else {
447452 // a mandatory rule that failed, so propagate backtrack
@@ -463,7 +468,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
463468 if (mp_lexer_is_kind (lex , tok_kind )) {
464469 // matched token
465470 if (tok_kind == MP_TOKEN_NAME ) {
466- push_result_token (parser , lex );
471+ push_result_token (& parser , lex );
467472 }
468473 mp_lexer_to_next (lex );
469474 } else {
@@ -480,8 +485,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
480485 break ;
481486 case RULE_ARG_RULE :
482487 case RULE_ARG_OPT_RULE :
483- push_rule (parser , rule_src_line , rule , i + 1 ); // save this and-rule
484- push_rule_from_arg (parser , rule -> arg [i ]); // push child of and-rule
488+ push_rule (& parser , rule_src_line , rule , i + 1 ); // save this and-rule
489+ push_rule_from_arg (& parser , rule -> arg [i ]); // push child of and-rule
485490 goto next_rule ;
486491 default :
487492 assert (0 );
@@ -514,12 +519,12 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
514519#if 0 && !MICROPY_ENABLE_DOC_STRING
515520 // this code discards lonely statement, such as doc strings
516521 // problem is that doc strings have already been interned, so this doesn't really help reduce RAM usage
517- if (input_kind != MP_PARSE_SINGLE_INPUT && rule -> rule_id == RULE_expr_stmt && peek_result (parser , 0 ) == MP_PARSE_NODE_NULL ) {
518- mp_parse_node_t p = peek_result (parser , 1 );
522+ if (input_kind != MP_PARSE_SINGLE_INPUT && rule -> rule_id == RULE_expr_stmt && peek_result (& parser , 0 ) == MP_PARSE_NODE_NULL ) {
523+ mp_parse_node_t p = peek_result (& parser , 1 );
519524 if (MP_PARSE_NODE_IS_LEAF (p ) && !MP_PARSE_NODE_IS_ID (p )) {
520525 pop_result (parser );
521526 pop_result (parser );
522- push_result_rule (parser , rule_src_line , rules [RULE_pass_stmt ], 0 );
527+ push_result_rule (& parser , rule_src_line , rules [RULE_pass_stmt ], 0 );
523528 break ;
524529 }
525530 }
@@ -540,35 +545,35 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
540545 // always emit these rules, and add an extra blank node at the end (to be used by the compiler to store data)
541546 if (ADD_BLANK_NODE (rule -> rule_id )) {
542547 emit_rule = true;
543- push_result_node (parser , MP_PARSE_NODE_NULL );
548+ push_result_node (& parser , MP_PARSE_NODE_NULL );
544549 i += 1 ;
545550 }
546551
547552 int num_not_nil = 0 ;
548553 for (int x = 0 ; x < i ; ++ x ) {
549- if (peek_result (parser , x ) != MP_PARSE_NODE_NULL ) {
554+ if (peek_result (& parser , x ) != MP_PARSE_NODE_NULL ) {
550555 num_not_nil += 1 ;
551556 }
552557 }
553558 //printf("done and %s n=%d i=%d notnil=%d\n", rule->rule_name, n, i, num_not_nil);
554559 if (emit_rule ) {
555- push_result_rule (parser , rule_src_line , rule , i );
560+ push_result_rule (& parser , rule_src_line , rule , i );
556561 } else if (num_not_nil == 0 ) {
557- push_result_rule (parser , rule_src_line , rule , i ); // needed for, eg, atom_paren, testlist_comp_3b
562+ push_result_rule (& parser , rule_src_line , rule , i ); // needed for, eg, atom_paren, testlist_comp_3b
558563 //result_stack_show(parser);
559564 //assert(0);
560565 } else if (num_not_nil == 1 ) {
561566 // single result, leave it on stack
562567 mp_parse_node_t pn = MP_PARSE_NODE_NULL ;
563568 for (int x = 0 ; x < i ; ++ x ) {
564- mp_parse_node_t pn2 = pop_result (parser );
569+ mp_parse_node_t pn2 = pop_result (& parser );
565570 if (pn2 != MP_PARSE_NODE_NULL ) {
566571 pn = pn2 ;
567572 }
568573 }
569- push_result_node (parser , pn );
574+ push_result_node (& parser , pn );
570575 } else {
571- push_result_rule (parser , rule_src_line , rule , i );
576+ push_result_rule (& parser , rule_src_line , rule , i );
572577 }
573578 break ;
574579
@@ -615,7 +620,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
615620 if (i & 1 & n ) {
616621 // separators which are tokens are not pushed to result stack
617622 } else {
618- push_result_token (parser , lex );
623+ push_result_token (& parser , lex );
619624 }
620625 mp_lexer_to_next (lex );
621626 // got element of list, so continue parsing list
@@ -628,8 +633,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
628633 }
629634 break ;
630635 case RULE_ARG_RULE :
631- push_rule (parser , rule_src_line , rule , i + 1 ); // save this list-rule
632- push_rule_from_arg (parser , arg ); // push child of list-rule
636+ push_rule (& parser , rule_src_line , rule , i + 1 ); // save this list-rule
637+ push_rule_from_arg (& parser , arg ); // push child of list-rule
633638 goto next_rule ;
634639 default :
635640 assert (0 );
@@ -649,13 +654,13 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
649654 // list matched single item
650655 if (had_trailing_sep ) {
651656 // if there was a trailing separator, make a list of a single item
652- push_result_rule (parser , rule_src_line , rule , i );
657+ push_result_rule (& parser , rule_src_line , rule , i );
653658 } else {
654659 // just leave single item on stack (ie don't wrap in a list)
655660 }
656661 } else {
657662 //printf("done list %s %d %d\n", rule->rule_name, n, i);
658- push_result_rule (parser , rule_src_line , rule , i );
663+ push_result_rule (& parser , rule_src_line , rule , i );
659664 }
660665 break ;
661666
@@ -667,7 +672,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
667672 mp_parse_node_t result ;
668673
669674 // check if we had a memory error
670- if (parser -> had_memory_error ) {
675+ if (parser .had_memory_error ) {
676+ memory_error :
671677 * parse_error_kind_out = MP_PARSE_ERROR_MEMORY ;
672678 result = MP_PARSE_NODE_NULL ;
673679 goto finished ;
@@ -681,19 +687,18 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
681687
682688 //printf("--------------\n");
683689 //result_stack_show(parser);
684- //printf("rule stack alloc: %d\n", parser-> rule_stack_alloc);
685- //printf("result stack alloc: %d\n", parser-> result_stack_alloc);
690+ //printf("rule stack alloc: %d\n", parser. rule_stack_alloc);
691+ //printf("result stack alloc: %d\n", parser. result_stack_alloc);
686692 //printf("number of parse nodes allocated: %d\n", num_parse_nodes_allocated);
687693
688694 // get the root parse node that we created
689- assert (parser -> result_stack_top == 1 );
690- result = parser -> result_stack [0 ];
695+ assert (parser . result_stack_top == 1 );
696+ result = parser . result_stack [0 ];
691697
692698finished :
693699 // free the memory that we don't need anymore
694- m_del (rule_stack_t , parser -> rule_stack , parser -> rule_stack_alloc );
695- m_del (mp_parse_node_t , parser -> result_stack , parser -> result_stack_alloc );
696- m_del_obj (parser_t , parser );
700+ m_del (rule_stack_t , parser .rule_stack , parser .rule_stack_alloc );
701+ m_del (mp_parse_node_t , parser .result_stack , parser .result_stack_alloc );
697702
698703 // return the result
699704 return result ;
0 commit comments