/* IdentifierToken - get an identifier */ static int IdentifierToken(ParseContext *c, int ch) { int len, i; char *p; /* get the identifier */ p = c->token; *p++ = ch; len = 1; while ((ch = GetChar(c)) != EOF && IdentifierCharP(ch)) { if (++len > MAXTOKEN) ParseError(c, "Identifier too long"); *p++ = ch; } UngetC(c); *p = '\0'; /* check to see if it is a keyword */ for (i = 0; ktab[i].keyword != NULL; ++i) if (strcasecmp(ktab[i].keyword, c->token) == 0) return ktab[i].token; /* otherwise, it is an identifier */ return T_IDENTIFIER; }
/* GetChar - get the next character */ int GetChar(ParseContext *c) { int ch; /* check for being in a comment */ if (c->inComment) { if (!SkipComment(c)) return EOF; c->inComment = VMFALSE; } /* loop until we find a non-comment character */ for (;;) { /* get the next character */ if ((ch = XGetC(c)) == EOF) return EOF; /* check for a comment */ else if (ch == '/') { if ((ch = XGetC(c)) == '/') { while ((ch = XGetC(c)) != EOF) ; } else if (ch == '*') { if (!SkipComment(c)) { c->inComment = VMTRUE; return EOF; } } else { UngetC(c); ch = '/'; break; } } /* handle a normal character */ else break; } /* return the character */ return ch; }
/* BinaryNumberToken - get a binary number */ static int BinaryNumberToken(ParseContext *c) { char *p = c->token; int ch; /* get the number */ while ((ch = GetChar(c)) != EOF) { if (ch == '0' || ch == '1') *p++ = ch; else if (ch != '_') break; } UngetC(c); *p = '\0'; /* convert the string to an integer */ c->value = (VMVALUE)strtoul(c->token, NULL, 2); /* return the token */ return T_NUMBER; }
/* NumberToken - get a number */ static int NumberToken(ParseContext *c, int ch) { char *p = c->token; /* get the number */ *p++ = ch; while ((ch = GetChar(c)) != EOF) { if (isdigit(ch)) *p++ = ch; else if (ch != '_') break; } UngetC(c); *p = '\0'; /* convert the string to an integer */ c->value = (VMVALUE)atol(c->token); /* return the token */ return T_NUMBER; }
/* NextToken - read the next token */ static int NextToken(ParseContext *c) { int ch, tkn; /* skip leading blanks */ ch = SkipSpaces(c); /* remember the start of the current token */ c->tokenOffset = (int)(c->sys->linePtr - c->sys->lineBuf); /* check the next character */ switch (ch) { case EOF: tkn = T_EOL; break; case '"': tkn = StringToken(c); break; case '\'': tkn = CharToken(c); break; case '<': if ((ch = GetChar(c)) == '=') tkn = T_LE; else if (ch == '>') tkn = T_NE; else if (ch == '<') tkn = T_SHL; else { UngetC(c); tkn = '<'; } break; case '>': if ((ch = GetChar(c)) == '=') tkn = T_GE; else if (ch == '>') tkn = T_SHR; else { UngetC(c); tkn = '>'; } break; case '0': switch (GetChar(c)) { case 'x': case 'X': tkn = HexNumberToken(c); break; case 'b': case 'B': tkn = BinaryNumberToken(c); break; default: UngetC(c); tkn = NumberToken(c, '0'); break; } break; default: if (isdigit(ch)) tkn = NumberToken(c, ch); else if (IdentifierCharP(ch)) { char *savePtr; switch (tkn = IdentifierToken(c,ch)) { case T_ELSE: savePtr = c->sys->linePtr; if ((ch = SkipSpaces(c)) != EOF && IdentifierCharP(ch)) { switch (IdentifierToken(c, ch)) { case T_IF: tkn = T_ELSE_IF; break; default: c->sys->linePtr = savePtr; break; } } else c->sys->linePtr = savePtr; break; case T_END: savePtr = c->sys->linePtr; if ((ch = SkipSpaces(c)) != EOF && IdentifierCharP(ch)) { switch (IdentifierToken(c, ch)) { case T_DEF: tkn = T_END_DEF; break; case T_IF: tkn = T_END_IF; break; default: c->sys->linePtr = savePtr; break; } } else c->sys->linePtr = savePtr; break; case T_DO: savePtr = c->sys->linePtr; if ((ch = SkipSpaces(c)) != EOF && IdentifierCharP(ch)) { switch (IdentifierToken(c, ch)) { case T_WHILE: tkn = T_DO_WHILE; break; case T_UNTIL: tkn = T_DO_UNTIL; break; default: c->sys->linePtr = savePtr; break; } } else c->sys->linePtr = savePtr; break; case T_LOOP: savePtr = c->sys->linePtr; if ((ch = SkipSpaces(c)) != EOF && IdentifierCharP(ch)) { switch (IdentifierToken(c, ch)) { case T_WHILE: tkn = T_LOOP_WHILE; break; case T_UNTIL: tkn = T_LOOP_UNTIL; break; default: c->sys->linePtr = savePtr; break; } } else c->sys->linePtr = savePtr; break; } } else tkn = ch; } /* return the token */ return tkn; }
int Lex::SubGetToken(void) { int c, n; for(;;) { f_stoken = f_input; c = GetC(); switch(c) { case 0: return 0; case '0': c = GetC(); if(c == 'x' && c == 'X') { do { c = GetC(); } while((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); return NUMBER; } // here we could test for octal, but it doesn't // matter too much here, we're not a compiler! UngetC(); case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': do { c = GetC(); } while(c >= '0' && c <= '9'); if(c == 'U' || c == 'u') { c = GetC(); if(c == 'L' || c == 'l') { c = GetC(); if(c != 'L' && c != 'l') { UngetC(); } return NUMBER; } // a U by itself is ignored UngetC(); return NUMBER; } if(c == 'L' || c == 'l') { c = GetC(); if(c != 'L' && c != 'l') { UngetC(); } return NUMBER; } if(c == '.') { do { c = GetC(); } while(c >= '0' && c <= '9'); } if(c == 'e' || c == 'E') { c = GetC(); if(c == '-' || c == '+') { c = GetC(); } while(c >= '0' && c <= '9') { c = GetC(); } } if(c == 'f' || c == 'F') { return NUMBER; } UngetC(); return NUMBER; case '\'': character: c = GetC(); if(c == '\\') { c = GetC(); } c = GetC(); if(c != '\'') { fprintf(stderr, "%s:%ld: error: invalid character\n", f_filename, f_line); g_errcnt++; } return CHARACTER; case '"': string: do { c = GetC(); if(c == '\n' || c == '\0') { fprintf(stderr, "%s:%ld: error: unterminated string\n", f_filename, f_line); g_errcnt++; break; } if(c == '\\') { c = GetC(); if(c == '\n' || c == '\0') { fprintf(stderr, "%s:%ld: error: unterminated string\n", f_filename, f_line); g_errcnt++; break; } c = '\0'; } } while(c != '"'); return STRING; case 'l': case 'L': c = GetC(); if(c == '"') { goto string; } if(c == '\'') { goto character; } // comments are very simply ignored case '/': n = GetC(); if(n == '/') { do { c = GetC(); } while(c != '\n' && c != '\0'); break; } if(n == '*') { n = GetC(); do { c = n; n = GetC(); } while(n != '\0' && (c != '*' || n != '/')); break; } UngetC(); return c; default: if( isalpha(c) || (c=='_') || (c==':') ) { do { c = GetC(); } while((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == ':'); UngetC(); return IDENTIFIER; } else { return c; } } } }
/* ParseStatement - parse a statement */ void ParseStatement(ParseContext *c, Token tkn) { /* dispatch on the statement keyword */ switch (tkn) { case T_REM: /* just a comment so ignore the rest of the line */ break; case T_DEF: ParseDef(c); break; case T_END_DEF: ParseEndDef(c); break; case T_DIM: ParseDim(c); break; case T_LET: ParseLet(c); break; case T_IF: ParseIf(c); break; case T_ELSE: ParseElse(c); break; case T_ELSE_IF: ParseElseIf(c); break; case T_END_IF: ParseEndIf(c); break; case T_END: ParseEnd(c); break; case T_FOR: ParseFor(c); break; case T_NEXT: ParseNext(c); break; case T_DO: ParseDo(c); break; case T_DO_WHILE: ParseDoWhile(c); break; case T_DO_UNTIL: ParseDoUntil(c); break; case T_LOOP: ParseLoop(c); break; case T_LOOP_WHILE: ParseLoopWhile(c); break; case T_LOOP_UNTIL: ParseLoopUntil(c); break; case T_STOP: ParseStop(c); break; case T_GOTO: ParseGoto(c); break; case T_RETURN: ParseReturn(c); break; case T_PRINT: ParsePrint(c); break; case T_IDENTIFIER: if (SkipSpaces(c) == ':') { DefineLabel(c, c->token, codeaddr(c)); break; } UngetC(c); default: SaveToken(c, tkn); ParseImpliedLetOrFunctionCall(c); break; } }