home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 204_01 / stmt.c < prev    next >
Text File  |  1979-12-31  |  13KB  |  422 lines

  1. #include        <stdio.h> 
  2. #include        "c.h" 
  3. #include        "expr.h" 
  4. #include        "gen.h"
  5. #include        "cglbdec.h" 
  6.  
  7. /*
  8.  *    68000 C compiler
  9.  *
  10.  *    Copyright 1984, 1985, 1986 Matthew Brandt.
  11.  *  all commercial rights reserved.
  12.  *
  13.  *    This compiler is intended as an instructive tool for personal use. Any
  14.  *    use for profit without the written consent of the author is prohibited.
  15.  *
  16.  *    This compiler may be distributed freely for non-commercial use as long
  17.  *    as this notice stays intact. Please forward any enhancements or questions
  18.  *    to:
  19.  *
  20.  *        Matthew Brandt
  21.  *        Box 920337
  22.  *        Norcross, Ga 30092
  23.  */
  24.   
  25. /* 
  26.  *      the statement module handles all of the possible c statements 
  27.  *      and builds a parse tree of the statements. 
  28.  * 
  29.  *      each routine returns a pointer to a statement parse node which 
  30.  *      reflects the statement just parsed. 
  31.  */ 
  32.   
  33. struct snode    *statement();   /* forward declaration */ 
  34.   
  35. struct snode    *whilestmt() 
  36. /* 
  37.  *      whilestmt parses the c while statement. 
  38.  */ 
  39. {       struct snode    *snp; 
  40.         snp = xalloc(sizeof(struct snode)); 
  41.         snp->stype = st_while; 
  42.         getsym(); 
  43.         if( lastst != openpa ) 
  44.                 error(ERR_EXPREXPECT); 
  45.         else    { 
  46.                 getsym(); 
  47.                 if( expression(&(snp->exp)) == 0 ) 
  48.                         error(ERR_EXPREXPECT); 
  49.                 needpunc( closepa ); 
  50.                 snp->s1 = statement(); 
  51.                 } 
  52.         return snp; 
  53.   
  54. struct snode    *dostmt() 
  55. /* 
  56.  *      dostmt parses the c do-while construct. 
  57.  */ 
  58. {       struct snode    *snp; 
  59.         snp = xalloc(sizeof(struct snode)); 
  60.         snp->stype = st_do; 
  61.         getsym(); 
  62.         snp->s1 = statement(); 
  63.         if( lastst != kw_while ) 
  64.                 error(ERR_WHILEXPECT); 
  65.         else    { 
  66.                 getsym(); 
  67.                 if( lastst != openpa ) 
  68.                         error(ERR_EXPREXPECT); 
  69.                 else    { 
  70.                         getsym(); 
  71.                         if( expression(&(snp->exp)) == 0 ) 
  72.                                 error(ERR_EXPREXPECT); 
  73.                         needpunc(closepa); 
  74.                         } 
  75.                 if( lastst != end )
  76.                         needpunc( semicolon );
  77.                 } 
  78.         return snp; 
  79.   
  80. struct snode    *forstmt() 
  81. {       struct snode    *snp; 
  82.         snp = xalloc(sizeof(struct snode)); 
  83.         getsym(); 
  84.         needpunc(openpa); 
  85.         if( expression(&(snp->label)) == 0 ) 
  86.                 snp->label = 0; 
  87.         needpunc(semicolon); 
  88.         snp->stype = st_for; 
  89.         if( expression(&(snp->exp)) == 0 ) 
  90.                 snp->exp = 0; 
  91.         needpunc(semicolon); 
  92.         if( expression(&(snp->s2)) == 0 ) 
  93.                 snp->s2 = 0; 
  94.         needpunc(closepa); 
  95.         snp->s1 = statement(); 
  96.         return snp; 
  97.   
  98. struct snode    *ifstmt() 
  99. /* 
  100.  *      ifstmt parses the c if statement and an else clause if 
  101.  *      one is present. 
  102.  */ 
  103. {       struct snode    *snp; 
  104.         snp = xalloc(sizeof(struct snode)); 
  105.         snp->stype = st_if; 
  106.         getsym(); 
  107.         if( lastst != openpa ) 
  108.                 error(ERR_EXPREXPECT); 
  109.         else    { 
  110.                 getsym(); 
  111.                 if( expression(&(snp->exp)) == 0 ) 
  112.                         error(ERR_EXPREXPECT); 
  113.                 needpunc( closepa ); 
  114.                 snp->s1 = statement(); 
  115.                 if( lastst == kw_else ) { 
  116.                         getsym(); 
  117.                         snp->s2 = statement(); 
  118.                         } 
  119.                 else 
  120.                         snp->s2 = 0; 
  121.                 } 
  122.         return snp; 
  123.   
  124. struct snode    *casestmt() 
  125. /* 
  126.  *      cases are returned as seperate statements. for normal 
  127.  *      cases label is the case value and s2 is zero. for the 
  128.  *      default case s2 is nonzero. 
  129.  */ 
  130. {       struct snode    *snp; 
  131.         struct snode    *head, *tail; 
  132.         snp = xalloc(sizeof(struct snode)); 
  133.         if( lastst == kw_case ) { 
  134.                 getsym(); 
  135.                 snp->s2 = 0;
  136.                 snp->stype = st_case;
  137.                 snp->label = intexpr(); 
  138.                 } 
  139.         else if( lastst == kw_default) { 
  140.                 getsym(); 
  141.                 snp->s2 = 1; 
  142.                 } 
  143.         else    { 
  144.                 error(ERR_NOCASE); 
  145.                 return 0; 
  146.                 } 
  147.         needpunc(colon); 
  148.         head = 0; 
  149.         while( lastst != end && 
  150.                 lastst != kw_case && 
  151.                 lastst != kw_default ) { 
  152.                 if( head == 0 ) 
  153.                         head = tail = statement(); 
  154.                 else    { 
  155.                         tail->next = statement(); 
  156.                         if( tail->next != 0 ) 
  157.                                 tail = tail->next; 
  158.                         } 
  159.                 tail->next = 0; 
  160.                 } 
  161.         snp->s1 = head; 
  162.         return snp; 
  163.   
  164. int     checkcases(head) 
  165. /* 
  166.  *      checkcases will check to see if any duplicate cases 
  167.  *      exist in the case list pointed to by head. 
  168.  */ 
  169. struct snode    *head; 
  170. {     
  171.     struct snode    *top, *cur;
  172.     cur = top = head;
  173.     while( top != 0 )
  174.     {
  175.         cur = top->next;
  176.         while( cur != 0 )
  177.         {
  178.             if( (!(cur->s1 || cur->s2) && cur->label == top->label)
  179.                 || (cur->s2 && top->s2) )
  180.             {
  181.                 printf(" duplicate case label %d\n",cur->label);
  182.                 return 1;
  183.             }
  184.             cur = cur->next;
  185.         }
  186.         top = top->next;
  187.     }
  188.     return 0;
  189.   
  190. struct snode    *switchstmt() 
  191. {       struct snode    *snp; 
  192.         struct snode    *head, *tail; 
  193.         snp = xalloc(sizeof(struct snode)); 
  194.         snp->stype = st_switch; 
  195.         getsym(); 
  196.         needpunc(openpa); 
  197.         if( expression(&(snp->exp)) == 0 ) 
  198.                 error(ERR_EXPREXPECT); 
  199.         needpunc(closepa); 
  200.         needpunc(begin); 
  201.         head = 0; 
  202.         while( lastst != end ) { 
  203.                 if( head == 0 ) 
  204.                         head = tail = casestmt(); 
  205.                 else    { 
  206.                         tail->next = casestmt(); 
  207.                         if( tail->next != 0 ) 
  208.                                 tail = tail->next; 
  209.                         } 
  210.                 tail->next = 0; 
  211.                 } 
  212.         snp->s1 = head; 
  213.         getsym(); 
  214.         if( checkcases(head) ) 
  215.                 error(ERR_DUPCASE); 
  216.         return snp; 
  217.   
  218. struct snode    *retstmt() 
  219. {       struct snode    *snp; 
  220.         snp = xalloc(sizeof(struct snode)); 
  221.         snp->stype = st_return; 
  222.         getsym(); 
  223.         expression(&(snp->exp));
  224.         if( lastst != end )
  225.                 needpunc( semicolon );
  226.         return snp; 
  227.   
  228. struct snode    *breakstmt() 
  229. {       struct snode    *snp; 
  230.         snp = xalloc(sizeof(struct snode)); 
  231.         snp->stype = st_break; 
  232.         getsym(); 
  233.         if( lastst != end )
  234.                 needpunc( semicolon );
  235.         return snp; 
  236.   
  237. struct snode    *contstmt() 
  238. {       struct snode    *snp; 
  239.         snp = xalloc(sizeof(struct snode)); 
  240.         snp->stype = st_continue; 
  241.         getsym();
  242.         if( lastst != end )
  243.                 needpunc( semicolon );
  244.         return snp;
  245.   
  246. struct snode    *exprstmt() 
  247. /* 
  248.  *      exprstmt is called whenever a statement does not begin 
  249.  *      with a keyword. the statement should be an expression. 
  250.  */ 
  251. {       struct snode    *snp; 
  252.         snp = xalloc(sizeof(struct snode)); 
  253.         snp->stype = st_expr; 
  254.         if( expression(&(snp->exp)) == 0 ) { 
  255.                 error(ERR_EXPREXPECT); 
  256.                 getsym(); 
  257.                 } 
  258.         if( lastst != end )
  259.                 needpunc( semicolon );
  260.         return snp; 
  261.   
  262. struct snode    *compound() 
  263. /* 
  264.  *      compound processes a block of statements and forms a linked 
  265.  *      list of the statements within the block. 
  266.  * 
  267.  *      compound expects the input pointer to already be past the 
  268.  *      begin symbol of the block. 
  269.  */ 
  270. {       struct snode    *head, *tail; 
  271.         head = 0; 
  272.         while( lastst != end ) { 
  273.                 if( head == 0 ) 
  274.                         head = tail = statement(); 
  275.                 else    { 
  276.                         tail->next = statement(); 
  277.                         if( tail->next != 0 ) 
  278.                                 tail = tail->next; 
  279.                         } 
  280.                 } 
  281.         getsym(); 
  282.         return head; 
  283.   
  284. struct snode    *labelstmt() 
  285. /* 
  286.  *      labelstmt processes a label that appears before a 
  287.  *      statement as a seperate statement. 
  288.  */ 
  289. {       struct snode    *snp; 
  290.         SYM             *sp; 
  291.         snp = xalloc(sizeof(struct snode)); 
  292.         snp->stype = st_label; 
  293.         if( (sp = search(lastid,lsyms.head)) == 0 ) { 
  294.                 sp = xalloc(sizeof(SYM)); 
  295.                 sp->name = litlate(lastid); 
  296.                 sp->storage_class = sc_label; 
  297.                 sp->tp = 0; 
  298.                 sp->value.i = nextlabel++; 
  299.                 insert(sp,&lsyms); 
  300.                 } 
  301.         else    { 
  302.                 if( sp->storage_class != sc_ulabel ) 
  303.                         error(ERR_LABEL); 
  304.                 else 
  305.                         sp->storage_class = sc_label; 
  306.                 } 
  307.         getsym();       /* get past id */ 
  308.         needpunc(colon); 
  309.         if( sp->storage_class == sc_label ) { 
  310.                 snp->label = sp->value.i; 
  311.                 snp->next = 0; 
  312.                 return snp; 
  313.                 } 
  314.         return 0; 
  315.   
  316. struct snode    *gotostmt() 
  317. /* 
  318.  *      gotostmt processes the goto statement and puts undefined 
  319.  *      labels into the symbol table. 
  320.  */ 
  321. {       struct snode    *snp; 
  322.         SYM             *sp; 
  323.         getsym(); 
  324.         if( lastst != id ) { 
  325.                 error(ERR_IDEXPECT); 
  326.                 return 0; 
  327.                 } 
  328.         snp = xalloc(sizeof(struct snode)); 
  329.         if( (sp = search(lastid,lsyms.head)) == 0 ) { 
  330.                 sp = xalloc(sizeof(SYM)); 
  331.                 sp->name = litlate(lastid); 
  332.                 sp->value.i = nextlabel++; 
  333.                 sp->storage_class = sc_ulabel; 
  334.                 sp->tp = 0; 
  335.                 insert(sp,&lsyms); 
  336.                 } 
  337.         getsym();       /* get past label name */ 
  338.         if( lastst != end )
  339.                 needpunc( semicolon );
  340.         if( sp->storage_class != sc_label && sp->storage_class != sc_ulabel) 
  341.                 error( ERR_LABEL ); 
  342.         else    { 
  343.                 snp->stype = st_goto; 
  344.                 snp->label = sp->value.i; 
  345.                 snp->next = 0; 
  346.                 return snp; 
  347.                 } 
  348.         return 0; 
  349.   
  350. struct snode    *statement() 
  351. /* 
  352.  *      statement figures out which of the statement processors 
  353.  *      should be called and transfers control to the proper 
  354.  *      routine. 
  355.  */ 
  356. {       struct snode    *snp; 
  357.         switch( lastst ) { 
  358.                 case semicolon: 
  359.                         getsym(); 
  360.                         snp = 0; 
  361.                         break; 
  362.                 case begin: 
  363.                         getsym(); 
  364.                         snp = compound(); 
  365.                         return snp; 
  366.                 case kw_if: 
  367.                         snp = ifstmt(); 
  368.                         break; 
  369.                 case kw_while: 
  370.                         snp = whilestmt(); 
  371.                         break; 
  372.                 case kw_for: 
  373.                         snp = forstmt(); 
  374.                         break; 
  375.                 case kw_return: 
  376.                         snp = retstmt(); 
  377.                         break; 
  378.                 case kw_break: 
  379.                         snp = breakstmt(); 
  380.                         break; 
  381.                 case kw_goto: 
  382.                         snp = gotostmt(); 
  383.                         break; 
  384.                 case kw_continue: 
  385.                         snp = contstmt(); 
  386.                         break; 
  387.                 case kw_do: 
  388.                         snp = dostmt(); 
  389.                         break; 
  390.                 case kw_switch: 
  391.                         snp = switchstmt(); 
  392.                         break; 
  393.                 case id: 
  394.                         while( isspace(lastch) ) 
  395.                                 getch(); 
  396.                         if( lastch == ':' ) 
  397.                                 return labelstmt(); 
  398.                         /* else fall through to process expression */ 
  399.                 default: 
  400.                         snp = exprstmt(); 
  401.                         break; 
  402.                 } 
  403.         if( snp != 0 ) 
  404.                 snp->next = 0; 
  405.         return snp; 
  406.  
  407.