static tpmi_status_t eval_cell(tpmi_t *interp, cell_t *c) { if (c->type == CT_ATOM) { entry_t *entry = dict_find(interp->words, c->atom); if (entry == NULL) { ERROR(interp, "unknown identifier: '%s'", c->atom); return TPMI_ERROR; } interp->last_word = entry->word; if (entry->word->type == WT_DRCT) { clist_append(&interp->curr_drct, cell_copy(c)); interp->args_drct = entry->word->value->fn->count; return (interp->args_drct == 0) ? eval_directive(interp) : TPMI_OK; } if (entry->word->type != WT_VAR) return eval_word(interp, entry); } stack_push(&interp->stack, cell_copy(c)); return TPMI_OK; }
void eval_expression(const char ** source_begin, const char * source_end, command_stack & command, bool is_sub_expression) { const char * start = *source_begin; if(is_sub_expression) { assert(*start == '('); start++; } std::size_t call_index = command.push_command(); bool first_argument = true; for(const char * cursor = start; cursor != source_end; cursor++) { char c = *cursor; expression::token_id token_id = expression::symbols[static_cast<std::size_t>(c)]; switch(token_id) { case expression::WHITESPACE: // Do nothing break; case expression::END_EXPRESSION: { *source_begin = cursor; if(!is_sub_expression) throw_unexpected(')', "expression"); command.call(call_index); return; } case expression::END_ROOT_EXPRESSION: { if(is_sub_expression) { if(c == ';') throw_unexpected(';', "expression"); break; // Allow new lines in sub expressions } *source_begin = cursor + 1; command.call(call_index); return; } case expression::START_EXPRESSION: { eval_expression(&cursor, source_end, command, true); first_argument = false; break; } case expression::START_SYMBOL: { eval_symbol(&cursor, source_end, command); first_argument = false; break; } case expression::START_REFERENCE: { eval_reference(&cursor, source_end, command); first_argument = false; break; } case expression::START_END_STRING: { eval_string(&cursor, source_end, command); first_argument = false; break; } case expression::START_MULTILINE_STRING: { eval_multiline_string(&cursor, source_end, command); first_argument = false; break; } case expression::CHAR: { if(!first_argument) eval_word(&cursor, source_end, command); else eval_reference(&cursor, source_end, command); first_argument = false; break; } case expression::START_COMMENT: { eval_comment(&cursor, source_end, command); break; } case expression::ERROR: default: *source_begin = cursor; throw_unexpected(c, "expression"); } } throw parse_incomplete(); }