Parser errors

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
p-i-
Posts: 20
Joined: Sun Sep 14, 2014 2:24 pm

Parser errors

Post by p-i- » Tue Sep 23, 2014 1:17 pm

I'm getting a parser error:

Code: Select all

void test_python()
{
#if MICROPY_ENABLE_GC
    // Heap size of GC heap (if enabled)
    // Make it larger on a 64 bit machine, because pointers are larger.
    long heap_size = 128*1024 * (sizeof(mp_uint_t) / 4);

    char *heap = malloc(heap_size);
    gc_init(heap, heap + heap_size);
#endif

    
    mp_init();
    do_str("print ( 'hello world!' )  \n");

Code: Select all

void do_str(const char *src) {
    printf("%d\n", (int)strlen(src));
    mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
    if (lex == NULL) {
        return;
    }
    
    mp_parse_error_kind_t parse_error_kind;
    mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_error_kind);
    
    if (pn == MP_PARSE_NODE_NULL) {
        // parse error
        mp_parse_show_exception(lex, parse_error_kind);
        mp_lexer_free(lex);
        return;
    }
    
    // parse okay
    qstr source_name = mp_lexer_source_name(lex);
    mp_lexer_free(lex);
    mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true);

Code: Select all

mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is_repl) {
    compiler_t *comp = m_new0(compiler_t, 1);
    comp->source_file = source_file;
    comp->is_repl = is_repl;

    // optimise constants
    mp_map_t consts;
    mp_map_init(&consts, 0);
    pn = fold_constants(comp, pn, &consts);

Code: Select all

// this function is essentially a simple preprocessor
STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_map_t *consts) {
    if (0) {
        // dummy
#if MICROPY_COMP_CONST
    } else if (MP_PARSE_NODE_IS_ID(pn)) {
        // lookup identifier in table of dynamic constants
        qstr qst = MP_PARSE_NODE_LEAF_ARG(pn);
        mp_map_elem_t *elem = mp_map_lookup(consts, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
        if (elem != NULL) {
            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, MP_OBJ_SMALL_INT_VALUE(elem->value));
        }
#endif
    } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;

        // fold some parse nodes before folding their arguments
        switch (MP_PARSE_NODE_STRUCT_KIND(pns)) { 
switch (MP_PARSE_NODE_STRUCT_KIND(pns)) is giving EXC_BAD_ACCESS

If I try without the brackets, i.e. print 'hello world!' instead of print ( 'hello world!' ) (which should be valid Python I think -- it works on my commandline Python) and uncomment:

Code: Select all

#define USE_RULE_NAME (1)
I get the following output:

rule: simple_stmt
File "<stdin>", line 1, column 0
SyntaxError: invalid syntax


Is there a single problem underlined both of these errors?

blmorris
Posts: 348
Joined: Fri May 02, 2014 3:43 pm
Location: Massachusetts, USA

Re: Parser errors

Post by blmorris » Tue Sep 23, 2014 2:36 pm

p-i- wrote:If I try without the brackets, i.e. print 'hello world!' instead of print ( 'hello world!' ) (which should be valid Python I think -- it works on my commandline Python)
Are you using Python2 as your command line Python? Micropython implements Python3 syntax (I believe targeting 3.4 specifically) and you need to use print ( 'hello world!' ) in Python3.
Sorry if this isn't the answer to your main question; I admit that I wouldn't be able to help much there. But I could answer the last part.

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: Parser errors

Post by stijn » Tue Sep 23, 2014 2:58 pm

I would first try it with the unmodified code from unix main(), and use a debugger to step through it and inspect values of variables as you go. EXC_BAD_ACCESS likely means pns or whatever it points to is not initialized properly possibly due to failed allocation or something like that.

p-i-
Posts: 20
Joined: Sun Sep 14, 2014 2:24 pm

Re: Parser errors

Post by p-i- » Wed Sep 24, 2014 12:45 am

So now I am using brackets for print, thanks!

I've switched from using the bare_arm do_str function to using the one in /unix/main.c

Code: Select all

uint mp_verbose_flag = 1;

uint emit_opt = MP_EMIT_OPT_NONE;
bool compile_only = false;

// returns standard error codes: 0 for success, 1 for all other errors
STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) {
    if (lex == NULL) {
        return 1;
    }
    
    if (0) {
        // just tokenise
        while (!mp_lexer_is_kind(lex, MP_TOKEN_END)) {
            mp_token_show(mp_lexer_cur(lex));
            mp_lexer_to_next(lex);
        }
        mp_lexer_free(lex);
        return 0;
    }
    
    mp_parse_error_kind_t parse_error_kind;
    mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind);
    
    if (pn == MP_PARSE_NODE_NULL) {
        // parse error
        mp_parse_show_exception(lex, parse_error_kind);
        mp_lexer_free(lex);
        return 1;
    }
    
    qstr source_name = mp_lexer_source_name(lex);
#if MICROPY_PY___FILE__
    if (input_kind == MP_PARSE_FILE_INPUT) {
        mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
    }
#endif
    mp_lexer_free(lex);
    
    
     printf("----------------\n"); // <-- I uncommented this 
     mp_parse_node_print(pn, 0);
     printf("----------------\n");
     
    
    mp_obj_t module_fun = mp_compile(pn, source_name, emit_opt, is_repl); // <-- fails here
    
    if (module_fun == mp_const_none) {
        // compile error
        return 1;
    }
    
    if (compile_only) {
        return 0;
    }
    
    // execute it
    nlr_buf_t nlr;
    if (nlr_push(&nlr) == 0) {
        mp_call_function_0(module_fun);
        nlr_pop();
        return 0;
    } else {
        // uncaught exception
        // check for SystemExit
        mp_obj_t exc = (mp_obj_t)nlr.ret_val;
        if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) {
            mp_obj_t exit_val = mp_obj_exception_get_value(exc);
            mp_int_t val;
            if (!mp_obj_get_int_maybe(exit_val, &val)) {
                val = 0;
            }
            exit(val);
        }
        mp_obj_print_exception((mp_obj_t)nlr.ret_val);
        return 1;
    }
}
I uncommented the mp_parse_node_print lines

This produced compiler errors: searching under mp_parse_node_print, I find I need to set

Code: Select all

#define MICROPY_DEBUG_PRINTERS      (1)
in mpconfigport.h, which then requires

Code: Select all

uint mp_verbose_flag = 1;
Which I already included in the first listing.

Now when I run, I get the output:
----------------
[ 1] expr_stmt(32) (n=2)
[ 1] power(120) (n=3)
id(print)
[ 1] trailer_paren(136) (n=1)
[ 1] literal str(hello world!)
NULL
NULL
----------------
The line that fails in do_str is:

Code: Select all

    mp_obj_t module_fun = mp_compile(pn, source_name, emit_opt, is_repl);
All of the parameters look reasonable.

YAY it works!

Hello world!

Strange thing is that I'm pretty sure I already tried the UNIX do_str and was getting the error. And now I'm not. Might have been a clean/build that shook something loose.

Post Reply