home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / bob13st / bobscn.c < prev    next >
C/C++ Source or Header  |  1991-12-24  |  8KB  |  412 lines

  1. /* bobscn.c - a lexical scanner */
  2. /*
  3.     Copyright (c) 1991, by David Michael Betz
  4.     All rights reserved
  5. */
  6.  
  7. /*
  8.     1.3ST    12/25/91    Ported to Atari ST and Mark Williams C
  9.                         Removed ANSI void * declarations
  10. */
  11.  
  12. #include <setjmp.h>
  13. #include "bob.h"
  14.  
  15. /* useful definitions */
  16. #define LSIZE    200
  17.  
  18. /* keyword table */
  19. static struct { char *kt_keyword; int kt_token; } ktab[] = 
  20. {
  21. { "class",        T_CLASS        },
  22. { "static",        T_STATIC    },
  23. { "if",            T_IF        },
  24. { "else",        T_ELSE        },
  25. { "while",        T_WHILE        },
  26. { "return",        T_RETURN    },
  27. { "for",        T_FOR        },
  28. { "break",        T_BREAK        },
  29. { "continue",     T_CONTINUE    },
  30. { "do",            T_DO        },
  31. { "new",        T_NEW        },
  32. { "nil",        T_NIL        },
  33. { NULL,            0            }
  34. };
  35.  
  36. /* token name table */
  37. static char *t_names[] = 
  38. {
  39.     "<string>", "<identifier>", "<number>", "class", "static",
  40.     "if", "else", "while", "return", "for", "break", "continue",
  41.     "do", "new", "nil", "<=", "==", "!=", ">=", "<<", ">>", "&&",
  42.     "||", "++", "--", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=",
  43.     "<<=", ">>=", "::", "->"
  44. };
  45.  
  46. /* global variables */
  47. int t_value;            /* numeric value */
  48. char t_token[TKNSIZE+1];/* token string */
  49.  
  50. /* local variables */
  51. static int (*getcf)();    /* getc function */
  52. static char *getcd;        /* getc data */
  53. static int savetkn;        /* look ahead token */
  54. static int savech;        /* look ahead character */
  55. static int lastch;        /* last input character */
  56. static char line[LSIZE];/* last input line */
  57. static char *lptr;        /* line pointer */
  58. static int lnum;        /* line number */
  59.  
  60. /* init_scanner - initialize the scanner */
  61. init_scanner(gf,gd)
  62. int (*gf)(); 
  63. char *gd;
  64. {
  65.     getcf = gf; getcd = gd;     /* remember the getc function and data */
  66.  
  67.     lptr = line; *lptr = '\0';     /* setup the line buffer */
  68.     lnum = 0;
  69.  
  70.     savetkn = T_NOTOKEN;         /* no lookahead yet */
  71.     savech = '\0';
  72.  
  73.     lastch = '\0';                /* no last character */
  74. }
  75.  
  76. /* token - get the next token */
  77. int token()
  78. {
  79.     int tkn;
  80.  
  81.     if ((tkn = savetkn) != T_NOTOKEN)
  82.         savetkn = T_NOTOKEN;
  83.     else
  84.         tkn = rtoken();
  85.     return (tkn);
  86. }
  87.  
  88. /* stoken - save a token */
  89. stoken(tkn)
  90. int tkn;
  91. {
  92.     savetkn = tkn;
  93. }
  94.  
  95. /* tkn_name - get the name of a token */
  96. char *tkn_name(tkn)
  97. int tkn;
  98. {
  99.     static char tname[2];
  100.     
  101.     if (tkn == T_EOF)
  102.         return ("<eof>");
  103.     else 
  104.         if (tkn >= _TMIN && tkn <= _TMAX)
  105.             return (t_names[tkn-_TMIN]);
  106.     tname[0] = tkn;
  107.     tname[1] = '\0';
  108.     return (tname);
  109. }
  110.  
  111. /* rtoken - read the next token */
  112. static int rtoken()
  113. {
  114.     int ch,ch2;
  115.  
  116.     for (;;)         /* check the next character */
  117.     {
  118.         switch (ch = skipspaces()) 
  119.         {
  120.         case EOF:    
  121.             return (T_EOF);
  122.         case '"':    
  123.             return (getstring());
  124.         case '\'':    
  125.             return (getcharacter());
  126.         case '<':    
  127.             switch (ch = getch()) 
  128.             {
  129.             case '=':
  130.                 return (T_LE);
  131.             case '<':
  132.                 if ((ch = getch()) == '=')
  133.                     return (T_SHLEQ);
  134.                 savech = ch;
  135.                 return (T_SHL);
  136.             default:
  137.                 savech = ch;
  138.                 return ('<');
  139.             }
  140.         case '=':    
  141.             if ((ch = getch()) == '=')
  142.                 return (T_EQ);
  143.             savech = ch;
  144.             return ('=');
  145.         case '!':    
  146.             if ((ch = getch()) == '=')
  147.                 return (T_NE);
  148.             savech = ch;
  149.             return ('!');
  150.         case '>':    
  151.             switch (ch = getch()) 
  152.             {
  153.             case '=':
  154.                 return (T_GE);
  155.             case '>':
  156.                 if ((ch = getch()) == '=')
  157.                     return (T_SHREQ);
  158.                 savech = ch;
  159.                 return (T_SHR);
  160.             default:
  161.                 savech = ch;
  162.                 return ('>');
  163.             }
  164.         case '&':    
  165.             switch (ch = getch()) 
  166.             {
  167.             case '&':
  168.                 return (T_AND);
  169.             case '=':
  170.                 return (T_ANDEQ);
  171.             default:
  172.                 savech = ch;
  173.                 return ('&');
  174.             }
  175.         case '|':    
  176.             switch (ch = getch()) 
  177.             {
  178.             case '|':
  179.                 return (T_AND);
  180.             case '=':
  181.                 return (T_OREQ);
  182.             default:
  183.                 savech = ch;
  184.                 return ('|');
  185.             }
  186.         case '^':    
  187.             if ((ch = getch()) == '=')
  188.                 return (T_XOREQ);
  189.             savech = ch;
  190.             return ('^');
  191.         case '+':    
  192.             switch (ch = getch()) 
  193.             {
  194.             case '+':
  195.                 return (T_INC);
  196.             case '=':
  197.                 return (T_ADDEQ);
  198.             default:
  199.                 savech = ch;
  200.                 return ('+');
  201.             }
  202.         case '-':    
  203.             switch (ch = getch()) 
  204.             {
  205.             case '-':
  206.                 return (T_DEC);
  207.             case '=':
  208.                 return (T_SUBEQ);
  209.             case '>':
  210.                 return (T_MEMREF);
  211.             default:
  212.                 savech = ch;
  213.                 return ('-');
  214.             }
  215.         case '*':    
  216.             if ((ch = getch()) == '=')
  217.                 return (T_MULEQ);
  218.             savech = ch;
  219.             return ('*');
  220.         case '/':    
  221.             switch (ch = getch()) 
  222.             {
  223.             case '=':
  224.                 return (T_DIVEQ);
  225.             case '/':
  226.                 while ((ch = getch()) != EOF)
  227.                     if (ch == '\n')
  228.                         break;
  229.                 break;
  230.             case '*':
  231.                 ch = ch2 = EOF;
  232.                 for (; (ch2 = getch()) != EOF; ch = ch2)
  233.                     if (ch == '*' && ch2 == '/')
  234.                         break;
  235.                 break;
  236.             default:
  237.                 savech = ch;
  238.                 return ('/');
  239.             }
  240.             break;
  241.         case ':':    
  242.             if ((ch = getch()) == ':')
  243.                 return (T_CC);
  244.             savech = ch;
  245.             return (':');
  246.         default:    
  247.             if (isdigit(ch))
  248.                 return (getnumber(ch));
  249.             else 
  250.                 if (isidchar(ch))
  251.                     return (getid(ch));
  252.                 else 
  253.                 {
  254.                     t_token[0] = ch;
  255.                     t_token[1] = '\0';
  256.                     return (ch);
  257.                 }
  258.         }
  259.     }
  260. }
  261.  
  262. /* getstring - get a string */
  263. static int getstring()
  264. {
  265.     char *p;
  266.     int ch;
  267.  
  268.     p = t_token;             /* get the string */
  269.     while ((ch = literalch()) != EOF && ch != '"')
  270.         *p++ = ch;
  271.     if (ch == EOF)
  272.         savech = EOF;
  273.     *p = '\0';
  274.     return (T_STRING);
  275. }
  276.  
  277. /* getcharacter - get a character constant */
  278. static int getcharacter()
  279. {
  280.     t_value = literalch();
  281.     t_token[0] = t_value;
  282.     t_token[1] = '\0';
  283.     if (getch() != '\'')
  284.         parse_error("Expecting a closing single quote");
  285.     return (T_NUMBER);
  286. }
  287.  
  288. /* literalch - get a character from a literal string */
  289. static int literalch()
  290. {
  291.     int ch;
  292.     
  293.     if ((ch = getch()) == '\\')
  294.     {
  295.         switch (ch = getch()) 
  296.         {
  297.         case 'n':  
  298.             ch = '\n'; 
  299.             break;
  300.         case 't':  
  301.             ch = '\t'; 
  302.             break;
  303.         case EOF:  
  304.             ch = '\\'; 
  305.             savech = EOF; 
  306.             break;
  307.         }
  308.     }
  309.     return (ch);
  310. }
  311.  
  312. /* getid - get an identifier */
  313. static int getid(ch)
  314. int ch;
  315. {
  316.     char *p;
  317.     int i;
  318.  
  319.     p = t_token;              /* get the identifier */
  320.     *p++ = ch;
  321.     while ((ch = getch()) != EOF && isidchar(ch))
  322.         *p++ = ch;
  323.     savech = ch;
  324.     *p = '\0';
  325.  
  326.     for (i = 0; ktab[i].kt_keyword != NULL; ++i) /* check to see if it is a keyword */
  327.         if (strcmp(ktab[i].kt_keyword,t_token) == 0)
  328.             return (ktab[i].kt_token);
  329.     return (T_IDENTIFIER);
  330. }
  331.  
  332. /* getnumber - get a number */
  333. static int getnumber(ch)
  334. int ch;
  335. {
  336.     char *p;
  337.  
  338.     p = t_token;                  /* get the number */
  339.     *p++ = ch; 
  340.     t_value = ch - '0';
  341.     while ((ch = getch()) != EOF && isdigit(ch)) 
  342.     {
  343.         t_value = t_value * 10 + ch - '0';
  344.         *p++ = ch;
  345.     }
  346.     savech = ch;
  347.     *p = '\0';
  348.     return (T_NUMBER);
  349. }
  350.  
  351. /* skipspaces - skip leading spaces */
  352. static skipspaces()
  353. {
  354.     int ch;
  355.     
  356.     while ((ch = getch()) != '\0' && isspace(ch))
  357.         ;
  358.     return (ch);
  359. }
  360.  
  361. /* isidchar - is this an identifier character */
  362. static int isidchar(ch)
  363. int ch;
  364. {
  365.     return (isupper(ch) || islower(ch) || isdigit(ch) || ch == '_');
  366. }
  367.  
  368. /* getch - get the next character */
  369. static int getch()
  370. {
  371.     int ch;
  372.     
  373.     if ((ch = savech) != '\0')     /* check for a lookahead character */
  374.         savech = '\0';
  375.     else                          /* check for a buffered character */
  376.     {
  377.         while ((ch = *lptr++) == '\0') 
  378.         {
  379.  
  380.             if (lastch == EOF)         /* check for being at the end of file */
  381.                 return (EOF);
  382.  
  383.             lptr = line;             /* read the next line */
  384.             while ((lastch = (*getcf)(getcd)) != EOF && lastch != '\n')
  385.                 *lptr++ = lastch;
  386.             *lptr++ = '\n'; *lptr = '\0';
  387.             lptr = line;
  388.             ++lnum;
  389.         }
  390.     }
  391.  
  392.     return (ch);                     /* return the current character */
  393. }
  394.  
  395. /* parse_error - report an error in the current line */
  396. parse_error(msg)
  397. char *msg;
  398. {
  399.     extern jmp_buf error_trap;
  400.     char buf[LSIZE],*src,*dst;
  401.  
  402.     sprintf(buf,">>> %s <<<\n>>> in line %d <<<\n%s",msg,lnum,line); /* redisplay the line with the error */
  403.     osputs(buf);
  404.  
  405.     for (src = line, dst = buf; src < lptr-1; ++src) /* point to the position immediately following the error */
  406.         *dst++ = (*src == '\t' ? '\t' : ' ');
  407.     *dst++ = '^'; *dst++ = '\n'; *dst = '\0';
  408.     osputs(buf);
  409.  
  410.     longjmp(error_trap,1);                             /* invoke the error trap */
  411. }
  412.