/* Little Smalltalk, version 2 Written by Tim Budd, Oregon State University, July 1987 lexical analysis routines for method parser should be called only by parser */ # include # include # include "env.h" # include "memory.h" # include "lex.h" extern double atof(); /* global variables returned by lexical analyser */ tokentype token; /* token variety */ char tokenString[80]; /* text of current token */ int tokenInteger; /* integer (or character) value of token */ double tokenFloat; /* floating point value of token */ /* local variables used only by lexical analyser */ static char *cp; /* character pointer */ static char pushBuffer[10]; /* pushed back buffer */ static int pushindex; /* index of last pushed back char */ static char cc; /* current character */ static long longresult; /* value used when building int tokens */ /* lexinit - initialize the lexical analysis routines */ noreturn lexinit(str) char *str; { pushindex = 0; cp = str; /* get first token */ ignore nextToken(); } /* pushBack - push one character back into the input */ static pushBack(c) char c; { pushBuffer[pushindex++] = c; } /* nextChar - retrieve the next char, from buffer or input */ static char nextChar() { if (pushindex > 0) cc = pushBuffer[--pushindex]; else if (*cp) cc = *cp++; else cc = '\0'; return(cc); } /* isClosing - characters which can close an expression */ static boolean isClosing(c) char c; { switch(c) { case '.': case ']': case ')': case ';': return(true); } return(false); } /* isSymbolChar - characters which can be part of symbols */ static boolean isSymbolChar(c) char c; { if (isdigit(c) || isalpha(c)) return(true); if (isspace(c) || isClosing(c)) return(false); return(true); } /* singleBinary - binary characters that cannot be continued */ static boolean singleBinary(c) char c; { switch(c) { case '[': case '(': case ')': case ']': return(true); } return(false); } /* binarySecond - return true if char can be second char in binary symbol */ static boolean binarySecond(c) char c; { if (isalpha(c) || isdigit(c) || isspace(c) || isClosing(c) || singleBinary(c)) return(false); return(true); } tokentype nextToken() { char *tp; boolean sign; /* skip over blanks and comments */ while(nextChar() && (isspace(cc) || (cc == '"'))) if (cc == '"') { /* read comment */ while (nextChar() && (cc != '"')) ; if (! cc) break; /* break if we run into eof */ } tp = tokenString; *tp++ = cc; if (! cc) /* end of input */ token = inputend; else if (isalpha(cc)) { /* identifier */ while (nextChar() && isalnum(cc)) *tp++ = cc; if (cc == ':') { *tp++ = cc; token = namecolon; } else { pushBack(cc); token = nameconst; } } else if (isdigit(cc)) { /* number */ longresult = cc - '0'; while (nextChar() && isdigit(cc)) { *tp++ = cc; longresult = (longresult * 10) + (cc - '0'); } if (longCanBeInt(longresult)) { tokenInteger = longresult; token = intconst; } else { token = floatconst; tokenFloat = (double) longresult; } if (cc == '.') { /* possible float */ if (nextChar() && isdigit(cc)) { *tp++ = '.'; do *tp++ = cc; while (nextChar() && isdigit(cc)); if (cc) pushBack(cc); token = floatconst; *tp = '\0'; tokenFloat = atof(tokenString); } else { /* nope, just an ordinary period */ if (cc) pushBack(cc); pushBack('.'); } } else pushBack(cc); if (nextChar() && cc == 'e') { /* possible float */ if (nextChar() && cc == '-') { sign = true; ignore nextChar(); } else sign = false; if (cc && isdigit(cc)) { /* yep, its a float */ *tp++ = 'e'; if (sign) *tp++ = '-'; while (cc && isdigit(cc)) { *tp++ = cc; ignore nextChar(); } if (cc) pushBack(cc); *tp = '\0'; token = floatconst; tokenFloat = atof(tokenString); } else { /* nope, wrong again */ if (cc) pushBack(cc); if (sign) pushBack('-'); pushBack('e'); } } else if (cc) pushBack(cc); } else if (cc == '$') { /* character constant */ tokenInteger = (int) nextChar(); token = charconst; } else if (cc == '#') { /* symbol */ tp--; /* erase pound sign */ if (nextChar() == '(') token = arraybegin; else { pushBack(cc); while (nextChar() && isSymbolChar(cc)) *tp++ = cc; pushBack(cc); token = symconst; } } else if (cc == '\'') { /* string constant */ tp--; /* erase pound sign */ strloop: while (nextChar() && (cc != '\'')) *tp++ = cc; /* check for nested quote marks */ if (cc && nextChar() && (cc == '\'')) { *tp++ = cc; goto strloop; } pushBack(cc); token = strconst; } else if (isClosing(cc)) /* closing expressions */ token = closing; else if (singleBinary(cc)) { /* single binary expressions */ token = binary; } else { /* anything else is binary */ if (nextChar() && binarySecond(cc)) *tp++ = cc; else pushBack(cc); token = binary; } *tp = '\0'; return(token); } w, floatValue(newobj), f); decr(newobj);