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