home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 338_02 / stmt.c < prev    next >
Text File  |  1989-10-06  |  13KB  |  424 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.   
  238. struct snode    *contstmt()
  239. {       struct snode    *snp; 
  240.         snp = xalloc(sizeof(struct snode));
  241.         snp->stype = st_continue; 
  242.         getsym();
  243.         if( lastst != end )
  244.                 needpunc( semicolon );
  245.         return snp;
  246. }
  247.   
  248. struct snode    *exprstmt()
  249. /* 
  250.  *      exprstmt is called whenever a statement does not begin 
  251.  *      with a keyword. the statement should be an expression. 
  252.  */ 
  253. {       struct snode    *snp;
  254.         snp = xalloc(sizeof(struct snode));
  255.         snp->stype = st_expr;
  256.         if( expression(&(snp->exp)) == 0 ) { 
  257.                 error(ERR_EXPREXPECT); 
  258.                 getsym(); 
  259.                 } 
  260.         if( lastst != end )
  261.                 needpunc( semicolon );
  262.         return snp;
  263. }
  264.   
  265. struct snode    *compound()
  266. /* 
  267.  *      compound processes a block of statements and forms a linked 
  268.  *      list of the statements within the block. 
  269.  * 
  270.  *      compound expects the input pointer to already be past the
  271.  *      begin symbol of the block. 
  272.  */
  273. {       struct snode    *head, *tail; 
  274.         head = 0; 
  275.         while( lastst != end ) { 
  276.                 if( head == 0 ) 
  277.                         head = tail = statement(); 
  278.                 else    { 
  279.                         tail->next = statement();
  280.                         if( tail->next != 0 )
  281.                                 tail = tail->next; 
  282.                         }
  283.                 } 
  284.         getsym(); 
  285.         return head; 
  286.  
  287. struct snode    *labelstmt() 
  288. /*
  289.  *      labelstmt processes a label that appears before a 
  290.  *      statement as a seperate statement. 
  291.  */ 
  292. {       struct snode    *snp;
  293.         SYM             *sp; 
  294.         snp = xalloc(sizeof(struct snode));
  295.         snp->stype = st_label;
  296.         if( (sp = search(lastid,lsyms.head)) == 0 ) {
  297.                 sp = xalloc(sizeof(SYM));
  298.                 sp->name = litlate(lastid);
  299.                 sp->storage_class = sc_label; 
  300.                 sp->tp = 0; 
  301.                 sp->value.i = nextlabel++; 
  302.                 insert(sp,&lsyms); 
  303.                 }
  304.         else    { 
  305.                 if( sp->storage_class != sc_ulabel )
  306.                         error(ERR_LABEL); 
  307.                 else 
  308.                         sp->storage_class = sc_label; 
  309.                 } 
  310.         getsym();       /* get past id */ 
  311.         needpunc(colon); 
  312.         if( sp->storage_class == sc_label ) {
  313.                 snp->label = &( (int) sp->value.i);
  314.                 snp->next = 0;
  315.                 return snp;
  316.                 }
  317.         return 0; 
  318.   
  319. struct snode    *gotostmt()
  320. /* 
  321.  *      gotostmt processes the goto statement and puts undefined
  322.  *      labels into the symbol table. 
  323.  */ 
  324. {       struct snode    *snp; 
  325.         SYM             *sp; 
  326.         getsym(); 
  327.         if( lastst != id ) { 
  328.                 error(ERR_IDEXPECT);
  329.                 return 0;
  330.                 } 
  331.         snp = xalloc(sizeof(struct snode));
  332.         if( (sp = search(lastid,lsyms.head)) == 0 ) {
  333.                 sp = xalloc(sizeof(SYM));
  334.                 sp->name = litlate(lastid);
  335.                 sp->value.i = nextlabel++;
  336.                 sp->storage_class = sc_ulabel;
  337.                 sp->tp = 0; 
  338.                 insert(sp,&lsyms);
  339.                 } 
  340.         getsym();       /* get past label name */ 
  341.         if( lastst != end )
  342.                 needpunc( semicolon );
  343.         if( sp->storage_class != sc_label && sp->storage_class != sc_ulabel) 
  344.                 error( ERR_LABEL );
  345.         else    {
  346.                 snp->stype = st_goto;
  347.                 snp->label = &( (int) sp->value.i);
  348.                 snp->next = 0;
  349.                 return snp;
  350.                 }
  351.         return 0;
  352. }
  353.  
  354.  
  355. struct snode    *statement()
  356. /*
  357.  *      statement figures out which of the statement processors
  358.  *      should be called and transfers control to the proper
  359.  *      routine.
  360.  */
  361. {       struct snode    *snp;
  362.  
  363.         switch( lastst ) {
  364.                 case semicolon:
  365.                         getsym();
  366.                         snp = 0;
  367.                         break;
  368.                 case begin:
  369.                         getsym();
  370.                         snp = compound();
  371.                         return snp;
  372.                 case kw_if:
  373.                         snp = ifstmt();
  374.                         break;
  375.                 case kw_while:
  376.                         snp = whilestmt();
  377.                         break;
  378.                 case kw_for:
  379.                         snp = forstmt();
  380.                         break;
  381.                 case kw_return:
  382.                         snp = retstmt();
  383.                         break;
  384.                 case kw_break:
  385.                         snp = breakstmt(); 
  386.                         break; 
  387.                 case kw_goto: 
  388.                         snp = gotostmt(); 
  389.                         break; 
  390.                 case kw_continue: 
  391.                         snp = contstmt(); 
  392.                         break; 
  393.                 case kw_do: 
  394.                         snp = dostmt(); 
  395.                         break; 
  396.                 case kw_switch: 
  397.                         snp = switchstmt();
  398.                         break; 
  399.                 case id: 
  400.                         while( isspace(lastch) ) 
  401.                                 cgetch();
  402.                         if( lastch == ':' ) 
  403.                                 return labelstmt(); 
  404.                         /* else fall through to process expression */ 
  405.                 default: 
  406.                         snp = exprstmt(); 
  407.                         break; 
  408.                 } 
  409.         if( snp != 0 ) 
  410.                 snp->next = 0; 
  411.         return snp; 
  412.  
  413.