int mathWrapInt(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c; int err; a = g->sp - 2; b = g->sp - 1; c = g->sp; if (IsSym(b)) { *a = *b; } else if (IsSym(c)) { *a = *c; } else if (IsInt(b) && IsInt(c)) { SetRaw(a, sc_mod((int)(slotRawInt(a) - slotRawInt(b)), (int)(slotRawInt(c) - slotRawInt(b) + 1)) + slotRawInt(b)); } else { double x, lo, hi; x = slotRawInt(a); err = slotDoubleVal(b, &lo); if (err) return err; err = slotDoubleVal(c, &hi); if (err) return err; SetFloat(a, sc_mod(x - lo, hi - lo) + lo); } return errNone; }
int mathFoldInt(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c; int err; a = g->sp - 2; b = g->sp - 1; c = g->sp; if (IsSym(b)) { *a = *b; } else if (IsSym(c)) { *a = *c; } else if (IsInt(b) && IsInt(c)) { SetRaw(a, sc_fold(slotRawInt(a), slotRawInt(b), slotRawInt(c))); } else { double x, lo, hi; x = slotRawInt(a); err = slotDoubleVal(b, &lo); if (err) return err; err = slotDoubleVal(c, &hi); if (err) return err; SetFloat(a, sc_fold(x, lo, hi)); } return errNone; }
int mathFoldSignal(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c; float lo, hi; int err; PyrObject *sig; a = g->sp - 2; b = g->sp - 1; c = g->sp; if (IsSym(b)) { *a = *b; } else if (IsSym(c)) { *a = *c; } else if (IsSignal(b) && IsSignal(c)) { sig = signal_fold_x(g, slotRawObject(a), slotRawObject(b), slotRawObject(c)); SetObject(a, sig); } else { err = slotFloatVal(b, &lo); if (err) return err; err = slotFloatVal(c, &hi); if (err) return err; sig = signal_fold_f(g, slotRawObject(a), lo, hi); SetObject(a, sig); } return errNone; }
int prArray_OSCBytes(VMGlobals *g, int numArgsPushed) { PyrSlot* a = g->sp; PyrObject *array = a->uo; PyrSlot* args = array->slots; int numargs = array->size; if (numargs < 1) return errFailed; big_scpacket packet; if (IsFloat(args) || IsNil(args) || IsInt(args)) { makeSynthBundle(&packet, args, numargs, false); } else if (IsSym(args) || isKindOfSlot(args, class_string)) { makeSynthMsgWithTags(&packet, args, numargs); } else { return errWrongType; } int size = packet.size(); PyrInt8Array* obj = newPyrInt8Array(g->gc, size, 0, true); obj->size = size; memcpy(obj->b, packet.data(), size); SetObject(a, (PyrObject*)obj); //for (int i=0; i<packet.size()/4; i++) post("%d %08X\n", i, packet.buf[i]); return errNone; }
int prSymbolIsPrefix(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b; int length; a = g->sp - 1; b = g->sp; if (!IsSym(a) || !IsSym(b)) return errWrongType; int32 alen = slotRawSymbol(a)->length; int32 blen = slotRawSymbol(b)->length; length = sc_min(alen, blen); if (memcmp(slotRawSymbol(a)->name, slotRawSymbol(b)->name, length) == 0) { SetTrue(a); } else { SetFalse(a); } return errNone; }
int prSymbol_matchOSCPattern(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b; int length; a = g->sp - 1; b = g->sp; if (!IsSym(a) || !IsSym(b)) return errWrongType; // int32 alen = slotRawSymbol(a)->length; // int32 blen = slotRawSymbol(b)->length; // length = sc_min(alen, blen); if (lo_pattern_match(slotRawSymbol(a)->name, slotRawSymbol(b)->name)) { SetTrue(a); } else { SetFalse(a); } return errNone; }
int identDictPut(struct VMGlobals *g, PyrObject *dict, PyrSlot *key, PyrSlot *value) { PyrSlot *slot, *newslot; int i, index, size; PyrObject *array; bool knows = IsTrue(dict->slots + ivxIdentDict_know); if (knows && IsSym(key)) { if (slotRawSymbol(key) == s_parent) { slotCopy(&dict->slots[ivxIdentDict_parent],value); g->gc->GCWrite(dict, value); return errNone; } if (slotRawSymbol(key) == s_proto) { slotCopy(&dict->slots[ivxIdentDict_proto],value); g->gc->GCWrite(dict, value); return errNone; } } array = slotRawObject(&dict->slots[ivxIdentDict_array]); if (array->IsImmutable()) return errImmutableObject; if (!isKindOf((PyrObject*)array, class_array)) return errFailed; index = arrayAtIdentityHashInPairs(array, key); slot = array->slots + index; slotCopy(&slot[1],value); g->gc->GCWrite(array, value); if (IsNil(slot)) { slotCopy(slot,key); g->gc->GCWrite(array, key); size = slotRawInt(&dict->slots[ivxIdentDict_size]) + 1; SetRaw(&dict->slots[ivxIdentDict_size], size); if (array->size < size*3) { PyrObject *newarray; newarray = newPyrArray(g->gc, size*3, 0, false); newarray->size = ARRAYMAXINDEXSIZE(newarray); nilSlots(newarray->slots, newarray->size); slot = array->slots; for (i=0; i<array->size; i+=2, slot+=2) { if (NotNil(slot)) { index = arrayAtIdentityHashInPairs(newarray, slot); newslot = newarray->slots + index; slotCopy(&newslot[0],&slot[0]); slotCopy(&newslot[1],&slot[1]); } } SetRaw(&dict->slots[ivxIdentDict_array], newarray); g->gc->GCWriteNew(dict, newarray); // we know newarray is white so we can use GCWriteNew } } return errNone; }
static int MacName (char* Ident) /* Get a macro symbol name into Ident. If we have an error, print a * diagnostic message and clear the line. */ { if (IsSym (Ident) == 0) { PPError ("Identifier expected"); ClearLine (); return 0; } else { return 1; } }
int identDictPut(struct VMGlobals *g, PyrObject *dict, PyrSlot *key, PyrSlot *value) { PyrSlot *slot, *newslot; int i, index, size; PyrObject *array; bool knows = IsTrue(dict->slots + ivxIdentDict_know); if (knows && IsSym(key)) { if (key->us == s_parent) { slotCopy(&dict->slots[ivxIdentDict_parent],value); g->gc->GCWrite(dict, value); return errNone; } if (key->us == s_proto) { slotCopy(&dict->slots[ivxIdentDict_proto],value); g->gc->GCWrite(dict, value); return errNone; } } array = dict->slots[ivxIdentDict_array].uo; if (!isKindOf((PyrObject*)array, class_array)) return errFailed; index = arrayAtIdentityHashInPairs(array, key); slot = array->slots + index; slotCopy(&slot[1],value); g->gc->GCWrite(array, value); if (IsNil(slot)) { slotCopy(slot,key); g->gc->GCWrite(array, key); size = ++dict->slots[ivxIdentDict_size].ui; if (array->size < size*3) { PyrObject *newarray; newarray = newPyrArray(g->gc, size*3, 0, false); newarray->size = ARRAYMAXINDEXSIZE(newarray); nilSlots(newarray->slots, newarray->size); slot = array->slots; for (i=0; i<array->size; i+=2, slot+=2) { if (NotNil(slot)) { index = arrayAtIdentityHashInPairs(newarray, slot); newslot = newarray->slots + index; slotCopy(&newslot[0],&slot[0]); slotCopy(&newslot[1],&slot[1]); } } dict->slots[ivxIdentDict_array].uo = newarray; g->gc->GCWrite(dict, newarray); } } return errNone; }
int mathWrapFloat(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c; double lo, hi; int err; a = g->sp - 2; b = g->sp - 1; c = g->sp; if (IsSym(b)) { *a = *b; } else if (IsSym(c)) { *a = *c; } else { err = slotDoubleVal(b, &lo); if (err) return err; err = slotDoubleVal(c, &hi); if (err) return err; SetRaw(a, sc_mod(slotRawFloat(a) - lo, hi - lo) + lo); } return errNone; }
int prIdentDict_At(struct VMGlobals *g, int numArgsPushed) { PyrSlot* a = g->sp - 1; // dict PyrSlot* key = g->sp; // key PyrObject *dict = slotRawObject(a); bool knows = IsTrue(dict->slots + ivxIdentDict_know); if (knows && IsSym(key)) { if (slotRawSymbol(key) == s_parent) { slotCopy(a,&dict->slots[ivxIdentDict_parent]); return errNone; } if (slotRawSymbol(key) == s_proto) { slotCopy(a,&dict->slots[ivxIdentDict_proto]); return errNone; } } identDict_lookup(dict, key, calcHash(key), a); return errNone; }
static void MacroReplacement (StrBuf* Source, StrBuf* Target) /* Perform macro replacement. */ { ident Ident; Macro* M; /* Remember the current input and switch to Source */ StrBuf* OldSource = InitLine (Source); /* Loop substituting macros */ while (CurC != '\0') { /* If we have an identifier, check if it's a macro */ if (IsSym (Ident)) { /* Check if it's a macro */ if ((M = FindMacro (Ident)) != 0 && !M->Expanding) { /* It's a macro, expand it */ ExpandMacro (Target, M); } else { /* An identifier, keep it */ SB_AppendStr (Target, Ident); } } else if (IsQuote (CurC)) { CopyQuotedString (Target); } else if (IsSpace (CurC)) { if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, CurC); } NextChar (); } else { SB_AppendChar (Target, CurC); NextChar (); } } /* Switch back the input */ InitLine (OldSource); }
void Preprocess (void) /* Preprocess a line */ { int Skip; ident Directive; /* Create the output buffer if we don't already have one */ if (MLine == 0) { MLine = NewStrBuf (); } /* Skip white space at the beginning of the line */ SkipWhitespace (0); /* Check for stuff to skip */ Skip = 0; while (CurC == '\0' || CurC == '#' || Skip) { /* Check for preprocessor lines lines */ if (CurC == '#') { NextChar (); SkipWhitespace (0); if (CurC == '\0') { /* Ignore the empty preprocessor directive */ continue; } if (!IsSym (Directive)) { PPError ("Preprocessor directive expected"); ClearLine (); } else { switch (FindPPToken (Directive)) { case PP_DEFINE: if (!Skip) { DefineMacro (); } break; case PP_ELIF: if (IfIndex >= 0) { if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) { /* Handle as #else/#if combination */ if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) { Skip = !Skip; } IfStack[IfIndex] |= IFCOND_ELSE; Skip = DoIf (Skip); /* #elif doesn't need a terminator */ IfStack[IfIndex] &= ~IFCOND_NEEDTERM; } else { PPError ("Duplicate #else/#elif"); } } else { PPError ("Unexpected #elif"); } break; case PP_ELSE: if (IfIndex >= 0) { if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) { if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) { Skip = !Skip; } IfStack[IfIndex] |= IFCOND_ELSE; } else { PPError ("Duplicate #else"); } } else { PPError ("Unexpected `#else'"); } break; case PP_ENDIF: if (IfIndex >= 0) { /* Remove any clauses on top of stack that do not * need a terminating #endif. */ while (IfIndex >= 0 && (IfStack[IfIndex] & IFCOND_NEEDTERM) == 0) { --IfIndex; } /* Stack may not be empty here or something is wrong */ CHECK (IfIndex >= 0); /* Remove the clause that needs a terminator */ Skip = (IfStack[IfIndex--] & IFCOND_SKIP) != 0; } else { PPError ("Unexpected `#endif'"); } break; case PP_ERROR: if (!Skip) { DoError (); } break; case PP_IF: Skip = DoIf (Skip); break; case PP_IFDEF: Skip = DoIfDef (Skip, 1); break; case PP_IFNDEF: Skip = DoIfDef (Skip, 0); break; case PP_INCLUDE: if (!Skip) { DoInclude (); } break; case PP_LINE: /* Should do something in C99 at least, but we ignore it */ if (!Skip) { ClearLine (); } break; case PP_PRAGMA: if (!Skip) { DoPragma (); goto Done; } break; case PP_UNDEF: if (!Skip) { DoUndef (); } break; case PP_WARNING: /* #warning is a non standard extension */ if (IS_Get (&Standard) > STD_C99) { if (!Skip) { DoWarning (); } } else { if (!Skip) { PPError ("Preprocessor directive expected"); } ClearLine (); } break; default: if (!Skip) { PPError ("Preprocessor directive expected"); } ClearLine (); } } } if (NextLine () == 0) { if (IfIndex >= 0) { PPError ("`#endif' expected"); } return; } SkipWhitespace (0); } PreprocessLine (); Done: if (Verbosity > 1 && SB_NotEmpty (Line)) { printf ("%s(%u): %.*s\n", GetCurrentFile (), GetCurrentLine (), (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } }
void NextToken (void) /* Get next token from input stream */ { ident token; /* We have to skip white space here before shifting tokens, since the ** tokens and the current line info is invalid at startup and will get ** initialized by reading the first time from the file. Remember if ** we were at end of input and handle that later. */ int GotEOF = (SkipWhite() == 0); /* Current token is the lookahead token */ if (CurTok.LI) { ReleaseLineInfo (CurTok.LI); } CurTok = NextTok; /* When reading the first time from the file, the line info in NextTok, ** which was copied to CurTok is invalid. Since the information from ** the token is used for error messages, we must make it valid. */ if (CurTok.LI == 0) { CurTok.LI = UseLineInfo (GetCurLineInfo ()); } /* Remember the starting position of the next token */ NextTok.LI = UseLineInfo (GetCurLineInfo ()); /* Now handle end of input. */ if (GotEOF) { /* End of file reached */ NextTok.Tok = TOK_CEOF; return; } /* Determine the next token from the lookahead */ if (IsDigit (CurC) || (CurC == '.' && IsDigit (NextC))) { /* A number */ NumericConst (); return; } /* Check for wide character literals */ if (CurC == 'L' && NextC == '\"') { StringConst (); return; } /* Check for keywords and identifiers */ if (IsSym (token)) { /* Check for a keyword */ if ((NextTok.Tok = FindKey (token)) != TOK_IDENT) { /* Reserved word found */ return; } /* No reserved word, check for special symbols */ if (token[0] == '_' && token[1] == '_') { /* Special symbols */ if (strcmp (token+2, "FILE__") == 0) { NextTok.SVal = AddLiteral (GetCurrentFile()); NextTok.Tok = TOK_SCONST; return; } else if (strcmp (token+2, "LINE__") == 0) { NextTok.Tok = TOK_ICONST; NextTok.IVal = GetCurrentLine(); NextTok.Type = type_int; return; } else if (strcmp (token+2, "func__") == 0) { /* __func__ is only defined in functions */ if (CurrentFunc) { NextTok.SVal = AddLiteral (F_GetFuncName (CurrentFunc)); NextTok.Tok = TOK_SCONST; return; } } } /* No reserved word but identifier */ strcpy (NextTok.Ident, token); NextTok.Tok = TOK_IDENT; return; } /* Monstrous switch statement ahead... */ switch (CurC) { case '!': NextChar (); if (CurC == '=') { SetTok (TOK_NE); } else { NextTok.Tok = TOK_BOOL_NOT; } break; case '\"': StringConst (); break; case '%': NextChar (); if (CurC == '=') { SetTok (TOK_MOD_ASSIGN); } else { NextTok.Tok = TOK_MOD; } break; case '&': NextChar (); switch (CurC) { case '&': SetTok (TOK_BOOL_AND); break; case '=': SetTok (TOK_AND_ASSIGN); break; default: NextTok.Tok = TOK_AND; } break; case '\'': CharConst (); break; case '(': SetTok (TOK_LPAREN); break; case ')': SetTok (TOK_RPAREN); break; case '*': NextChar (); if (CurC == '=') { SetTok (TOK_MUL_ASSIGN); } else { NextTok.Tok = TOK_STAR; } break; case '+': NextChar (); switch (CurC) { case '+': SetTok (TOK_INC); break; case '=': SetTok (TOK_PLUS_ASSIGN); break; default: NextTok.Tok = TOK_PLUS; } break; case ',': SetTok (TOK_COMMA); break; case '-': NextChar (); switch (CurC) { case '-': SetTok (TOK_DEC); break; case '=': SetTok (TOK_MINUS_ASSIGN); break; case '>': SetTok (TOK_PTR_REF); break; default: NextTok.Tok = TOK_MINUS; } break; case '.': NextChar (); if (CurC == '.') { NextChar (); if (CurC == '.') { SetTok (TOK_ELLIPSIS); } else { UnknownChar (CurC); } } else { NextTok.Tok = TOK_DOT; } break; case '/': NextChar (); if (CurC == '=') { SetTok (TOK_DIV_ASSIGN); } else { NextTok.Tok = TOK_DIV; } break; case ':': SetTok (TOK_COLON); break; case ';': SetTok (TOK_SEMI); break; case '<': NextChar (); switch (CurC) { case '=': SetTok (TOK_LE); break; case '<': NextChar (); if (CurC == '=') { SetTok (TOK_SHL_ASSIGN); } else { NextTok.Tok = TOK_SHL; } break; default: NextTok.Tok = TOK_LT; } break; case '=': NextChar (); if (CurC == '=') { SetTok (TOK_EQ); } else { NextTok.Tok = TOK_ASSIGN; } break; case '>': NextChar (); switch (CurC) { case '=': SetTok (TOK_GE); break; case '>': NextChar (); if (CurC == '=') { SetTok (TOK_SHR_ASSIGN); } else { NextTok.Tok = TOK_SHR; } break; default: NextTok.Tok = TOK_GT; } break; case '?': SetTok (TOK_QUEST); break; case '[': SetTok (TOK_LBRACK); break; case ']': SetTok (TOK_RBRACK); break; case '^': NextChar (); if (CurC == '=') { SetTok (TOK_XOR_ASSIGN); } else { NextTok.Tok = TOK_XOR; } break; case '{': SetTok (TOK_LCURLY); break; case '|': NextChar (); switch (CurC) { case '|': SetTok (TOK_BOOL_OR); break; case '=': SetTok (TOK_OR_ASSIGN); break; default: NextTok.Tok = TOK_OR; } break; case '}': SetTok (TOK_RCURLY); break; case '~': SetTok (TOK_COMP); break; default: UnknownChar (CurC); } }
static unsigned Pass1 (StrBuf* Source, StrBuf* Target) /* Preprocessor pass 1. Remove whitespace. Handle old and new style comments * and the "defined" operator. */ { unsigned IdentCount; ident Ident; int HaveParen; /* Switch to the new input source */ StrBuf* OldSource = InitLine (Source); /* Loop removing ws and comments */ IdentCount = 0; while (CurC != '\0') { if (SkipWhitespace (0)) { /* Squeeze runs of blanks */ if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, ' '); } } else if (IsSym (Ident)) { if (Preprocessing && strcmp (Ident, "defined") == 0) { /* Handle the "defined" operator */ SkipWhitespace (0); HaveParen = 0; if (CurC == '(') { HaveParen = 1; NextChar (); SkipWhitespace (0); } if (IsSym (Ident)) { SB_AppendChar (Target, IsMacro (Ident)? '1' : '0'); if (HaveParen) { SkipWhitespace (0); if (CurC != ')') { PPError ("`)' expected"); } else { NextChar (); } } } else { PPError ("Identifier expected"); SB_AppendChar (Target, '0'); } } else { ++IdentCount; SB_AppendStr (Target, Ident); } } else if (IsQuote (CurC)) { CopyQuotedString (Target); } else if (CurC == '/' && NextC == '*') { if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, ' '); } OldStyleComment (); } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') { if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, ' '); } NewStyleComment (); } else { SB_AppendChar (Target, CurC); NextChar (); } } /* Switch back to the old source */ InitLine (OldSource); /* Return the number of identifiers found in the line */ return IdentCount; }
static void MacroArgSubst (MacroExp* E) /* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff */ { ident Ident; int ArgIdx; StrBuf* OldSource; StrBuf* Arg; int HaveSpace; /* Remember the current input and switch to the macro replacement. */ int OldIndex = SB_GetIndex (&E->M->Replacement); SB_Reset (&E->M->Replacement); OldSource = InitLine (&E->M->Replacement); /* Argument handling loop */ while (CurC != '\0') { /* If we have an identifier, check if it's a macro */ if (IsSym (Ident)) { /* Check if it's a macro argument */ if ((ArgIdx = FindMacroArg (E->M, Ident)) >= 0) { /* A macro argument. Get the corresponding actual argument. */ Arg = ME_GetActual (E, ArgIdx); /* Copy any following whitespace */ HaveSpace = SkipWhitespace (0); /* If a ## operator follows, we have to insert the actual * argument as is, otherwise it must be macro replaced. */ if (CurC == '#' && NextC == '#') { /* ### Add placemarker if necessary */ SB_Append (&E->Replacement, Arg); } else { /* Replace the formal argument by a macro replaced copy * of the actual. */ SB_Reset (Arg); MacroReplacement (Arg, &E->Replacement); /* If we skipped whitespace before, re-add it now */ if (HaveSpace) { SB_AppendChar (&E->Replacement, ' '); } } } else { /* An identifier, keep it */ SB_AppendStr (&E->Replacement, Ident); } } else if (CurC == '#' && NextC == '#') { /* ## operator. */ NextChar (); NextChar (); SkipWhitespace (0); /* Since we need to concatenate the token sequences, remove * any whitespace that was added to target, since it must come * from the input. */ while (IsSpace (SB_LookAtLast (&E->Replacement))) { SB_Drop (&E->Replacement, 1); } /* If the next token is an identifier which is a macro argument, * replace it, otherwise do nothing. */ if (IsSym (Ident)) { /* Check if it's a macro argument */ if ((ArgIdx = FindMacroArg (E->M, Ident)) >= 0) { /* Get the corresponding actual argument and add it. */ SB_Append (&E->Replacement, ME_GetActual (E, ArgIdx)); } else { /* Just an ordinary identifier - add as is */ SB_AppendStr (&E->Replacement, Ident); } } } else if (CurC == '#' && E->M->ArgCount >= 0) { /* A # operator within a macro expansion of a function like * macro. Read the following identifier and check if it's a * macro parameter. */ NextChar (); SkipWhitespace (0); if (!IsSym (Ident) || (ArgIdx = FindMacroArg (E->M, Ident)) < 0) { PPError ("`#' is not followed by a macro parameter"); } else { /* Make a valid string from Replacement */ Arg = ME_GetActual (E, ArgIdx); SB_Reset (Arg); Stringize (Arg, &E->Replacement); } } else if (IsQuote (CurC)) { CopyQuotedString (&E->Replacement); } else { SB_AppendChar (&E->Replacement, CurC); NextChar (); } } #if 0 /* Remove whitespace from the end of the line */ while (IsSpace (SB_LookAtLast (&E->Replacement))) { SB_Drop (&E->Replacement, 1); } #endif /* Switch back the input */ InitLine (OldSource); SB_SetIndex (&E->M->Replacement, OldIndex); }
Token & TokenFactory:: DoSymbol(unsigned char ch) { // Get the position of the start of the symbol std::streampos pos = m_sCur->tellg(); pos -= 1; // State of symbol determination E_STATE state = ES__NONE; // Current symbol type TokenType::E_TYPE type = TokenType::TT_SYMBOL; do { switch (state) { case ES__NONE: // ES_NONE switch (ch) { case 'A': if (CheckLetters("rray")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_Array; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'B': if (CheckLetters("oolean")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_Boolean; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'D': if (CheckLetters("ate")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_Date; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'E': state = ES_E; // ES_E break; case 'F': if (CheckLetters("unction")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_Function; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'M': if (CheckLetters("ath")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_Math; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'N': if (CheckLetters("umber")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_Number; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'O': if (CheckLetters("bject")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_Object; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'R': state = ES_R; // ES_R break; case 'S': state = ES_S; // ES_S break; case 'T': if (CheckLetters("ypeError")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_TypeError; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'U': if (CheckLetters("RIError")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_URIError; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'a': if (CheckLetters("bstract")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_abstract; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'b': state = ES_b; // ES_b break; case 'c': state = ES_c; // ES_c break; case 'd': state = ES_d; // ES_d break; case 'e': state = ES_e; // ES_e break; case 'f': state = ES_f; // ES_f break; case 'g': if (CheckLetters("oto")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_goto; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'i': state = ES_i; // ES_i break; case 'l': if (CheckLetters("ong")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_long; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'n': state = ES_n; // ES_n break; case 'p': state = ES_p; // ES_p break; case 'r': if (CheckLetters("eturn")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_return; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 's': state = ES_s; // ES_s break; case 't': state = ES_t; // ES_t break; case 'u': if (CheckLetters("ndefined")) // Can only be this or unknown { // "undefined" is not a keyword but // is often used as one, we'll treat it // as one but warn them of the problems state = ES__DONE; // Mark as done type = TokenType::TK_undefined; Message::Send(Message::USED_UNDEFINED); } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'v': state = ES_v; // ES_v break; case 'w': state = ES_w; // ES_w break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_E: // ES_E switch (ch) { case 'r': if (CheckLetters("ror")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_Error; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'v': if (CheckLetters("alError")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_EvalError; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_R: // ES_R switch (ch) { case 'a': if (CheckLetters("ngeError")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_RangeError; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'e': state = ES_Re; // ES_Re break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_Re: // ES_Re switch (ch) { case 'f': if (CheckLetters("erenceError")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_ReferenceError; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'g': if (CheckLetters("Exp")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_RegExp; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_S: // ES_S switch (ch) { case 't': if (CheckLetters("ring")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_String; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'y': if (CheckLetters("ntaxError")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TG_SyntaxError; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_b: // ES_b switch (ch) { case 'o': if (CheckLetters("olean")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_boolean; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'r': if (CheckLetters("eak")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_break; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'y': if (CheckLetters("te")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_byte; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_c: // ES_c switch (ch) { case 'a': state = ES_ca; // ES_ca break; case 'h': if (CheckLetters("ar")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_char; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'l': if (CheckLetters("ass")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_class; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'o': if (CheckLetters("n")) // All possible symbols have these symbols { state = ES_con; // ES_con } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_ca: // ES_ca switch (ch) { case 's': if (CheckLetters("e")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_case; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 't': if (CheckLetters("ch")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_catch; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_con: // ES_con switch (ch) { case 's': if (CheckLetters("t")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_const; // SOME browsers implement this (at least FF) // but others don't (at least IE) } else { state = ES__UNKNOWN; // Mark as unknown } break; case 't': if (CheckLetters("inue")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_continue; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_d: // ES_d switch (ch) { case 'e': state = ES_de; // ES_de break; case 'o': state = ES_do; // ES_do type = TokenType::TK_do; break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_de: // ES_de switch (ch) { case 'b': if (CheckLetters("ugger")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_debugger; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'f': if (CheckLetters("ault")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_default; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'l': if (CheckLetters("ete")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_delete; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_do: // ES_do switch (ch) { case 'u': if (CheckLetters("ble")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_double; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_e: // ES_e switch (ch) { case 'l': if (CheckLetters("se")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_else; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'n': if (CheckLetters("um")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_enum; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'v': if (CheckLetters("al")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_eval; // Bad Bad Bad } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'x': state = ES_ex; // ES_ex break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_ex: // ES_ex switch (ch) { case 'p': if (CheckLetters("ort")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_export; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 't': if (CheckLetters("ends")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_extends; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_f: // ES_f switch (ch) { case 'a': if (CheckLetters("lse")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_false; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'i': if (CheckLetters("nal")) // All possible symbols have these symbols { state = ES_final; // ES_final type = TokenType::TR_final; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'l': if (CheckLetters("oat")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_float; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'o': if (CheckLetters("r")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_for; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'u': if (CheckLetters("nction")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_function; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_final: // ES_final switch (ch) { case 'l': if (CheckLetters("y")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_finally; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_i: // ES_i switch (ch) { case 'f': state = ES__DONE; // Mark as done type = TokenType::TK_if; break; case 'm': if (CheckLetters("p")) // All possible symbols have these symbols { state = ES_imp; // ES_imp } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'n': state = ES_in; // ES_in type = TokenType::TK_in; break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_imp: // ES_imp switch (ch) { case 'l': if (CheckLetters("ements")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_implements; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'o': if (CheckLetters("rt")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_import; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_in: // ES_in switch (ch) { case 's': if (CheckLetters("tanceof")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_instanceof; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 't': state = ES_int; // ES_int type = TokenType::TR_int; break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_int: // ES_int switch (ch) { case 'e': if (CheckLetters("rface")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_interface; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_n: // ES_n switch (ch) { case 'a': if (CheckLetters("tive")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_native; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'e': if (CheckLetters("w")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_new; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'u': if (CheckLetters("ll")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_null; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_p: // ES_p switch (ch) { case 'a': if (CheckLetters("ckage")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_package; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'r': state = ES_pr; // ES_pr break; case 'u': if (CheckLetters("blic")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_public; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_pr: // ES_pr switch (ch) { case 'i': if (CheckLetters("vate")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_private; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'o': if (CheckLetters("tected")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_protected; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_s: // ES_s switch (ch) { case 'h': if (CheckLetters("ort")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_short; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 't': if (CheckLetters("atic")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_static; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'u': if (CheckLetters("per")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_super; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'w': if (CheckLetters("itch")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_switch; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'y': if (CheckLetters("nchronized")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_synchronized; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_t: // ES_t switch (ch) { case 'h': state = ES_th; // ES_th break; case 'r': state = ES_tr; // ES_tr break; case 'y': if (CheckLetters("peof")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_typeof; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_th: // ES_th switch (ch) { case 'i': if (CheckLetters("s")) // Can only be this or unknown { state = ES__DONE; // Mark as done //type = TokenType::TT_THIS; // Special case, "this" keyword //value.keyword = SymbolType::EK_this; // Only needed for the check below type = TokenType::TK_this; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'r': if (CheckLetters("ow")) // All possible symbols have these symbols { state = ES_throw; // ES_throw type = TokenType::TK_throw; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_throw: // ES_throw switch (ch) { case 's': state = ES__DONE; // Mark as done type = TokenType::TR_throws; break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_tr: // ES_tr switch (ch) { case 'a': if (CheckLetters("nsient")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_transient; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'u': if (CheckLetters("e")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_true; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'y': state = ES__DONE; // Mark as done type = TokenType::TK_try; break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_v: // ES_v switch (ch) { case 'a': if (CheckLetters("r")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_var; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'o': state = ES_vo; // ES_vo break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_vo: // ES_vo switch (ch) { case 'i': if (CheckLetters("d")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_void; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'l': if (CheckLetters("atile")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TR_volatile; } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES_w: // ES_w switch (ch) { case 'h': if (CheckLetters("ile")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_while; } else { state = ES__UNKNOWN; // Mark as unknown } break; case 'i': if (CheckLetters("th")) // Can only be this or unknown { state = ES__DONE; // Mark as done type = TokenType::TK_with; // Bad Bad Bad } else { state = ES__UNKNOWN; // Mark as unknown } break; default: state = ES__UNKNOWN; // Mark as unknown break; } break; case ES__DONE: // If it's done that means there's no longer known // word that it can be, so if we get another char // then it's a custom symbol that starts out the // same as a regular symbol Message::Send(Message::POSSIBLY_AMBIGUOUS); state = ES__UNKNOWN; break; case ES__UNKNOWN: // Do nothing, we're just collecting data break; default: Message::Send(Message::UNKNOWN_STATE); state = ES__UNKNOWN; break; } ch = Read(); // Check IsSym and IsDec as now they're both // valid symbol characters } while (IsSym(ch) || IsDec(ch)); if (state == ES__UNKNOWN || type == TokenType::TT_SYMBOL) { // Technically not "unknown" // Just a new custom symbol // Found a new token std::streampos len; if (!ch) { // At the end of the file m_sCur->clear(); len = 1; } else { len = 0; } len += m_sCur->tellg(); len -= pos; // Include NULL in allocation // Use alloca because we only need this // temporarilly and it's easy to handle // no need to remember to delete the // memory on function exit or exception char * c = (char *)alloca(len); if (c) { // Get the start of the symbol and read m_sCur->seekg(pos); len -= 1; m_sCur->read(c, len); c[len] = '\0'; Preprocessor & pp = Compiler::Get().GetPreprocessor(); // Check if this is a macro if (pp.Defined(c)) { // Yes m_altIn.push(pp.Get(c)); return GetNext(); } if (m_sCur->bad()) { // Error reading Message::Send(Message::INPUT_STREAM_ERROR); } else { // Read, save token return Create(c, TokenType::TT_SYMBOL); } } else { m_sCur->unget(); Message::Send(Message::OUT_OF_MEMORY); } // Something went wrong // Compile should fail return Create(TokenType::TT__NONE); } else { // Found an existing known token if (TokenType::IsReserved(type) && type != TokenType::TK_undefined) { // Using a reserved word, may conflict in future Message::Send(Message::USED_RESERVE, SC::L(type)); } // Return a character to the stream m_sCur->unget(); return Create(type); } }