home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / src / rtt / rttlex.c < prev    next >
C/C++ Source or Header  |  2002-01-18  |  14KB  |  362 lines

  1. /*
  2.  * This lexical analyzer uses the preprocessor to convert text into tokens.
  3.  *  The lexical anayser discards white space, checks to see if identifiers
  4.  *  are reserved words or typedef names, makes sure single characters
  5.  *  are valid tokens, and converts preprocessor constants into the
  6.  *  various C constants.
  7.  */
  8. #include "rtt.h"
  9.  
  10. /*
  11.  * Prototype for static function.
  12.  */
  13. static int int_suffix (char *s);
  14.  
  15. int lex_state = DfltLex;
  16.  
  17. char *ident = "ident";
  18.  
  19. /*
  20.  * Characters are used as token id's for single character tokens. The
  21.  *  following table indicates which ones can be valid for RTL.
  22.  */
  23.  
  24. #define GoodChar(c) ((c) < 127 && good_char[c])
  25. static int good_char[128] = {
  26.    0  /* \000 */,   0  /* \001 */,   0  /* \002 */,   0  /* \003 */,
  27.    0  /* \004 */,   0  /* \005 */,   0  /* \006 */,   0  /* \007 */,
  28.    0  /*  \b  */,   0  /*  \t  */,   0  /*  \n  */,   0  /*  \v  */,
  29.    0  /*  \f  */,   0  /*  \r  */,   0  /* \016 */,   0  /* \017 */,
  30.    0  /* \020 */,   0  /* \021 */,   0  /* \022 */,   0  /* \023 */,
  31.    0  /* \024 */,   0  /* \025 */,   0  /* \026 */,   0  /* \027 */,
  32.    0  /* \030 */,   0  /* \031 */,   0  /* \032 */,   0  /*  \e  */,
  33.    0  /* \034 */,   0  /* \035 */,   0  /* \036 */,   0  /* \037 */,
  34.    0  /*      */,   1  /*  !   */,   0  /*  \   */,   0  /*  #   */,
  35.    0  /*  $   */,   1  /*  %   */,   1  /*  &   */,   0  /*  '   */,
  36.    1  /*  (   */,   1  /*  )   */,   1  /*  *   */,   1  /*  +   */,
  37.    1  /*  ,   */,   1  /*  -   */,   1  /*  .   */,   1  /*  /   */,
  38.    0  /*  0   */,   0  /*  1   */,   0  /*  2   */,   0  /*  3   */,
  39.    0  /*  4   */,   0  /*  5   */,   0  /*  6   */,   0  /*  7   */,
  40.    0  /*  8   */,   0  /*  9   */,   1  /*  :   */,   1  /*  ;   */,
  41.    1  /*  <   */,   1  /*  =   */,   1  /*  >   */,   1  /*  ?   */,
  42.    0  /*  @   */,   0  /*  A   */,   0  /*  B   */,   0  /*  C   */,
  43.    0  /*  D   */,   0  /*  E   */,   0  /*  F   */,   0  /*  G   */,
  44.    0  /*  H   */,   0  /*  I   */,   0  /*  J   */,   0  /*  K   */,
  45.    0  /*  L   */,   0  /*  M   */,   0  /*  N   */,   0  /*  O   */,
  46.    0  /*  P   */,   0  /*  Q   */,   0  /*  R   */,   0  /*  S   */,
  47.    0  /*  T   */,   0  /*  U   */,   0  /*  V   */,   0  /*  W   */,
  48.    0  /*  X   */,   0  /*  Y   */,   0  /*  Z   */,   1  /*  [   */,
  49.    1  /*  \\  */,   1  /*  ]   */,   1  /*  ^   */,   0  /*  _   */,
  50.    0  /*  `   */,   0  /*  a   */,   0  /*  b   */,   0  /*  c   */,
  51.    0  /*  d   */,   0  /*  e   */,   0  /*  f   */,   0  /*  g   */,
  52.    0  /*  h   */,   0  /*  i   */,   0  /*  j   */,   0  /*  k   */,
  53.    0  /*  l   */,   0  /*  m   */,   0  /*  n   */,   0  /*  o   */,
  54.    0  /*  p   */,   0  /*  q   */,   0  /*  r   */,   0  /*  s   */,
  55.    0  /*  t   */,   0  /*  u   */,   0  /*  v   */,   0  /*  w   */,
  56.    0  /*  x   */,   0  /*  y   */,   0  /*  z   */,   1  /*  {   */,
  57.    1  /*  |   */,   1  /*  }   */,   1  /*  ~   */,   0  /*  \d  */
  58.    };
  59.  
  60. /*
  61.  * init_lex - initialize lexical analyzer.
  62.  */
  63. void init_lex()
  64.    {
  65.    struct sym_entry *sym;
  66.    int i;
  67.    static int first_time = 1;
  68.  
  69.    if (first_time) {
  70.       first_time = 0;
  71.       ident = spec_str(ident);  /* install ident in string table */
  72.       /*
  73.        * install C keywords into the symbol table
  74.        */
  75.       sym_add(Auto,          spec_str("auto"),          OtherDcl, 0);
  76.       sym_add(Break,         spec_str("break"),         OtherDcl, 0);
  77.       sym_add(Case,          spec_str("case"),          OtherDcl, 0);
  78.       sym_add(TokChar,       spec_str("char"),          OtherDcl, 0);
  79.       sym_add(Const,         spec_str("const"),         OtherDcl, 0);
  80.       sym_add(Continue,      spec_str("continue"),      OtherDcl, 0);
  81.       sym_add(Default,       spec_str("default"),       OtherDcl, 0);
  82.       sym_add(Do,            spec_str("do"),            OtherDcl, 0);
  83.       sym_add(Doubl,         spec_str("double"),        OtherDcl, 0);
  84.       sym_add(Else,          spec_str("else"),          OtherDcl, 0);
  85.       sym_add(TokEnum,       spec_str("enum"),          OtherDcl, 0);
  86.       sym_add(Extern,        spec_str("extern"),        OtherDcl, 0);
  87.       sym_add(Float,         spec_str("float"),         OtherDcl, 0);
  88.       sym_add(For,           spec_str("for"),           OtherDcl, 0);
  89.       sym_add(Goto,          spec_str("goto"),          OtherDcl, 0);
  90.       sym_add(If,            spec_str("if"),            OtherDcl, 0);
  91.       sym_add(Int,           spec_str("int"),           OtherDcl, 0);
  92.       sym_add(TokLong,       spec_str("long"),          OtherDcl, 0);
  93.       sym_add(TokRegister,   spec_str("register"),      OtherDcl, 0);
  94.       sym_add(Return,        spec_str("return"),        OtherDcl, 0);
  95.       sym_add(TokShort,      spec_str("short"),         OtherDcl, 0);
  96.       sym_add(Signed,        spec_str("signed"),        OtherDcl, 0);
  97.       sym_add(Sizeof,        spec_str("sizeof"),        OtherDcl, 0);
  98.       sym_add(Static,        spec_str("static"),        OtherDcl, 0);
  99.       sym_add(Struct,        spec_str("struct"),        OtherDcl, 0);
  100.       sym_add(Switch,        spec_str("switch"),        OtherDcl, 0);
  101.       sym_add(Typedef,       spec_str("typedef"),       OtherDcl, 0);
  102.       sym_add(Union,         spec_str("union"),         OtherDcl, 0);
  103.       sym_add(Unsigned,      spec_str("unsigned"),      OtherDcl, 0);
  104.       sym_add(Void,          spec_str("void"),          OtherDcl, 0);
  105.       sym_add(Volatile,      spec_str("volatile"),      OtherDcl, 0);
  106.       sym_add(While,         spec_str("while"),         OtherDcl, 0);
  107.  
  108.       /*
  109.        * Install keywords from run-time interface language.
  110.        */
  111.       sym_add(Abstract,      spec_str("abstract"),      OtherDcl, 0);
  112.       sym_add(All_fields,    spec_str("all_fields"),    OtherDcl, 0);
  113.       sym_add(Any_value,     spec_str("any_value"),     OtherDcl, 0);
  114.       sym_add(Arith_case,    spec_str("arith_case"),    OtherDcl, 0);
  115.       sym_add(Body,          spec_str("body"),          OtherDcl, 0);
  116.       sym_add(C_Double,      spec_str("C_double"),      OtherDcl, 0);
  117.       sym_add(C_Integer,     spec_str("C_integer"),     OtherDcl, 0);
  118.       sym_add(C_String,      spec_str("C_string"),      OtherDcl, 0);
  119.       sym_add(Cnv,           spec_str("cnv"),           OtherDcl, 0);
  120.       sym_add(Constant,      spec_str("constant"),      OtherDcl, 0);
  121.       sym_add(Declare,       spec_str("declare"),       OtherDcl, 0);
  122.       sym_add(Def,           spec_str("def"),           OtherDcl, 0);
  123.       sym_add(Empty_type,    spec_str("empty_type"),    OtherDcl, 0);
  124.       sym_add(End,           spec_str("end"),           OtherDcl, 0);
  125.       sym_add(Errorfail,     spec_str("errorfail"),     OtherDcl, 0);
  126.       sym_add(Exact,         spec_str("exact"),         OtherDcl, 0);
  127.       sym_add(Fail,          spec_str("fail"),          OtherDcl, 0);
  128.       sym_add(TokFunction,   spec_str("function"),      OtherDcl, 0);
  129.       sym_add(Inline,        spec_str("inline"),        OtherDcl, 0);
  130.       sym_add(Is,            spec_str("is"),            OtherDcl, 0);
  131.       sym_add(Keyword,       spec_str("keyword"),       OtherDcl, 0);
  132.       sym_add(Len_case,      spec_str("len_case"),      OtherDcl, 0);
  133.       sym_add(Named_var,     spec_str("named_var"),     OtherDcl, 0);
  134.       sym_add(New,           spec_str("new"),           OtherDcl, 0);
  135.       sym_add(Of,            spec_str("of"),            OtherDcl, 0);
  136.       sym_add(Operator,      spec_str("operator"),      OtherDcl, 0);
  137.       str_rslt = spec_str("result");
  138.       sym_add(Runerr,        spec_str("runerr"),        OtherDcl, 0);
  139.       sym_add(Store,         spec_str("store"),         OtherDcl, 0);
  140.       sym_add(Struct_var,    spec_str("struct_var"),    OtherDcl, 0);
  141.       sym_add(Suspend,       spec_str("suspend"),       OtherDcl, 0);
  142.       sym_add(Tended,        spec_str("tended"),        OtherDcl, 0);
  143.       sym_add(Then,          spec_str("then"),          OtherDcl, 0);
  144.       sym_add(Tmp_cset,      spec_str("tmp_cset"),      OtherDcl, 0);
  145.       sym_add(Tmp_string,    spec_str("tmp_string"),    OtherDcl, 0);
  146.       sym_add(TokType,       spec_str("type"),          OtherDcl, 0);
  147.       sym_add(Type_case,     spec_str("type_case"),     OtherDcl, 0);
  148.       sym_add(Underef,       spec_str("underef"),       OtherDcl, 0);
  149.       sym_add(Variable,      spec_str("variable"),      OtherDcl, 0);
  150.  
  151.       for (i = 0; i < num_typs; ++i) {
  152.          icontypes[i].id = spec_str(icontypes[i].id);
  153.          sym = sym_add(IconType, icontypes[i].id, OtherDcl, 0);
  154.          sym->u.typ_indx = i;
  155.          }
  156.  
  157.       for (i = 0; i < num_cmpnts; ++i) {
  158.          typecompnt[i].id = spec_str(typecompnt[i].id);
  159.          sym = sym_add(Component, typecompnt[i].id, OtherDcl, 0);
  160.          sym->u.typ_indx = i;
  161.          }
  162.       }
  163.    }
  164.  
  165. /*
  166.  * int_suffix - we have reached the end of what seems to be an integer
  167.  *  constant. check for a valid suffix.
  168.  */
  169. static int int_suffix(s)
  170. char *s;
  171.    {
  172.    int tok_id;
  173.  
  174.    if (*s == 'u' || *s == 'U') {
  175.       ++s;
  176.       if (*s == 'l' || *s == 'L') {
  177.          ++s;
  178.          tok_id = ULIntConst;  /* unsigned long */
  179.          }
  180.       else
  181.          tok_id  = UIntConst;  /* unsigned */
  182.       }
  183.    else if (*s == 'l' || *s == 'L') {
  184.       ++s;
  185.       if (*s == 'u' || *s == 'U') {
  186.          ++s;
  187.          tok_id = ULIntConst;  /* unsigned long */
  188.          }
  189.       else
  190.          tok_id = LIntConst;   /* long */
  191.       }
  192.    else
  193.       tok_id = IntConst;       /* plain int */
  194.    if (*s != '\0')
  195.       errt2(yylval.t, "invalid integer constant: ", yylval.t->image);
  196.    return tok_id;
  197.    }
  198.  
  199. /*
  200.  * yylex - lexical analyzer, called by yacc-generated parser.
  201.  */
  202. int yylex()
  203.    {
  204.    register char *s;
  205.    struct sym_entry *sym;
  206.    struct token *lk_ahead = NULL;
  207.    int is_float;
  208.    struct str_buf *sbuf;
  209.  
  210.    /*
  211.     * See if the last call to yylex() left a token from looking ahead.
  212.     */
  213.    if (lk_ahead == NULL)
  214.       yylval.t = preproc();
  215.    else {
  216.       yylval.t = lk_ahead;
  217.       lk_ahead = NULL;
  218.       }
  219.  
  220.    /*
  221.     * Skip white space, then check for end-of-input.
  222.     */
  223.    while (yylval.t != NULL && yylval.t->tok_id == WhiteSpace) {
  224.       free_t(yylval.t);
  225.       yylval.t = preproc();
  226.       }
  227.    if (yylval.t == NULL)
  228.       return 0;
  229.  
  230.    /*
  231.     * The rtt recognizes ** as an operator in abstract type computations.
  232.     *  The parsing context is indicated by lex_state.
  233.     */
  234.    if (lex_state == TypeComp && yylval.t->tok_id == '*') {
  235.       lk_ahead = preproc();
  236.       if (lk_ahead != NULL && lk_ahead->tok_id == '*') {
  237.          free_t(lk_ahead);
  238.          lk_ahead = NULL;
  239.          yylval.t->tok_id = Intersect;
  240.          yylval.t->image = spec_str("**");
  241.          }
  242.       }
  243.  
  244.    /*
  245.     * Some tokens are passed along without change, but some need special
  246.     *  processing: identifiers, numbers, PpKeep tokens, and single
  247.     *  character tokens.
  248.     */
  249.    if (yylval.t->tok_id == Identifier) {
  250.       /*
  251.        * See if this is an identifier, a reserved word, or typedef name.
  252.        */
  253.       sym = sym_lkup(yylval.t->image);
  254.       if (sym != NULL)
  255.          yylval.t->tok_id = sym->tok_id;
  256.       }
  257.    else if (yylval.t->tok_id == PpNumber) {
  258.       /*
  259.        * Determine what kind of numeric constant this is.
  260.        */
  261.       s = yylval.t->image;
  262.       if (*s == '0' && (*++s == 'x' || *s == 'X')) {
  263.          /*
  264.           * Hex integer constant.
  265.           */
  266.          ++s;
  267.          while (isxdigit(*s))
  268.             ++s;
  269.          yylval.t->tok_id = int_suffix(s);
  270.          }
  271.       else {
  272.          is_float = 0;
  273.          while (isdigit(*s))
  274.              ++s;
  275.          if (*s == '.') {
  276.             is_float = 1;
  277.             ++s;
  278.             while (isdigit(*s))
  279.                ++s;
  280.             }
  281.          if (*s == 'e' || *s == 'E') {
  282.             is_float = 1;
  283.             ++s;
  284.             if (*s == '+' || *s == '-')
  285.                ++s;
  286.             while (isdigit(*s))
  287.                ++s;
  288.             }
  289.          if (is_float) {
  290.             switch (*s) {
  291.                case '\0':
  292.                   yylval.t->tok_id = DblConst;   /* double */
  293.                   break;
  294.                case 'f': case 'F':
  295.                    yylval.t->tok_id = FltConst;  /* float */
  296.                    break;
  297.                case 'l': case 'L':
  298.                    yylval.t->tok_id = LDblConst; /* long double */
  299.                    break;
  300.                default:
  301.                    errt2(yylval.t, "invalid float constant: ", yylval.t->image);
  302.                }
  303.             }
  304.          else {
  305.             /*
  306.              * This appears to be an integer constant. If it starts
  307.              *  with '0', it should be an octal constant.
  308.              */
  309.             if (yylval.t->image[0] == '0') {
  310.                s = yylval.t->image;
  311.                while (*s >= '0' && *s <= '7')
  312.                   ++s;
  313.                }
  314.             yylval.t->tok_id = int_suffix(s);
  315.             }
  316.          }
  317.       }
  318.    else if (yylval.t->tok_id == PpKeep) {
  319.       /*
  320.        * This is a non-standard preprocessor directive that must be
  321.        *  passed on to the output.
  322.        */
  323.       keepdir(yylval.t);
  324.       return yylex();
  325.       }
  326.    else if (lex_state == OpHead && yylval.t->tok_id != '}' &&
  327.      GoodChar((int)yylval.t->image[0])) {
  328.       /*
  329.        * This should be the operator symbol in the header of an operation
  330.        *  declaration. Concatenate all operator symbols into one token
  331.        *  of type OpSym.
  332.        */
  333.       sbuf = get_sbuf();
  334.       for (s = yylval.t->image; *s != '\0'; ++s)
  335.          AppChar(*sbuf, *s);
  336.       lk_ahead = preproc();
  337.       while (lk_ahead != NULL && GoodChar((int)lk_ahead->image[0])) {
  338.          for (s = lk_ahead->image; *s != '\0'; ++s)
  339.             AppChar(*sbuf, *s);
  340.          free_t(lk_ahead);
  341.          lk_ahead = preproc();
  342.          }
  343.       yylval.t->tok_id = OpSym;
  344.       yylval.t->image = str_install(sbuf);
  345.       rel_sbuf(sbuf);
  346.       }
  347.    else if (yylval.t->tok_id < 256) {
  348.       /*
  349.        * This is a one-character token, make sure it is valid.
  350.        */
  351.       if (!GoodChar(yylval.t->tok_id))
  352.          errt2(yylval.t, "invalid character: ", yylval.t->image);
  353.       }
  354.  
  355. #if EBCDIC
  356.    if (yylval.t->tok_id < 256)
  357.       return FromEBCDIC[yylval.t->tok_id];
  358. #endif
  359.  
  360.    return yylval.t->tok_id;
  361.    }
  362.