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; }