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; }
char *IoLexer_errorDescription(IoLexer *self) { IoToken *et = IoLexer_errorToken(self); if (!self->errorDescription) { self->errorDescription = io_calloc(1, 1024); self->errorDescription[0] = 0; } if (et) { sprintf(self->errorDescription, "\"%s\" on line %i character %i", et->error, IoToken_lineNumber(et), IoToken_charNumber(et)); } return self->errorDescription; }
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 ); }