@ -147,15 +147,7 @@ typedef struct _mp_parse_chunk_t {
byte data [ ] ;
} mp_parse_chunk_t ;
typedef enum {
PARSE_ERROR_NONE = 0 ,
PARSE_ERROR_MEMORY ,
PARSE_ERROR_CONST ,
} parse_error_t ;
typedef struct _parser_t {
parse_error_t parse_error ;
size_t rule_stack_alloc ;
size_t rule_stack_top ;
rule_stack_t * rule_stack ;
@ -216,15 +208,8 @@ STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) {
}
STATIC void push_rule ( parser_t * parser , size_t src_line , const rule_t * rule , size_t arg_i ) {
if ( parser - > parse_error ) {
return ;
}
if ( parser - > rule_stack_top > = parser - > rule_stack_alloc ) {
rule_stack_t * rs = m_renew_maybe ( rule_stack_t , parser - > rule_stack , parser - > rule_stack_alloc , parser - > rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC , true ) ;
if ( rs = = NULL ) {
parser - > parse_error = PARSE_ERROR_MEMORY ;
return ;
}
rule_stack_t * rs = m_renew ( rule_stack_t , parser - > rule_stack , parser - > rule_stack_alloc , parser - > rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC ) ;
parser - > rule_stack = rs ;
parser - > rule_stack_alloc + = MICROPY_ALLOC_PARSE_RULE_INC ;
}
@ -241,7 +226,6 @@ STATIC void push_rule_from_arg(parser_t *parser, size_t arg) {
}
STATIC void pop_rule ( parser_t * parser , const rule_t * * rule , size_t * arg_i , size_t * src_line ) {
assert ( ! parser - > parse_error ) ;
parser - > rule_stack_top - = 1 ;
* rule = rules [ parser - > rule_stack [ parser - > rule_stack_top ] . rule_id ] ;
* arg_i = parser - > rule_stack [ parser - > rule_stack_top ] . arg_i ;
@ -354,31 +338,18 @@ STATIC void result_stack_show(parser_t *parser) {
*/
STATIC mp_parse_node_t pop_result ( parser_t * parser ) {
if ( parser - > parse_error ) {
return MP_PARSE_NODE_NULL ;
}
assert ( parser - > result_stack_top > 0 ) ;
return parser - > result_stack [ - - parser - > result_stack_top ] ;
}
STATIC mp_parse_node_t peek_result ( parser_t * parser , size_t pos ) {
if ( parser - > parse_error ) {
return MP_PARSE_NODE_NULL ;
}
assert ( parser - > result_stack_top > pos ) ;
return parser - > result_stack [ parser - > result_stack_top - 1 - pos ] ;
}
STATIC void push_result_node ( parser_t * parser , mp_parse_node_t pn ) {
if ( parser - > parse_error ) {
return ;
}
if ( parser - > result_stack_top > = parser - > result_stack_alloc ) {
mp_parse_node_t * stack = m_renew_maybe ( mp_parse_node_t , parser - > result_stack , parser - > result_stack_alloc , parser - > result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC , true ) ;
if ( stack = = NULL ) {
parser - > parse_error = PARSE_ERROR_MEMORY ;
return ;
}
mp_parse_node_t * stack = m_renew ( mp_parse_node_t , parser - > result_stack , parser - > result_stack_alloc , parser - > result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC ) ;
parser - > result_stack = stack ;
parser - > result_stack_alloc + = MICROPY_ALLOC_PARSE_RESULT_INC ;
}
@ -387,10 +358,6 @@ STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
STATIC mp_parse_node_t make_node_const_object ( parser_t * parser , size_t src_line , mp_obj_t obj ) {
mp_parse_node_struct_t * pn = parser_alloc ( parser , sizeof ( mp_parse_node_struct_t ) + sizeof ( mp_obj_t ) ) ;
if ( pn = = NULL ) {
parser - > parse_error = PARSE_ERROR_MEMORY ;
return MP_PARSE_NODE_NULL ;
}
pn - > source_line = src_line ;
# if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
// nodes are 32-bit pointers, but need to store 64-bit object
@ -653,8 +620,11 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
mp_parse_node_t pn_value = ( ( mp_parse_node_struct_t * ) ( ( mp_parse_node_struct_t * ) pn1 ) - > nodes [ 1 ] ) - > nodes [ 0 ] ;
mp_obj_t value ;
if ( ! mp_parse_node_get_int_maybe ( pn_value , & value ) ) {
parser - > parse_error = PARSE_ERROR_CONST ;
return false ;
mp_obj_t exc = mp_obj_new_exception_msg ( & mp_type_SyntaxError ,
" constant must be an integer " ) ;
mp_obj_exception_add_traceback ( exc , parser - > lexer - > source_name ,
( ( mp_parse_node_struct_t * ) pn1 ) - > source_line , MP_QSTR_NULL ) ;
nlr_raise ( exc ) ;
}
// store the value in the table of dynamic constants
@ -755,10 +725,6 @@ STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *ru
# endif
mp_parse_node_struct_t * pn = parser_alloc ( parser , sizeof ( mp_parse_node_struct_t ) + sizeof ( mp_parse_node_t ) * num_args ) ;
if ( pn = = NULL ) {
parser - > parse_error = PARSE_ERROR_MEMORY ;
return ;
}
pn - > source_line = src_line ;
pn - > kind_num_nodes = ( rule - > rule_id & 0xff ) | ( num_args < < 8 ) ;
for ( size_t i = num_args ; i > 0 ; i - - ) {
@ -773,15 +739,13 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
parser_t parser ;
parser . parse_error = PARSE_ERROR_NONE ;
parser . rule_stack_alloc = MICROPY_ALLOC_PARSE_RULE_INIT ;
parser . rule_stack_top = 0 ;
parser . rule_stack = m_new_maybe ( rule_stack_t , parser . rule_stack_alloc ) ;
parser . rule_stack = m_new ( rule_stack_t , parser . rule_stack_alloc ) ;
parser . result_stack_alloc = MICROPY_ALLOC_PARSE_RESULT_INIT ;
parser . result_stack_top = 0 ;
parser . result_stack = m_new_maybe ( mp_parse_node_t , parser . result_stack_alloc ) ;
parser . result_stack = m_new ( mp_parse_node_t , parser . result_stack_alloc ) ;
parser . lexer = lex ;
@ -792,11 +756,6 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
mp_map_init ( & parser . consts , 0 ) ;
# endif
// check if we could allocate the stacks
if ( parser . rule_stack = = NULL | | parser . result_stack = = NULL ) {
goto memory_error ;
}
// work out the top-level rule to use, and push it on the stack
size_t top_level_rule ;
switch ( input_kind ) {
@ -815,7 +774,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
for ( ; ; ) {
next_rule :
if ( parser . rule_stack_top = = 0 | | parser . parse_error ) {
if ( parser . rule_stack_top = = 0 ) {
break ;
}
@ -1077,27 +1036,12 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
parser . tree . chunk = parser . cur_chunk ;
}
mp_obj_t exc ;
if ( parser . parse_error ) {
# if MICROPY_COMP_CONST
if ( parser . parse_error = = PARSE_ERROR_CONST ) {
exc = mp_obj_new_exception_msg ( & mp_type_SyntaxError ,
" constant must be an integer " ) ;
} else
# endif
{
assert ( parser . parse_error = = PARSE_ERROR_MEMORY ) ;
memory_error :
exc = mp_obj_new_exception_msg ( & mp_type_MemoryError ,
" parser could not allocate enough memory " ) ;
}
parser . tree . root = MP_PARSE_NODE_NULL ;
} else if (
if (
lex - > tok_kind ! = MP_TOKEN_END // check we are at the end of the token stream
| | parser . result_stack_top = = 0 // check that we got a node (can fail on empty input)
) {
syntax_error :
syntax_error : ;
mp_obj_t exc ;
if ( lex - > tok_kind = = MP_TOKEN_INDENT ) {
exc = mp_obj_new_exception_msg ( & mp_type_IndentationError ,
" unexpected indent " ) ;
@ -1108,37 +1052,24 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
exc = mp_obj_new_exception_msg ( & mp_type_SyntaxError ,
" invalid syntax " ) ;
}
parser . tree . root = MP_PARSE_NODE_NULL ;
} else {
// no errors
//result_stack_show(parser);
//printf("rule stack alloc: %d\n", parser.rule_stack_alloc);
//printf("result stack alloc: %d\n", parser.result_stack_alloc);
//printf("number of parse nodes allocated: %d\n", num_parse_nodes_allocated);
// get the root parse node that we created
assert ( parser . result_stack_top = = 1 ) ;
exc = MP_OBJ_NULL ;
parser . tree . root = parser . result_stack [ 0 ] ;
// add traceback to give info about file name and location
// we don't have a 'block' name, so just pass the NULL qstr to indicate this
mp_obj_exception_add_traceback ( exc , lex - > source_name , lex - > tok_line , MP_QSTR_NULL ) ;
nlr_raise ( exc ) ;
}
// get the root parse node that we created
assert ( parser . result_stack_top = = 1 ) ;
parser . tree . root = parser . result_stack [ 0 ] ;
// free the memory that we don't need anymore
m_del ( rule_stack_t , parser . rule_stack , parser . rule_stack_alloc ) ;
m_del ( mp_parse_node_t , parser . result_stack , parser . result_stack_alloc ) ;
// we also free the lexer on behalf of the caller (see below)
if ( exc ! = MP_OBJ_NULL ) {
// had an error so raise the exception
// add traceback to give info about file name and location
// we don't have a 'block' name, so just pass the NULL qstr to indicate this
mp_obj_exception_add_traceback ( exc , lex - > source_name , lex - > tok_line , MP_QSTR_NULL ) ;
mp_lexer_free ( lex ) ;
nlr_raise ( exc ) ;
} else {
mp_lexer_free ( lex ) ;
return parser . tree ;
}
// we also free the lexer on behalf of the caller
mp_lexer_free ( lex ) ;
return parser . tree ;
}
void mp_parse_tree_clear ( mp_parse_tree_t * tree ) {