//------------------------------------------------------------------------------ int AcceptTokenType(READFILE Stream,TokenType Type) { if (CheckTokenType(Stream,Type)) { NextToken(Stream); return(1); } else { TokenError(Stream); return(0); } }
CharObj *CharObj::from_string(string repr) { size_t len = repr.length(); if (len < 2) return NULL; if (repr[0] != '#' || repr[1] != '\\') return NULL; if (len == 3) return new CharObj(repr[2]); string char_name = repr.substr(2, len - 2); if (char_name == "newline") return new CharObj('\n'); if (char_name == "space") return new CharObj(' '); throw TokenError(char_name, RUN_ERR_UNKNOWN_CHAR_NAME); }
// // TBuf::Expect // // Generates an error if lastToken is not 'expect' // void TBuf::Expect(const char *expect) { ASSERT(expect); // check last read token if (Utils::Strcmp(expect, lastToken)) { TokenError("Expecting '%s' but found '%s'", expect, lastToken); } }
//------------------------------------------------------------------------------ int TakeTokenType(READFILE Stream,TokenType Type) { if (CheckTokenType(Stream,Type)) { TakeCurrentToken(Stream); return(1); } else { TokenError(Stream); return(0); } }
//------------------------------------------------------------------------------ int AcceptToken(READFILE Stream,TokenType Type,char * Value) { if (CheckTokenType(Stream,Type) && !strcmp(CurrentToken(Stream)->NameToken,Value)) { NextToken(Stream); return(1); } else { TokenError(Stream); return(0); } }
EvalObj *Environment::get_obj(EvalObj *obj) { if (!obj->is_sym_obj()) return obj; SymObj *sym_obj = static_cast<SymObj*>(obj); string name(sym_obj->val); for (Environment *ptr = this; ptr; ptr = ptr->prev_envt) { bool has_key = ptr->binding.count(name); if (has_key) return ptr->binding[name]; } // Object not found throw TokenError(name, RUN_ERR_UNBOUND_VAR); }
// // TBuf::Accept // // Accept token 'accept', or generate error if different // void TBuf::Accept(const char *accept) { ASSERT(accept); // get next token switch (NextToken()) { case TR_OK : case TR_PUN : if (Utils::Strcmp(accept, lastToken)) { TokenError("Expecting '%s' but found '%s'", accept, lastToken); } break; case TR_EOF : EofError(accept); } }
Pair *ProcObj::call(Pair *_args, Environment * &lenvt, Continuation * &cont, EvalObj ** &top_ptr, Pair *pc) { // Create a new continuation Pair *ret_addr = cont->pc; if (cont->state) { Pair *nexp = TO_PAIR(cont->state->cdr); if (nexp == empty_list) { gc.expose(*top_ptr); *top_ptr++ = gc.attach(TO_PAIR(_args->cdr)->car); EXIT_CURRENT_EXEC(lenvt, cont, _args); // exit cont and envt return ret_addr->next; } else { // tail recursion opt if (nexp->cdr == empty_list && !nexp->car->is_simple_obj()) { cont->tail = true; cont->state = NULL; top_ptr++; // revert the cont } else { gc.attach(static_cast<EvalObj*>(*(++top_ptr))); cont->state = nexp; top_ptr++; } gc.expose(_args); return nexp; } } else { gc.expose(lenvt); lenvt = new Environment(envt); gc.attach(lenvt); EvalObj *ppar, *nptr; Pair *args = _args; for (ppar = params; ppar->is_pair_obj(); ppar = TO_PAIR(ppar)->cdr) { if ((nptr = args->cdr) != empty_list) args = TO_PAIR(nptr); else break; lenvt->add_binding(static_cast<SymObj*>(TO_PAIR(ppar)->car), args->car); } // (... . var_n) if (ppar->is_sym_obj()) lenvt->add_binding(static_cast<SymObj*>(ppar), args->cdr); else if (args->cdr != empty_list || ppar != empty_list) throw TokenError("", RUN_ERR_WRONG_NUM_OF_ARGS); gc.attach(static_cast<EvalObj*>(*(++top_ptr))); top_ptr++; cont->state = body; gc.expose(_args); // Move pc to the proc entry point return cont->state; } }
// // TBuf::EofError // // Triggers error "Expecting %s but reached end of data" // void TBuf::EofError(const char *expected) { TokenError("Expected %s but reached end of data", expected); }
// // TBuf::ExpectError // // Triggers error "Expecting %s but found '%s' // void TBuf::ExpectError(const char *expected, const char *found) { TokenError("Expected %s but found '%s'", expected, found); }
// // TBuf::NextChar() // // Get the next char from the buffer, returning FALSE // when there is no data left. // Bool TBuf::NextChar(U8 *c) { ASSERT(c); U8 n; // Filter comments and carriage returns do { ASSERT(bufPos <= bufSize); // Check if at end of data if (bufPos == bufSize) { // Are we reading a string constant if (constantOn) { TokenError("reached end of data in string constant"); } return (FALSE); } // Get the next character n = (U8) bufData[bufPos++]; // Adjust parse position if (n == TBUF_CH_EOL) { // Are we reading a string constant if (constantOn) { TokenError("newline in string constant"); } lastXPos = xPos; xPos = 0; yPos++; } else if (n != TBUF_CH_CR) { xPos++; } // if not in a constant, check commenting if (!constantOn) { // turn line comment mode on if (!commentOn && (CharType(n) == COMMENT)) { commentOn = TRUE; } // turn line comment mode off if (commentOn && (n == TBUF_CH_EOL)) { commentOn = FALSE; } } } while(commentOn || (n == TBUF_CH_CR)); // convert tabs to spaces if (n == TBUF_CH_TAB) { n = TBUF_CH_SPACE; } // set the char value *c = n; return(TRUE); }
// // TBuf::NextToken // // Reads the next token into 'dest'. Skips any preceeding spaces, // stopping when either a space, a punctuation char, or end of data // occurs. Generates an error if token exceeds max token length. // // Returns : // // TR_OK - if token was read with no problems // TR_PUN - if punctuation char was found // TR_EOF - if end of data reached // TBufResult TBuf::NextToken() { ASSERT(setup); U8 c; U32 tokenLen = 0; char *sPtr; // Have we peeked at the next token if (peekState == PS_ON) { peekState = PS_OFF; Utils::Strcpy(prevToken, lastToken); Utils::Strcpy(lastToken, peekToken); return (peekVal); } // Setup peek operation if (peekState == PS_PRE) { // Store next token in peek buffer sPtr = peekToken; // We are now in peek mode peekState = PS_ON; } else { // Save previous token Utils::Strcpy(prevToken, lastToken); // Store next token in last token buffer sPtr = lastToken; } // Clear token buffer *sPtr = '\0'; // Read next token for (;;) { // Have we reached the end of the data if (!NextChar(&c)) { // Return token if we have one return (tokenLen ? TR_OK : TR_EOF); } // Finish reading constant if (constantOn && c == constantChar) { constantOn = FALSE; } // Ignore these checks if reading a constant if (!constantOn) { // What char have we got if ((c == TBUF_CH_SPACE) || (c == TBUF_CH_EOL)) { // Have we read a token if (tokenLen) { return (TR_OK); } // Ignore this character continue; } // Check for punctuation if (CharType(c) == PUNCTUATION) { // Haven't read anything yet if (!tokenLen) { sPtr[0] = c; sPtr[1] = '\0'; return(TR_PUN); } // Successfully read a token StepBack(); return(TR_OK); } } // Add this char to the current token if (tokenLen < TBUF_MAX_TOKEN - 1) { sPtr[tokenLen++] = c; sPtr[tokenLen] = '\0'; } else { TokenError("maximum token length [%d bytes] exceeded", TBUF_MAX_TOKEN-1); } } }
//------------------------------------------------------------------------------ void EnsureToken(READFILE Stream,TokenType Type,char * Value) { if (!CheckToken(Stream,Type,Value)) { TokenError(Stream); } }
//------------------------------------------------------------------------------ void EnsureTokenType(READFILE Stream,TokenType Type) { if (!CheckTokenType(Stream,Type)) { TokenError(Stream); } }
void Compiler::Phase3() { TokenListNode *cn = m_tl.head; while (cn != nullptr) { if (TokenHelper::IsOpcodeOrDirective(cn->value->type)) { switch (cn->value->type) { case TokenType::Opcode: if (OpcodeInfo::Get(cn->value->value).hasoperand) { if (cn->next != nullptr && !TokenHelper::IsOperand(cn->next->value->type)) throw TokenError(cn->next->value, m_name, "Expected valid operand"); if (cn->next != nullptr) cn = cn->next; } break; default: throw TokenError(cn->value, m_name, "Invalid token type"); } } else if (cn->value->type == TokenType::LabelDef) ; // just ignore it else throw TokenError(cn->value, m_name, "Invalid token type"); if (cn != nullptr) cn = cn->next; } /* Check for invalid exports */ for (std::string &exported : m_tl.exports) { bool found = false; for (const auto &l : m_tl.labels) if (std::get<0>(l) == exported) found = true; if (!found) throw GenericError("Undefined label " + exported); } /* Check for duplicate exports */ int d_count = 0; for (std::string &e : m_tl.exports) { for (std::string &e2 : m_tl.exports) if (e2 == e && ++d_count > 1) throw GenericError("Duplicate export " + e2); d_count = 0; } /* Check for duplicate labels */ d_count = 0; for (const auto &l : m_tl.labels) { for (const auto &l2 : m_tl.labels) if (std::get<0>(l) == std::get<0>(l2) && ++d_count > 1) throw TokenError(std::get<1>(l2)->value, m_name, "Duplicate label " + std::get<0>(l)); d_count = 0; } }