bool parse(ast_t* package, source_t* source, rule_t start, const char* expected) { assert(package != NULL); assert(source != NULL); assert(expected != NULL); // Open the lexer lexer_t* lexer = lexer_open(source); if(lexer == NULL) return false; // Create a parser and attach the lexer parser_t* parser = POOL_ALLOC(parser_t); parser->source = source; parser->lexer = lexer; parser->token = lexer_next(lexer); parser->last_matched = NULL; parser->last_token_line = 0; parser->next_flags = 0; parser->failed = false; // Parse given start rule builder_fn_t build_fn; ast_t* ast = start(parser, &build_fn, expected); if(ast == PARSE_ERROR) ast = NULL; if(ast == RULE_NOT_FOUND) { syntax_error(parser, expected, NULL, NULL); ast = NULL; } if(parser->failed) { ast_free(ast); ast = NULL; } lexer_close(lexer); token_free(parser->token); POOL_FREE(parser_t, parser); if(ast == NULL) { source_close(source); return false; } assert(ast_id(ast) == TK_MODULE); assert(ast_data(ast) == NULL); ast_setdata(ast, source); ast_add(package, ast); return true; }
// Turn the given description into an ast static ast_t* build_ast(source_t* source, symtab_t* symtab) { assert(source != NULL); assert(symtab != NULL); // Setup parser build_parser_t build_parser; build_parser.source = source; build_parser.token = NULL; build_parser.defs = symtab; build_parser.refs = NULL; build_parser.line = 1; build_parser.pos = 1; build_parser.have_token = false; build_parser.had_error = false; build_parser.lexer = lexer_open(source); assert(build_parser.lexer != NULL); // Parse given start rule ast_t* ast = get_nodes(&build_parser, AT_EOF); if(ast != NULL) { if(!process_refs(&build_parser)) { ast_free(ast); ast = NULL; } } // Tidy up parser lexer_close(build_parser.lexer); builder_ref_t* p = build_parser.refs; while(p != NULL) { builder_ref_t* next = p->next; POOL_FREE(builder_ref_t, p); p = next; } return ast; }
/******************** * dres_parse_file ********************/ EXPORTED dres_t * dres_parse_file(char *path) { #define FAIL(err) do { status = err; goto fail; } while (0) dres_t *dres = NULL; int status, i; if (path == NULL) FAIL(EINVAL); if ((status = lexer_open(path)) != 0) FAIL(status); if ((dres = dres_init(NULL)) == NULL) FAIL(errno); if ((status = yyparse(dres)) != 0 || (status = check_undefined(dres)) != 0 || (status = initialize_variables(dres)) != 0 || (status = finalize_variables(dres)) != 0) FAIL(status); dres->vm.nlocal = dres->ndresvar; for (i = 0; i < dres->ndresvar; i++) vm_set_varname(&dres->vm, i, dres->dresvars[i].name); return dres; fail: if (dres != NULL) dres_exit(dres); errno = status; return NULL; #undef FAIL }