enum v7_err v7_call(struct v7 *v7, int num_args) { struct v7_val **top = v7_top(v7), **v = top - (num_args + 1), *f = v[0]; if (v7->no_exec) return V7_OK; CHECK(v7->sp > num_args, V7_INTERNAL_ERROR); CHECK(f->type == V7_FUNC || f->type == V7_C_FUNC, V7_CALLED_NON_FUNCTION); // Return value will substitute function objest on a stack v[0] = v7_mkval(v7, V7_UNDEF); // Set return value to 'undefined' v[0]->ref_count++; if (f->type == V7_FUNC) { const char *src = v7->cursor; v7->cursor = f->v.func; // Move control flow to function body TRY(parse_function_definition(v7, v, num_args)); // Execute function body v7->cursor = src; // Return control flow if (v7_top(v7) > top) { // If function body pushed some value on stack, free_val(v7, v[0]); v[0] = top[0]; // use that value as return value v[0]->ref_count++; } } else if (f->type == V7_C_FUNC) { f->v.c_func(v7, v7->cur_obj, v[0], v + 1, num_args); } free_val(v7, f); TRY(inc_stack(v7, - (int) (v7_top(v7) - (v + 1)))); // Clean up stack return V7_OK; }
program_ptr Parser::parse_program() { int start_line = current_lexeme().line(); instructions program_body; instructions functions; instruction_ptr instruction = instruction_ptr(); while (match_current_lexeme(kEndofLine)) next_line(); while (!finished() && ErrorHandler::is_ok()) { instruction = instruction_ptr(); instruction = parse_function_definition(); if (instruction) { functions.push_back(instruction); continue; } instruction = parse_instruction(); if (!instruction) { report_current_syntax_error(); return program_ptr(); } program_body.push_back(instruction); } return program_ptr(new Program(start_line, program_body, functions)); }
// factor = number | string_literal | "(" expression ")" | // variable | "this" | "null" | "true" | "false" | // "{" object_literal "}" | // "[" array_literal "]" | // function_definition | // function_call static enum v7_err parse_factor(struct v7 *v7) { int old_sp = v7_sp(v7); if (*v7->cursor == '(') { TRY(match(v7, '(')); TRY(parse_expression(v7)); TRY(match(v7, ')')); } else if (*v7->cursor == '\'' || *v7->cursor == '"') { TRY(parse_string_literal(v7)); } else if (*v7->cursor == '{') { TRY(parse_object_literal(v7)); } else if (is_alpha(*v7->cursor) || *v7->cursor == '_') { TRY(parse_identifier(v7)); if (test_token(v7, "this", 4)) { inc_stack(v7, 1); v7_top(v7)[-1] = &v7->scopes[v7->current_scope]; } else if (test_token(v7, "null", 4)) { TRY(v7_make_and_push(v7, V7_NULL)); } else if (test_token(v7, "true", 4)) { TRY(v7_make_and_push(v7, V7_BOOL)); v7_top(v7)[-1]->v.num = 1; } else if (test_token(v7, "false", 5)) { TRY(v7_make_and_push(v7, V7_BOOL)); v7_top(v7)[-1]->v.num = 0; } else if (test_token(v7, "function", 8)) { TRY(parse_function_definition(v7, NULL, 0)); } else if (test_token(v7, "delete", 6)) { TRY(parse_delete(v7)); } else { TRY(parse_variable(v7)); } } else { TRY(parse_num(v7)); } if (*v7->cursor == '(') { TRY(parse_function_call(v7)); } // Don't leave anything on stack if no execution flag is set if (v7->no_exec) { inc_stack(v7, old_sp - v7->sp); } return V7_OK; }
Node Parser::Parse(const std::vector<token> &ntokens) { std::vector<token> tokens = ntokens; Node root; root.kind = NODE_PROGRAM; _current = &tokens.front(); while (_current->kind != TOKEN_EOF) { if (_current->kind == TOKEN_WORD) { std::string definition_name = _current->word; if (peek_next_token()->kind == TOKEN_OPENING_PAREN) root.next.push_back(parse_function_definition()); else root.next.push_back(parse_constant_definition()); } else { error("Unexpected top level token, expected word"); } } return root; }
char * parse_cell(Maze *maze, Functions *functions, char cell_str[2], char *f_ptr, char *f_end, Cell *cell) { if (str_eq(cell_str, "^^", 2)) { cell->type = CELL_START; } else if (str_eq(cell_str, "..", 2)) { cell->type = CELL_PATH; } else if (str_eq(cell_str, "##", 2) || str_eq(cell_str, " ", 2) || str_eq(cell_str, "``", 2)) { cell->type = CELL_WALL; } else if (str_eq(cell_str, "()", 2)) { cell->type = CELL_HOLE; } else if (str_eq(cell_str, "<>", 2)) { cell->type = CELL_SPLITTER; } else if (isLetter(cell_str[0]) && (isLetter(cell_str[1]) || isNum(cell_str[1]))) { char *end_function_name_f_ptr = f_ptr + 2; char *end_function_definition_f_ptr = parse_function_definition(functions, cell_str, end_function_name_f_ptr, f_end, cell); if (end_function_definition_f_ptr != end_function_name_f_ptr) { f_ptr = end_function_definition_f_ptr; } else { cell->type = CELL_FUNCTION; cell->function_index = get_function_index(cell_str); } } else if (str_eq(cell_str, "--", 2)) { cell->type = CELL_ONCE; } else if ((cell_str[0] == '*') && ((cell_str[1] == 'U') || (cell_str[1] == 'u'))) { cell->type = CELL_UP_UNLESS_DETECT; } else if ((cell_str[0] == '*') && ((cell_str[1] == 'D') || (cell_str[1] == 'd'))) { cell->type = CELL_DOWN_UNLESS_DETECT; } else if ((cell_str[0] == '*') && ((cell_str[1] == 'L') || (cell_str[1] == 'l'))) { cell->type = CELL_LEFT_UNLESS_DETECT; } else if ((cell_str[0] == '*') && ((cell_str[1] == 'R') || (cell_str[1] == 'r'))) { cell->type = CELL_RIGHT_UNLESS_DETECT; } else if (str_eq(cell_str, ">>", 2)) { cell->type = CELL_OUT; } else if (str_eq(cell_str, "<<", 2)) { cell->type = CELL_INP; } else if ((cell_str[0] == '%') && ((cell_str[1] == 'U') || (cell_str[1] == 'u'))) { cell->type = CELL_UP; } else if ((cell_str[0] == '%') && ((cell_str[1] == 'D') || (cell_str[1] == 'd'))) { cell->type = CELL_DOWN; } else if ((cell_str[0] == '%') && ((cell_str[1] == 'L') || (cell_str[1] == 'l'))) { cell->type = CELL_LEFT; } else if ((cell_str[0] == '%') && ((cell_str[1] == 'R') || (cell_str[1] == 'r'))) { cell->type = CELL_RIGHT; } else if (isNum(cell_str[0]) && isNum(cell_str[1])) { cell->type = CELL_PAUSE; u32 digit0 = cell_str[0] - '0'; u32 digit1 = cell_str[1] - '0'; cell->pause = (10 * digit0) + digit1; } if (cell->type != CELL_NULL) { f_ptr += 2; } return f_ptr; }