home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / smalltk / src / lex.c < prev    next >
C/C++ Source or Header  |  1991-10-12  |  6KB  |  255 lines

  1. /*
  2.     Little Smalltalk, version 2
  3.     Written by Tim Budd, Oregon State University, July 1987
  4.  
  5.     lexical analysis routines for method parser
  6.     should be called only by parser 
  7. */
  8.  
  9. # include <stdio.h>
  10. # include <ctype.h>
  11. # ifdef LIGHTC
  12. # include <unix.h>
  13. # include <proto.h>
  14. # endif
  15. # include "env.h"
  16. # include "memory.h"
  17. # include "lex.h"
  18.  
  19. extern double atof();
  20.  
  21. /* global variables returned by lexical analyser */
  22.  
  23. tokentype token;        /* token variety */
  24. char tokenString[80];        /* text of current token */
  25. int tokenInteger;        /* integer (or character) value of token */
  26. double tokenFloat;        /* floating point value of token */
  27.  
  28. /* local variables used only by lexical analyser */
  29.  
  30. static char *cp;        /* character pointer */
  31. static char pushBuffer[10];    /* pushed back buffer */
  32. static int  pushindex;        /* index of last pushed back char */
  33. static char cc;            /* current character */
  34. static long longresult;        /* value used when building int tokens */
  35.  
  36. /* lexinit - initialize the lexical analysis routines */
  37. noreturn lexinit(str)
  38. char *str;
  39. {
  40.     pushindex = 0;
  41.     cp = str;
  42.     /* get first token */
  43.     ignore nextToken();
  44. }
  45.  
  46. /* pushBack - push one character back into the input */
  47. static pushBack(c)
  48. char c;
  49. {
  50.     pushBuffer[pushindex++] = c;
  51. }
  52.  
  53. /* nextChar - retrieve the next char, from buffer or input */
  54. static char nextChar()
  55. {
  56.     if (pushindex > 0) cc = pushBuffer[--pushindex];
  57.     else if (*cp) cc = *cp++;
  58.     else cc = '\0';
  59.     return(cc);
  60. }
  61.  
  62. /* peek - take a peek at the next character */
  63. char peek()
  64. {
  65.     pushBack(nextChar());
  66.     return (cc);
  67. }
  68.  
  69. /* isClosing - characters which can close an expression */
  70. static boolean isClosing(c)
  71. char c;
  72. {
  73.     switch(c) {
  74.         case '.': case ']': case ')': case ';':
  75.         case '\"': case '\'':
  76.             return(true);
  77.     }
  78.     return(false);
  79. }
  80.  
  81. /* isSymbolChar - characters which can be part of symbols */
  82. static boolean isSymbolChar(c)
  83. char c;
  84. {
  85.     if (isdigit(c) || isalpha(c)) return(true);
  86.     if (isspace(c) || isClosing(c)) return(false);
  87.     return(true);
  88. }
  89.  
  90. /* singleBinary - binary characters that cannot be continued */
  91. static boolean singleBinary(c)
  92. char c;
  93. {
  94.     switch(c) {
  95.         case '[': case '(': case ')': case ']':
  96.             return(true);
  97.     }
  98.     return(false);
  99. }
  100.  
  101. /* binarySecond - return true if char can be second char in binary symbol */
  102. static boolean binarySecond(c)
  103. char c;
  104. {
  105.     if (isalpha(c) || isdigit(c) || isspace(c) || isClosing(c) ||
  106.         singleBinary(c))
  107.         return(false);
  108.     return(true);
  109. }
  110.  
  111. tokentype nextToken()
  112. {    char *tp;
  113.     boolean sign;
  114.  
  115.     /* skip over blanks and comments */
  116.     while(nextChar() && (isspace(cc) || (cc == '"')))
  117.         if (cc == '"') {
  118.             /* read comment */
  119.             while (nextChar() && (cc != '"')) ;
  120.             if (! cc) break;    /* break if we run into eof */
  121.             }
  122.  
  123.     tp = tokenString;
  124.     *tp++ = cc;
  125.  
  126.     if (! cc)            /* end of input */
  127.         token = inputend;
  128.     
  129.     else if (isalpha(cc)) {        /* identifier */
  130.         while (nextChar() && isalnum(cc))
  131.             *tp++ = cc;
  132.         if (cc == ':') {
  133.             *tp++ = cc;
  134.             token = namecolon;
  135.             }
  136.         else {
  137.             pushBack(cc);
  138.             token = nameconst;
  139.             }
  140.         }
  141.  
  142.     else if (isdigit(cc)) {        /* number */
  143.         longresult = cc - '0';
  144.         while (nextChar() && isdigit(cc)) {
  145.             *tp++ = cc;
  146.             longresult = (longresult * 10) + (cc - '0');
  147.             }
  148.         if (longCanBeInt(longresult)) {
  149.             tokenInteger = longresult;
  150.             token = intconst;
  151.             }
  152.         else {
  153.             token = floatconst;
  154.             tokenFloat = (double) longresult;
  155.             }
  156.         if (cc == '.') {    /* possible float */
  157.             if (nextChar() && isdigit(cc)) {
  158.                 *tp++ = '.';
  159.                 do
  160.                     *tp++ = cc;
  161.                 while (nextChar() && isdigit(cc));
  162.                 if (cc) pushBack(cc);
  163.                 token = floatconst;
  164.                 *tp = '\0';
  165.                 tokenFloat = atof(tokenString);
  166.                 }
  167.             else {
  168.                 /* nope, just an ordinary period */
  169.                 if (cc) pushBack(cc);
  170.                 pushBack('.');
  171.                 }
  172.             }
  173.         else
  174.             pushBack(cc);
  175.  
  176.         if (nextChar() && cc == 'e') {    /* possible float */
  177.             if (nextChar() && cc == '-') {
  178.                 sign = true;
  179.                 ignore nextChar();
  180.                 }
  181.             else
  182.                 sign = false;
  183.             if (cc && isdigit(cc)) { /* yep, its a float */
  184.                 *tp++ = 'e';
  185.                 if (sign) *tp++ = '-';
  186.                 while (cc && isdigit(cc)) {
  187.                     *tp++ = cc;
  188.                     ignore nextChar();
  189.                     }
  190.                 if (cc) pushBack(cc);
  191.                 *tp = '\0';
  192.                 token = floatconst;
  193.                 tokenFloat = atof(tokenString);
  194.                 }
  195.             else {    /* nope, wrong again */
  196.                 if (cc) pushBack(cc);
  197.                 if (sign) pushBack('-');
  198.                 pushBack('e');
  199.                 }
  200.             }
  201.             else
  202.                 if (cc) pushBack(cc);
  203.         }
  204.  
  205.     else if (cc == '$') {        /* character constant */
  206.         tokenInteger = (int) nextChar();
  207.         token = charconst;
  208.         }
  209.  
  210.     else if (cc == '#') {        /* symbol */
  211.         tp--;    /* erase pound sign */
  212.         if (nextChar() == '(')
  213.             token = arraybegin;
  214.         else {
  215.             pushBack(cc);
  216.             while (nextChar() && isSymbolChar(cc))
  217.                 *tp++ = cc;
  218.             pushBack(cc);
  219.             token = symconst;
  220.             }
  221.         }
  222.  
  223.     else if (cc == '\'') {        /* string constant */
  224.         tp--;    /* erase pound sign */
  225.         strloop:
  226.         while (nextChar() && (cc != '\''))
  227.             *tp++ = cc;
  228.         /* check for nested quote marks */
  229.         if (cc && nextChar() && (cc == '\'')) {
  230.             *tp++ = cc;
  231.             goto strloop;
  232.             }
  233.         pushBack(cc);
  234.         token = strconst;
  235.         }
  236.  
  237.     else if (isClosing(cc))        /* closing expressions */
  238.         token = closing;
  239.  
  240.     else if (singleBinary(cc)) {    /* single binary expressions */
  241.         token = binary;
  242.         }
  243.  
  244.     else {                /* anything else is binary */
  245.         if (nextChar() && binarySecond(cc))
  246.             *tp++ = cc;
  247.         else
  248.             pushBack(cc);
  249.         token = binary;
  250.         }
  251.  
  252.     *tp = '\0';
  253.     return(token);
  254. }
  255.