void IoMessage_parseName(IoMessage *self, IoLexer *lexer) { IoToken *token = IoLexer_pop(lexer); DATA(self)->name = IOREF(IOSYMBOL(IoToken_name(token))); IoMessage_ifPossibleCacheToken_(self, token); IoMessage_rawSetLineNumber_(self, IoToken_lineNumber(token)); IoMessage_rawSetCharNumber_(self, IoToken_charNumber(token)); }
IoMessage *IoMessage_newParseNextMessageChain(void *state, IoLexer *lexer) { IoCoroutine *current = IoState_currentCoroutine(state); Coro *coro = IoCoroutine_cid(current); size_t left = Coro_bytesLeftOnStack(coro); /* if (Coro_stackSpaceAlmostGone(coro)) { // need to make Coroutine support a stack of Coros which it frees when released // return IoCoroutine_internallyChain(current, context, IoMessage_...); Coro *newCoro = Coro_new(); ParseContext p = {state, lexer, newCoro, coro, NULL}; printf("Warning IoMessage_newParseNextMessageChain doing callc with %i bytes left to avoid stack overflow\n", left); Coro_startCoro_(coro, newCoro, &p, (CoroStartCallback *)IoMessage_coroNewParseNextMessageChain); Coro_free(newCoro); return p.result; } */ IoMessage *self = IoMessage_new(state); if (IoTokenType_isValidMessageName(IoLexer_topType(lexer))) { IoMessage_parseName(self, lexer); } if (IoLexer_topType(lexer) == OPENPAREN_TOKEN) { IoMessage_parseArgs(self, lexer); } if (IoTokenType_isValidMessageName(IoLexer_topType(lexer))) { IoMessage_parseNext(self, lexer); } while (IoLexer_topType(lexer) == TERMINATOR_TOKEN) { IoLexer_pop(lexer); if (IoTokenType_isValidMessageName(IoLexer_topType(lexer))) { IoMessage *eol = IoMessage_newWithName_(state, ((IoState*)state)->semicolonSymbol); IoMessage_rawSetNext(self, eol); IoMessage_parseNext(eol, lexer); } } return self; }
void IoMessage_parseArgs(IoMessage *self, IoLexer *lexer) { IoLexer_pop(lexer); if (IoTokenType_isValidMessageName(IoLexer_topType(lexer))) { IoMessage *arg = IoMessage_newParseNextMessageChain(IOSTATE, lexer); IoMessage_addArg_(self, arg); while (IoLexer_topType(lexer) == COMMA_TOKEN) { IoLexer_pop(lexer); if (IoTokenType_isValidMessageName(IoLexer_topType(lexer))) { IoMessage *arg = IoMessage_newParseNextMessageChain(IOSTATE, lexer); IoMessage_addArg_(self, arg); } // Does not actually work because the lexer detects this case and reports the error before we can handle it... // else if (IoLexer_topType(lexer) == CLOSEPAREN_TOKEN) //{ // // Allow the last arg to be empty as in, "foo(a,b,c,)". //} else { // TODO: Exception, missing message } } } if (IoLexer_topType(lexer) != CLOSEPAREN_TOKEN) { // TODO: Exception, missing close paren } IoLexer_pop(lexer); }
IO_METHOD(IoObject, tokensForString) { /*doc Compiler tokensForString(aString) Returns a list of token objects lexed from the input string. */ IoSymbol *text = IoMessage_locals_seqArgAt_(m, locals, 0); IoList *tokensList = IoList_new(IOSTATE); IoLexer *lexer = IoLexer_new(); IoSymbol *name = IOSYMBOL("name"); IoSymbol *line = IOSYMBOL("line"); IoSymbol *character = IOSYMBOL("character"); IoSymbol *type = IOSYMBOL("type"); IoLexer_string_(lexer, CSTRING(text)); IoLexer_lex(lexer); if (IoLexer_errorToken(lexer)) { IoSymbol *errorString = IOSYMBOL(IoLexer_errorDescription(lexer)); IoLexer_free(lexer); IoState_error_(IOSTATE, NULL, "compile error: %s", CSTRING(errorString)); } else { IoToken *t; while ((t = IoLexer_pop(lexer))) { IoObject *tokenObject = IoObject_new(IOSTATE); IoObject_setSlot_to_(tokenObject, name, IOSYMBOL(IoToken_name(t))); IoObject_setSlot_to_(tokenObject, line, IONUMBER(IoToken_lineNumber(t))); IoObject_setSlot_to_(tokenObject, character, IONUMBER(IoToken_charNumber(t))); IoObject_setSlot_to_(tokenObject, type, IOSYMBOL(IoToken_typeName(t))); IoList_rawAppend_(tokensList, tokenObject); } } IoLexer_free(lexer); return tokensList; }
IoMessage *IoMessage_newParse(void *state, IoLexer *lexer) { if (IoLexer_errorToken(lexer)) { IoMessage *m; IoSymbol *errorString; // Maybe the nil message could be used here. Or even a NULL. IoSymbol *error = IoState_symbolWithCString_(state, "Error"); m = IoMessage_newWithName_returnsValue_(state, error, error); errorString = IoState_symbolWithCString_((IoState *)state, IoLexer_errorDescription(lexer)); IoLexer_free(lexer); // hack for now - the caller should be responsible for this IoState_error_(state, m, "compile error: %s", CSTRING(errorString)); } if (IoLexer_topType(lexer) == TERMINATOR_TOKEN) { IoLexer_pop(lexer); } if (IoTokenType_isValidMessageName(IoLexer_topType(lexer))) { IoMessage *self = IoMessage_newParseNextMessageChain(state, lexer); if (IoLexer_topType(lexer) != NO_TOKEN) { // TODO: Exception as the end was expected IoState_error_(state, self, "compile error: %s", "unused tokens"); } return self; } return IoMessage_newWithName_returnsValue_(state, IoState_symbolWithCString_((IoState*)state, "nil"), ((IoState*)state)->ioNil ); }