// 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; }
instruction_ptr Parser::parse_value() { int start_line = current_lexeme().line(); if (match_current_lexeme(kSubtraction)) { next_lexeme(); instruction_ptr value = parse_value(); if (!value) { report_current_syntax_error(); return instruction_ptr(); } return instruction_ptr(new ArithmeticOperationInstruction(start_line, kSub, instruction_ptr(new Constant(start_line, 0)), value)); } if (match_current_lexeme(kLeftBracket)) { next_lexeme(); instruction_ptr expression = parse_expression(); if (!match_current_lexeme(kRightBracket)) { report_current_syntax_error(); return instruction_ptr(); } next_lexeme(); return expression; } instruction_ptr value = parse_constant(); if (!value) value = parse_function_call(); return value; }
/*----------------------------------------------------------------------*/ static ast_expression_t *parse_value(parse_state_t *p) { token_t *token = peek_token(p); if (token == NULL) { } else if (token->type == TK_INT_LITERAL || token->type == TK_FLOAT_LITERAL || token->type == TK_DOUBLE_LITERAL || token->type == TK_STRING_LITERAL) { return parse_literal(p); } else if (token->type == TK_IDENTIFIER) { next_token(p); if (test_token(peek_token(p), TK_LBRACKET)) { rewind_token(p); return parse_function_call(p); } else { rewind_token(p); return parse_variable(p); } } error(p, "value expected"); return NULL; /* unreachable */ }
Node* Parser::parse_expression() { // expects TOKEN_INTEGER, TOKEN_WORD or TOKEN_OPENING_PAREN as current token Node *node = create_node(NODE_EXPRESSION); if (_current->kind == TOKEN_INTEGER) { Node *node_const = create_node(NODE_CONSTANT); node_const->constant_number = _current->integer; node->next.push_back(node_const); } else if (_current->kind == TOKEN_WORD) { Node *node_word = create_node(NODE_WORD); node_word->word_word = _current->word; node->next.push_back(node_word); } else if (_current->kind == TOKEN_OPENING_PAREN) { node->next.push_back(parse_function_call()); } else { printf("Error: unknown expression: "); _current->print(); } next_token(); return node; }
int kowhai_protocol_parse(void* proto_packet, int packet_size, struct kowhai_protocol_t* protocol) { int required_size = sizeof(struct kowhai_protocol_header_t); memset(protocol, 0, sizeof(struct kowhai_protocol_t)); // check packet is large enough for header if (packet_size < required_size) return KOW_STATUS_PACKET_BUFFER_TOO_SMALL; memcpy(&protocol->header, proto_packet, required_size); switch (protocol->header.command) { case KOW_CMD_GET_VERSION: return KOW_STATUS_OK; case KOW_CMD_GET_VERSION_ACK: return parse_version((void*)((uint8_t*)proto_packet + required_size), packet_size - required_size, &protocol->payload); case KOW_CMD_GET_TREE_LIST: return KOW_STATUS_OK; case KOW_CMD_GET_TREE_LIST_ACK: case KOW_CMD_GET_TREE_LIST_ACK_END: case KOW_CMD_GET_FUNCTION_LIST_ACK: case KOW_CMD_GET_FUNCTION_LIST_ACK_END: return parse_id_list((void*)((uint8_t*)proto_packet + required_size), packet_size - required_size, &protocol->payload); case KOW_CMD_READ_DATA: return parse_symbols((void*)((uint8_t*)proto_packet + required_size), packet_size - required_size, &protocol->payload, &required_size); case KOW_CMD_WRITE_DATA: case KOW_CMD_WRITE_DATA_END: case KOW_CMD_WRITE_DATA_ACK: case KOW_CMD_READ_DATA_ACK: case KOW_CMD_READ_DATA_ACK_END: return parse_data_payload((void*)((uint8_t*)proto_packet + required_size), packet_size - required_size, &protocol->payload); case KOW_CMD_READ_DESCRIPTOR: // read descriptor command requires no more parameters return KOW_STATUS_OK; case KOW_CMD_READ_DESCRIPTOR_ACK: case KOW_CMD_READ_DESCRIPTOR_ACK_END: return parse_descriptor_payload((void*)((uint8_t*)proto_packet + required_size), packet_size - required_size, &protocol->payload); case KOW_CMD_GET_FUNCTION_LIST: case KOW_CMD_GET_FUNCTION_DETAILS: // get function list/details command requires no more parameters return KOW_STATUS_OK; case KOW_CMD_GET_FUNCTION_DETAILS_ACK: return parse_function_details((void*)((uint8_t*)proto_packet + required_size), packet_size - required_size, &protocol->payload.spec.function_details); case KOW_CMD_CALL_FUNCTION: case KOW_CMD_CALL_FUNCTION_ACK: case KOW_CMD_CALL_FUNCTION_RESULT: case KOW_CMD_CALL_FUNCTION_RESULT_END: return parse_function_call((void*)((uint8_t*)proto_packet + required_size), packet_size - required_size, &protocol->payload); case KOW_CMD_CALL_FUNCTION_FAILED: return KOW_STATUS_OK; case KOW_CMD_EVENT: case KOW_CMD_EVENT_END: return parse_event((void*)((uint8_t*)proto_packet + required_size), packet_size - required_size, &protocol->payload); case KOW_CMD_GET_SYMBOL_LIST: return KOW_STATUS_OK; case KOW_CMD_GET_SYMBOL_LIST_ACK: case KOW_CMD_GET_SYMBOL_LIST_ACK_END: return parse_string_list((void*)((uint8_t*)proto_packet + required_size), packet_size - required_size, &protocol->payload); // error codes case KOW_CMD_ERROR_INVALID_COMMAND: case KOW_CMD_ERROR_INVALID_FUNCTION_ID: case KOW_CMD_ERROR_INVALID_PAYLOAD_OFFSET: case KOW_CMD_ERROR_INVALID_PAYLOAD_SIZE: case KOW_CMD_ERROR_INVALID_SEQUENCE: case KOW_CMD_ERROR_INVALID_SYMBOL_PATH: case KOW_CMD_ERROR_INVALID_TREE_ID: case KOW_CMD_ERROR_NO_DATA: return KOW_STATUS_OK; default: return KOW_STATUS_INVALID_PROTOCOL_COMMAND; } }