home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / browser2.zip / parse.c < prev    next >
C/C++ Source or Header  |  1995-02-17  |  21KB  |  856 lines

  1. /* EMACS CLASS BROWSER FOR C++.
  2.    Copyright (C) 1993 Gerd Moellmann. All rights reserved.
  3.    Altenbergstr. 6, D-40235 Duesseldorf, Germany
  4.    CompuServe ID 100025,3303
  5.  
  6.    $Id: parse.c,v 3.1 1995/02/17 18:20:24 mmann Exp $
  7.  
  8.    This file may be made part of GNU Emacs at the option of the FSF.
  9.  
  10.    This code is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY.  No author or distributor
  12.    accepts responsibility to anyone for the consequences of using it
  13.    or for whether it serves any particular purpose or works at all,
  14.    unless he says so in writing.  Refer to the GNU Emacs General Public
  15.    License for full details.
  16.  
  17.    Everyone is granted permission to copy, modify and redistribute
  18.    this code, but only under the conditions described in the
  19.    GNU Emacs General Public License.   A copy of this license is
  20.    supposed to have been given to you along with GNU Emacs so you
  21.    can know your rights and responsibilities.  It should be in a
  22.    file named COPYING.  Among other things, the copyright notice
  23.    and this notice must be preserved on all copies. */
  24.  
  25. /* REMAINING PROBLEMS
  26.    ------------------
  27.    * Handling of nested classes is incorrect. Declarations of the form
  28.    `class X : public Base::X' will lead to a circular reference from
  29.    `X' to `X' as subclass.  I have chosen to ignore the relationship
  30.    in these cases.
  31.  
  32.    * member
  33.    What about the case `class X& some_member();' or `struct {} a;'. 
  34. */
  35.  
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <assert.h>
  40. #include "lex.h"
  41.  
  42. unsigned tk = ~0;
  43.  
  44. #define match()         (tk = yylex ())
  45. #define lookahead()     (tk == ~0u ? (tk = (unsigned) yylex ()) : tk)
  46. #define looking_at(t)   (tk == (t))
  47. #define current_tk()    tk
  48.  
  49. #ifdef PROTOTYPES
  50. static unsigned skip_to (unsigned t);
  51. static void skip_matching (void);
  52. static void member (sym_t* cls, unsigned vis);
  53. static void class_body (sym_t* cls);
  54. static void class_definition (sym_t* anonymous, int is_struct, int nested);
  55. static void declaration (void);
  56. static long parm_list (int* is_const, int* is_pure);
  57. static void operator_name (char* id, int* sc);
  58. #endif
  59.  
  60. void
  61. re_init_parse ()
  62. {
  63.   tk = -1;
  64. }
  65.  
  66. static unsigned
  67. skip_to (t)
  68.      unsigned t;
  69. {
  70.   while (!looking_at (YYEOF) && !looking_at (t))
  71.     match ();
  72.  
  73.   return current_tk ();
  74. }
  75.  
  76. static void
  77. skip_matching ()
  78. {
  79.   unsigned open, close, n;
  80.  
  81.   switch (open = lookahead ())
  82.     {
  83.     case '{':
  84.       close = '}';
  85.       break;
  86.     case '(':
  87.       close = ')';
  88.       break;
  89.     case '<':
  90.       close = '>';
  91.       break;
  92.     case '[':
  93.       close = ']';
  94.       break;
  95.     }
  96.  
  97.   for (n = 0;;)
  98.     {
  99.       if (looking_at (open))
  100.         ++n;
  101.       else if (looking_at (close))
  102.         --n;
  103.       else if (looking_at (YYEOF))
  104.         break;
  105.  
  106.       match ();
  107.  
  108.       if (0 == n)
  109.         break;
  110.     }
  111. }
  112.  
  113. static long
  114. parm_list (is_const, is_pure)
  115.      int* is_const;
  116.      int* is_pure;
  117. {
  118.   unsigned long hash = 0;
  119.   int type_seen = 0;
  120.   unsigned long ident_type_hash = 0;
  121.   unsigned long prev_ident_type_hash = 0;
  122.  
  123.   *is_const = *is_pure = 0;
  124.  
  125.   while (!looking_at (YYEOF) && !looking_at (')'))
  126.     {
  127.       switch (lookahead ())
  128.         {
  129.         case '(':
  130.           skip_matching ();
  131.           break;
  132.  
  133.         case ',':
  134.           match ();
  135.           type_seen = 0;
  136.           break;
  137.  
  138.       /* Ignore the scope part of types, if any. This is because
  139.          some types need scopes when defined outside of a class body,
  140.          and don't need them inside the class body.  This means that
  141.          we have to look for the last IDENT in a sequence of
  142.          IDENT::IDENT::... */
  143.  
  144.         case IDENT:
  145.       if (!type_seen)
  146.             {
  147.           char* s;
  148.           prev_ident_type_hash = ident_type_hash;
  149.           ident_type_hash = 0;
  150.               for (s = yytext; *s; ++s)
  151.                 ident_type_hash = (ident_type_hash << 1) ^ *s;
  152.             }
  153.           match ();
  154.           break;
  155.  
  156.         case VOID:
  157.           /* This distinction is made to make `func (void)' equivalent
  158.              to `func ()'. */
  159.           type_seen = 1;
  160.           match ();
  161.           if (!looking_at (')'))
  162.             hash = (hash << 1) ^ VOID;
  163.           break;
  164.  
  165.         case ELLIPSIS:  case CHAR:      case CLASS:     case CONST:
  166.         case DOUBLE:    case ENUM:      case FLOAT:     case INT:
  167.         case LONG:      case SHORT:     case SIGNED:    case STRUCT:
  168.         case UNION:     case UNSIGNED:  case VOLATILE:
  169.           type_seen = 1;
  170.           hash = (hash << 1) ^ lookahead ();
  171.           match ();
  172.           break;
  173.  
  174.         case '*':       case '&':       case '[':       case ']':
  175.           hash = (hash << 1) ^ lookahead ();
  176.           match ();
  177.           break;
  178.  
  179.         default:
  180.           match ();
  181.           break;
  182.         }
  183.     }
  184.  
  185.   if (!type_seen)
  186.     hash = (hash << 1) ^ prev_ident_type_hash;
  187.  
  188.   /* We can overload the same function on `const' */
  189.  
  190.   if (looking_at (')'))
  191.     {
  192.       match ();
  193.       if (looking_at (CONST))
  194.         {
  195.           hash = (hash << 1) ^ CONST;
  196.           *is_const = 1;
  197.         }
  198.  
  199.       if (looking_at ('='))
  200.         {
  201.           match ();
  202.           if (looking_at (CINT) && long_val == 0)
  203.             {
  204.               match ();
  205.               *is_pure = 1;
  206.             }
  207.         }
  208.     }
  209.  
  210.   return hash;
  211. }
  212.  
  213. /* Note that `cls' my be NULL due to options given on the command
  214.    line. */
  215.  
  216. static void
  217. member (cls, vis)
  218.      sym_t* cls;
  219.      unsigned vis;
  220. {
  221.   member_t* m;
  222.   char id[MAX_ID_LENGTH];
  223.   int sc = SC_MEMBER;
  224.   char* regexp;
  225.   unsigned pos;
  226.   long hash;
  227.   int is_constructor;
  228.   int anonymous = 0;
  229.   int is_struct;
  230.   int is_virtual = 0;
  231.   int is_inline = 0;
  232.   int is_const, is_pure;
  233.   int type_seen = 0;
  234.   int paren_seen = 0;
  235.   *id = 0;
  236.  
  237.   while (!looking_at (';') && !looking_at ('{') && !looking_at (YYEOF))
  238.     {
  239.       switch (lookahead ())
  240.         {
  241.         default:
  242.           match ();
  243.           break;
  244.  
  245.         case '[':
  246.           skip_matching ();
  247.           break;
  248.  
  249.         case ENUM:
  250.           sc = SC_TYPE;
  251.       type_seen = 1;
  252.           match ();
  253.           break;
  254.  
  255.         case TYPEDEF:
  256.           sc = SC_TYPE;
  257.       type_seen = 1;
  258.           match ();
  259.           break;
  260.  
  261.         case '~':
  262.           *id = '~';
  263.           *(id + 1) = 0;
  264.           match ();
  265.           break;
  266.  
  267.         case FRIEND:
  268.           sc = SC_FRIEND;
  269.       type_seen = 1;
  270.           match ();
  271.           break;
  272.  
  273.         case INLINE:
  274.           is_inline = 1;
  275.       type_seen = 1;
  276.           match ();
  277.           break;
  278.  
  279.         case VIRTUAL:
  280.           is_virtual = 1;
  281.       type_seen = 1;
  282.           match ();
  283.           break;
  284.  
  285.         case STATIC:
  286.           sc = SC_STATIC;
  287.       type_seen = 1;
  288.           match ();
  289.           break;
  290.  
  291.         case IDENT:
  292.           /* Remember IDENTS seen so far. Among these will be the member
  293.              name. */
  294.           if (*id == '~')
  295.             strcat (id, yytext);
  296.           else
  297.             strcpy (id, yytext);
  298.  
  299.       assert (strlen (id) < sizeof id);
  300.           match ();
  301.           break;
  302.  
  303.         case OPERATOR:
  304.           operator_name (id, &sc);
  305.       assert (strlen (id) < sizeof id);
  306.           break;
  307.  
  308.         case '(':
  309.           /* Most probably the beginning of a parameter list. */
  310.           match ();
  311.       paren_seen = 1;
  312.  
  313.           if (*id && cls)
  314.             {
  315.               if (!(is_constructor = !strcmp (id, cls->name)))
  316.                 regexp = dupstr (line_start ());
  317.             }
  318.           else
  319.             is_constructor = 0;
  320.  
  321.           pos = buffer_pos ();
  322.           hash = parm_list (&is_const, &is_pure);
  323.  
  324.           if (is_constructor)
  325.             regexp = dupstr (line_start ());
  326.  
  327.           if (*id && cls != NULL)
  328.         add_member_declaration (cls, id, regexp, pos, hash, 0,
  329.                     sc, vis, is_virtual, is_inline,
  330.                     is_const, is_pure);
  331.  
  332.           while (!looking_at (';') && !looking_at ('{')
  333.                  && !looking_at (YYEOF))
  334.             match ();
  335.  
  336.           if (looking_at ('{') && *id && cls)
  337.             add_member_definition (cls, id, regexp, pos, hash,
  338.                                    0, sc, 1, is_const);
  339.  
  340.           *id = 0;
  341.           sc = SC_MEMBER;
  342.           break;
  343.  
  344.         case STRUCT: case UNION: case CLASS:
  345.           /* Nested class */
  346.           is_struct = lookahead () != CLASS;
  347.       type_seen = 1;
  348.           match ();
  349.           anonymous = 1;
  350.  
  351.           /* More than one ident here to allow for MS-DOS specialties
  352.              like `_export class' etc.  The last IDENT seen counts
  353.              as the class name. */
  354.  
  355.           while (looking_at (IDENT))
  356.             {
  357.               anonymous = 0;
  358.               match ();
  359.             }
  360.  
  361.           if (looking_at (':') || looking_at ('{'))
  362.             class_definition (anonymous ? NULL : cls, is_struct, 1);
  363.           else
  364.         skip_to (';');
  365.  
  366.       break;
  367.  
  368.     case INT:     case CHAR:     case LONG:     case UNSIGNED:
  369.     case SIGNED:     case CONST:     case DOUBLE:     case VOID:
  370.     case SHORT:    case VOLATILE:
  371.       type_seen = 1;
  372.       match ();
  373.       break;
  374.         }
  375.     }
  376.  
  377.   if (looking_at (';'))
  378.     {
  379.       /* The end of member variable, a friend declaration or an access
  380.      declaration. We don't want to add friend classes as members. */
  381.  
  382.       if (*id && sc != SC_FRIEND && cls)
  383.         {
  384.           regexp = dupstr (line_start ());
  385.           pos = buffer_pos ();
  386.       
  387.       if (cls != NULL)
  388.         {
  389.           if (type_seen || !paren_seen)
  390.         add_member_declaration (cls, id, regexp, pos, 0, 1,
  391.                     sc, vis, 0, 0, 0, 0);
  392.           else
  393.         add_member_declaration (cls, id, regexp, pos, hash, 0,
  394.                     sc, vis, 0, 0, 0, 0);
  395.         }
  396.         }
  397.       match ();
  398.     }
  399.   else if (looking_at ('{'))
  400.     {
  401.       /* A named enum */
  402.       if (sc == SC_TYPE && *id && cls)
  403.         {
  404.           regexp = dupstr (line_start ());
  405.           pos = buffer_pos ();
  406.  
  407.       if (cls != NULL)
  408.         {
  409.           add_member_declaration (cls, id, regexp, pos, 0, 1, sc, vis,
  410.                       0, 0, 0, 0);
  411.           add_member_definition (cls, id, regexp, pos, 0, 1, sc, 0, 0);
  412.         }
  413.         }
  414.  
  415.       skip_matching ();
  416.     }
  417. }
  418.  
  419. static void
  420. class_body (cls)
  421.      sym_t* cls;
  422. {
  423.   int t;
  424.   unsigned vis = PRIVATE;
  425.   unsigned temp;
  426.  
  427.   while (!looking_at (YYEOF) && !looking_at ('}'))
  428.     {
  429.       switch (lookahead ())
  430.         {
  431.         case PRIVATE: case PROTECTED: case PUBLIC:
  432.           temp = lookahead ();
  433.           match ();
  434.  
  435.           if (looking_at (':'))
  436.             {
  437.               vis = temp;
  438.               match ();
  439.             }
  440.           else
  441.             {
  442.               /* Probably conditional compilation for inheritance list.
  443.                  We don't known whether there comes more of this.
  444.                  This is only a crude fix that works most of the time. */
  445.               do
  446.                 {
  447.                   match ();
  448.                 }
  449.               while (looking_at (IDENT) || looking_at (',')
  450.                      || looking_at (PUBLIC) || looking_at (PROTECTED)
  451.                      || looking_at (PRIVATE));
  452.             }
  453.           break;
  454.  
  455.           /* Try to synchronize */
  456.         case CHAR:      case CLASS:     case CONST:
  457.         case DOUBLE:    case ENUM:      case FLOAT:     case INT:
  458.         case LONG:      case SHORT:     case SIGNED:    case STRUCT:
  459.         case UNION:     case UNSIGNED:  case VOID:      case VOLATILE:
  460.         case TYPEDEF:   case STATIC:    case INLINE:    case FRIEND:
  461.         case VIRTUAL:   case TEMPLATE:  case IDENT:     case '~':
  462.           member (cls, vis);
  463.           break;
  464.  
  465.         default:
  466.           match ();
  467.           break;
  468.         }
  469.     }
  470. }
  471.  
  472. static void
  473. class_definition (containing_anonymous, is_struct, nested)
  474.      sym_t* containing_anonymous;
  475.      int is_struct;
  476.      int nested;
  477. {
  478.   sym_t* super;
  479.   sym_t* sub;
  480.  
  481.   if ((is_struct && !f_structs) || (nested && !f_nested_classes))
  482.     sub = NULL;
  483.   else
  484.     {
  485.       if (containing_anonymous)
  486.         sub = containing_anonymous;
  487.       else
  488.         {
  489.           sub = add_sym (yytext);
  490.           sub->pos = buffer_pos ();
  491.           sub->regexp = dupstr (line_start ());
  492.           sub->filename = filename;
  493.         }
  494.     }
  495.  
  496.   if (looking_at (':'))
  497.     {
  498.       /* If at ':', inheritance list follows. */
  499.       match ();
  500.  
  501.       for (;;)
  502.         {
  503.           switch (lookahead ())
  504.             {
  505.             case VIRTUAL: case PUBLIC: case PROTECTED: case PRIVATE: case ',':
  506.               match ();
  507.               break;
  508.             case IDENT:
  509.               /* The name of a base class. To avoid circular references that
  510.          come from something like `class X : public Base::X', do
  511.          not add a link in this case. */
  512.  
  513.               if (! ((is_struct && !f_structs)
  514.              || (nested && !f_nested_classes)))
  515.                 {
  516.                   super = add_sym (yytext);
  517.  
  518.           if (super != sub)
  519.             add_link (super, sub);
  520.                 }
  521.               match ();
  522.               break;
  523.  
  524.             case '<':
  525.               skip_matching ();
  526.               break;
  527.  
  528.           /* A base class name may have the form A<>::B<>... */
  529.  
  530.         case DCOLON:
  531.           match ();
  532.           break;
  533.  
  534.             case '{':
  535.               goto l_class_body;
  536.  
  537.             default:
  538.               /* A syntax error, possibly due to preprocessor constructs
  539.          like
  540.  
  541.          #ifdef SOMETHING
  542.          class A : public B
  543.          #else
  544.          class A : private B.
  545.  
  546.          Match until we see something like `;' or `{'. */
  547.  
  548.           while (!(looking_at (';') || !looking_at (YYEOF)
  549.                || looking_at ('{')))
  550.         match ();
  551.  
  552.           goto l_class_body;
  553.             }
  554.         }
  555.     }
  556.  
  557.  l_class_body:;
  558.  
  559.   if (looking_at ('{'))
  560.     {
  561.       if (is_struct && !f_structs)
  562.         skip_matching ();
  563.       else
  564.         {
  565.           match ();
  566.           class_body (sub);
  567.  
  568.       if (looking_at ('}'))
  569.         {
  570.           match ();
  571.           if (looking_at (';') && !nested)
  572.         match ();
  573.         }
  574.         }
  575.     }
  576. }
  577.  
  578. static void
  579. operator_name (id, sc)
  580.      char* id;
  581.      int* sc;
  582. {
  583.   match ();
  584.  
  585.   if (looking_at (NEW) || looking_at (DELETE))
  586.     {
  587.       if (*sc != SC_FRIEND)
  588.         *sc = SC_STATIC;
  589.  
  590.       strcpy (id, token_string (lookahead ()));
  591.       match ();
  592.     }
  593.   else
  594.     {
  595.       strcpy (id, "operator");
  596.  
  597.       /* Beware access declarations of the form "X::f;" */
  598.  
  599.       do
  600.         {
  601.           strcat (id, " ");
  602.           strcat (id, token_string (lookahead ()));
  603.           match ();
  604.         }
  605.       while (!looking_at ('(') && !looking_at (';'));
  606.     }
  607.  
  608.   assert (strlen (id) < MAX_ID_LENGTH);
  609. }
  610.  
  611. static void
  612. declaration ()
  613. {
  614.   char id[MAX_ID_LENGTH];
  615.   sym_t* cls = NULL;
  616.   char* regexp;
  617.   unsigned pos;
  618.   long hash;
  619.   int is_constructor;
  620.   int is_inline = 0;
  621.   int is_const;
  622.   int is_pure;
  623.   int sc = 0;
  624.  
  625.   *id = 0;
  626.  
  627.   while (!looking_at (';') && !looking_at ('{') && !looking_at (YYEOF))
  628.     {
  629.       switch (lookahead ())
  630.         {
  631.         default:
  632.           match ();
  633.           break;
  634.  
  635.     case '[':
  636.       skip_matching ();
  637.       break;
  638.  
  639.     case ENUM:
  640.     case TYPEDEF:
  641.       sc = SC_TYPE;
  642.       match ();
  643.       break;
  644.       
  645.         case STATIC:
  646.           sc = SC_STATIC;
  647.           match ();
  648.           break;
  649.  
  650.     case INT:     case CHAR:     case LONG:     case UNSIGNED:
  651.     case SIGNED:     case CONST:     case DOUBLE:     case VOID:
  652.     case SHORT:    case VOLATILE:
  653.       match ();
  654.       break;
  655.  
  656.         case CLASS: case STRUCT: case UNION:
  657.           /* This is for the case `STARTWRAP class X : ...' or
  658.              `declare (X, Y)\n class A : ...'. */
  659.           if (*id)
  660.             return;
  661.  
  662.         case '=':
  663.           /* Assumed to be the start of an initialization in this context.
  664.              Skip over everything upto ';'. */
  665.           skip_to (';');
  666.           break;
  667.  
  668.         case '~':
  669.           *id = '~';
  670.           *(id + 1) = 0;
  671.           match ();
  672.           break;
  673.  
  674.         case OPERATOR:
  675.           operator_name (id, &sc);
  676.           break;
  677.  
  678.         case INLINE:
  679.           is_inline = 1;
  680.           match ();
  681.           break;
  682.  
  683.         case IDENT:
  684.           if (*id == '~')
  685.             strcat (id, yytext);
  686.           else
  687.             strcpy (id, yytext);
  688.  
  689.       assert (strlen (id) < MAX_ID_LENGTH);
  690.           match ();
  691.  
  692.           /* Template arguments */
  693.           if (looking_at ('<'))
  694.             skip_matching ();
  695.  
  696.           /* Maybe class name not yet seen. */
  697.           if (looking_at (DCOLON))
  698.             {
  699.               cls = add_sym (id);
  700.               match ();
  701.             }
  702.           break;
  703.  
  704.         case '(':
  705.           /* Most probably the beginning of a parameter list. */
  706.           if (cls)
  707.             {
  708.               match ();
  709.  
  710.               if (*id && cls)
  711.                 {
  712.                   if (!(is_constructor = !strcmp (id, cls->name)))
  713.                     regexp = dupstr (line_start ());
  714.                 }
  715.               else
  716.                 is_constructor = 0;
  717.  
  718.               pos = buffer_pos ();
  719.               hash = parm_list (&is_const, &is_pure);
  720.  
  721.               if (is_constructor)
  722.                 regexp = dupstr (line_start ());
  723.  
  724.               if (*id && cls)
  725.                 add_member_definition (cls, id, regexp, pos,
  726.                                        hash, 0, SC_UNKNOWN,
  727.                                        is_inline, is_const);
  728.             }
  729.           else
  730.             {
  731.               /* This may be a normal C functions, but also a macro
  732.                  call of the form `declare (A, B)' --- such macros
  733.                  can be found in some foundation class libraries. */
  734.  
  735.               match ();
  736.  
  737.               if (*id)
  738.                 {
  739.                   regexp = dupstr (line_start ());
  740.                   pos = buffer_pos ();
  741.                   hash = parm_list (&is_const, &is_pure);
  742.                   add_global_declaration (id, regexp, pos, hash, 0, sc,
  743.                       is_inline, is_const);
  744.                 }
  745.  
  746.               /* This is for the case that the function really is
  747.                  a macro with no `;' following it.  If a CLASS directly
  748.                  follows, we would miss it otherwise. */
  749.  
  750.               if (looking_at (CLASS) || looking_at (STRUCT)
  751.                   || looking_at (UNION))
  752.                 return;
  753.             }
  754.  
  755.       while (!looking_at (';') && !looking_at ('{')
  756.                  && !looking_at (YYEOF))
  757.             match ();
  758.  
  759.       if (!cls && *id && looking_at ('{'))
  760.         add_global_definition (id, regexp, pos, hash, 0, sc,
  761.                    is_inline, is_const);
  762.  
  763.           *id = 0;
  764.           is_inline = 0;
  765.           break;
  766.         }
  767.     }
  768.  
  769.   if (looking_at (';'))
  770.     {
  771.       /* The end of member variable or of an access declaration `X::f'.
  772.      To distinguish between them we had to know whether type information
  773.      has been seen. */
  774.  
  775.       if (*id)
  776.         {
  777.           char* regexp = dupstr (line_start ());
  778.           unsigned pos = buffer_pos ();
  779.  
  780.       if (cls)
  781.         add_member_definition (cls, id, regexp, pos, 0, 1,
  782.                    SC_UNKNOWN, 0, 0);
  783.       else
  784.         add_global_definition (id, regexp, pos, 0, 1, sc, is_inline,
  785.                    is_const);
  786.         }
  787.     
  788.       match ();
  789.     }
  790.   else if (looking_at ('{'))
  791.     {
  792.       if (sc == SC_TYPE && *id)
  793.         {
  794.       /* A named enum */
  795.           regexp = dupstr (line_start ());
  796.           pos = buffer_pos ();
  797.           /* add_global_declaration (id, regexp, pos, 0, 1, sc, 0, 0); */
  798.           add_global_definition (id, regexp, pos, 0, 1, sc, 0, 0);
  799.         }
  800.  
  801.       skip_matching ();
  802.     }
  803. }
  804.  
  805. int
  806. yyparse ()
  807. {
  808.   int anonymous;
  809.   unsigned class_tk;
  810.  
  811.   for (;;)
  812.     {
  813.       switch (lookahead ())
  814.         {
  815.         case TEMPLATE:
  816.           match ();
  817.           if (looking_at ('<'))
  818.             skip_matching ();
  819.           break;
  820.  
  821.         case CLASS: case STRUCT: case UNION:
  822.           class_tk = lookahead ();
  823.           match ();
  824.           anonymous = 1;
  825.  
  826.           /* More than one ident here to allow for MS-DOS specialties
  827.          like `far', `_export' etc. */
  828.  
  829.           while (looking_at (IDENT))
  830.             {
  831.               anonymous = 0;
  832.               match ();
  833.             }
  834.  
  835.           /* Don't add anonymous unions. */
  836.           if ((looking_at (':') || looking_at ('{')) && !anonymous)
  837.               class_definition (NULL, class_tk != CLASS, 0);
  838.           else
  839.             {
  840.               if (skip_to (';') == ';')
  841.                 match ();
  842.             }
  843.           break;
  844.  
  845.         case YYEOF:
  846.           return 1;
  847.  
  848.         default:
  849.           declaration ();
  850.           break;
  851.         }
  852.     }
  853. }
  854.  
  855.  
  856.