home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / c / c68k_src / stmt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-12-10  |  12.3 KB  |  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.  
  55. struct snode    *dostmt()
  56. /*
  57.  *      dostmt parses the c do-while construct.
  58.  */
  59. {       struct snode    *snp;
  60.         snp = xalloc(sizeof(struct snode));
  61.         snp->stype = st_do;
  62.         getsym();
  63.         snp->s1 = statement();
  64.         if( lastst != kw_while )
  65.                 error(ERR_WHILEXPECT);
  66.         else    {
  67.                 getsym();
  68.                 if( lastst != openpa )
  69.                         error(ERR_EXPREXPECT);
  70.                 else    {
  71.                         getsym();
  72.                         if( expression(&(snp->exp)) == 0 )
  73.                                 error(ERR_EXPREXPECT);
  74.                         needpunc(closepa);
  75.                         }
  76.                 if( lastst != end )
  77.                         needpunc( semicolon );
  78.                 }
  79.         return snp;
  80. }
  81.  
  82. struct snode    *forstmt()
  83. {       struct snode    *snp;
  84.         snp = xalloc(sizeof(struct snode));
  85.         getsym();
  86.         needpunc(openpa);
  87.         if( expression(&(snp->label)) == 0 )
  88.                 snp->label = 0;
  89.         needpunc(semicolon);
  90.         snp->stype = st_for;
  91.         if( expression(&(snp->exp)) == 0 )
  92.                 snp->exp = 0;
  93.         needpunc(semicolon);
  94.         if( expression(&(snp->s2)) == 0 )
  95.                 snp->s2 = 0;
  96.         needpunc(closepa);
  97.         snp->s1 = statement();
  98.         return snp;
  99. }
  100.  
  101. struct snode    *ifstmt()
  102. /*
  103.  *      ifstmt parses the c if statement and an else clause if
  104.  *      one is present.
  105.  */
  106. {       struct snode    *snp;
  107.         snp = xalloc(sizeof(struct snode));
  108.         snp->stype = st_if;
  109.         getsym();
  110.         if( lastst != openpa )
  111.                 error(ERR_EXPREXPECT);
  112.         else    {
  113.                 getsym();
  114.                 if( expression(&(snp->exp)) == 0 )
  115.                         error(ERR_EXPREXPECT);
  116.                 needpunc( closepa );
  117.                 snp->s1 = statement();
  118.                 if( lastst == kw_else ) {
  119.                         getsym();
  120.                         snp->s2 = statement();
  121.                         }
  122.                 else
  123.                         snp->s2 = 0;
  124.                 }
  125.         return snp;
  126. }
  127.  
  128. struct snode    *casestmt()
  129. /*
  130.  *      cases are returned as seperate statements. for normal
  131.  *      cases label is the case value and s2 is zero. for the
  132.  *      default case s2 is nonzero.
  133.  */
  134. {       struct snode    *snp;
  135.         struct snode    *head, *tail;
  136.         snp = xalloc(sizeof(struct snode));
  137.         if( lastst == kw_case ) {
  138.                 getsym();
  139.                 snp->s2 = 0;
  140.                 snp->stype = st_case;
  141.                 snp->label = intexpr();
  142.                 }
  143.         else if( lastst == kw_default) {
  144.                 getsym();
  145.                 snp->s2 = 1;
  146.                 }
  147.         else    {
  148.                 error(ERR_NOCASE);
  149.                 return 0;
  150.                 }
  151.         needpunc(colon);
  152.         head = 0;
  153.         while( lastst != end &&
  154.                 lastst != kw_case &&
  155.                 lastst != kw_default ) {
  156.                 if( head == 0 )
  157.                         head = tail = statement();
  158.                 else    {
  159.                         tail->next = statement();
  160.                         if( tail->next != 0 )
  161.                                 tail = tail->next;
  162.                         }
  163.                 tail->next = 0;
  164.                 }
  165.         snp->s1 = head;
  166.         return snp;
  167. }
  168.  
  169. int     checkcases(head)
  170. /*
  171.  *      checkcases will check to see if any duplicate cases
  172.  *      exist in the case list pointed to by head.
  173.  */
  174. struct snode    *head;
  175. {
  176.     struct snode    *top, *cur;
  177.     cur = top = head;
  178.     while( top != 0 )
  179.     {
  180.         cur = top->next;
  181.         while( cur != 0 )
  182.         {
  183.             if( (!(cur->s1 || cur->s2) && cur->label == top->label)
  184.                 || (cur->s2 && top->s2) )
  185.             {
  186.                 printf(" duplicate case label %d\n",cur->label);
  187.                 return 1;
  188.             }
  189.             cur = cur->next;
  190.         }
  191.         top = top->next;
  192.     }
  193.     return 0;
  194. }
  195.  
  196. struct snode    *switchstmt()
  197. {       struct snode    *snp;
  198.         struct snode    *head, *tail;
  199.         snp = xalloc(sizeof(struct snode));
  200.         snp->stype = st_switch;
  201.         getsym();
  202.         needpunc(openpa);
  203.         if( expression(&(snp->exp)) == 0 )
  204.                 error(ERR_EXPREXPECT);
  205.         needpunc(closepa);
  206.         needpunc(begin);
  207.         head = 0;
  208.         while( lastst != end ) {
  209.                 if( head == 0 )
  210.                         head = tail = casestmt();
  211.                 else    {
  212.                         tail->next = casestmt();
  213.                         if( tail->next != 0 )
  214.                                 tail = tail->next;
  215.                         }
  216.                 tail->next = 0;
  217.                 }
  218.         snp->s1 = head;
  219.         getsym();
  220.         if( checkcases(head) )
  221.                 error(ERR_DUPCASE);
  222.         return snp;
  223. }
  224.  
  225. struct snode    *retstmt()
  226. {       struct snode    *snp;
  227.         snp = xalloc(sizeof(struct snode));
  228.         snp->stype = st_return;
  229.         getsym();
  230.         expression(&(snp->exp));
  231.         if( lastst != end )
  232.                 needpunc( semicolon );
  233.         return snp;
  234. }
  235.  
  236. struct snode    *breakstmt()
  237. {       struct snode    *snp;
  238.         snp = xalloc(sizeof(struct snode));
  239.         snp->stype = st_break;
  240.         getsym();
  241.         if( lastst != end )
  242.                 needpunc( semicolon );
  243.         return snp;
  244. }
  245.  
  246. struct snode    *contstmt()
  247. {       struct snode    *snp;
  248.         snp = xalloc(sizeof(struct snode));
  249.         snp->stype = st_continue;
  250.         getsym();
  251.         if( lastst != end )
  252.                 needpunc( semicolon );
  253.         return snp;
  254. }
  255.  
  256. struct snode    *exprstmt()
  257. /*
  258.  *      exprstmt is called whenever a statement does not begin
  259.  *      with a keyword. the statement should be an expression.
  260.  */
  261. {       struct snode    *snp;
  262.         snp = xalloc(sizeof(struct snode));
  263.         snp->stype = st_expr;
  264.         if( expression(&(snp->exp)) == 0 ) {
  265.                 error(ERR_EXPREXPECT);
  266.                 getsym();
  267.                 }
  268.         if( lastst != end )
  269.                 needpunc( semicolon );
  270.         return snp;
  271. }
  272.  
  273. struct snode    *compound()
  274. /*
  275.  *      compound processes a block of statements and forms a linked
  276.  *      list of the statements within the block.
  277.  *
  278.  *      compound expects the input pointer to already be past the
  279.  *      begin symbol of the block.
  280.  */
  281. {       struct snode    *head, *tail;
  282.         head = 0;
  283.         while( lastst != end ) {
  284.                 if( head == 0 )
  285.                         head = tail = statement();
  286.                 else    {
  287.                         tail->next = statement();
  288.                         if( tail->next != 0 )
  289.                                 tail = tail->next;
  290.                         }
  291.                 }
  292.         getsym();
  293.         return head;
  294. }
  295.  
  296. struct snode    *labelstmt()
  297. /*
  298.  *      labelstmt processes a label that appears before a
  299.  *      statement as a seperate statement.
  300.  */
  301. {       struct snode    *snp;
  302.         SYM             *sp;
  303.         snp = xalloc(sizeof(struct snode));
  304.         snp->stype = st_label;
  305.         if( (sp = search(lastid,lsyms.head)) == 0 ) {
  306.                 sp = xalloc(sizeof(SYM));
  307.                 sp->name = litlate(lastid);
  308.                 sp->storage_class = sc_label;
  309.                 sp->tp = 0;
  310.                 sp->value.i = nextlabel++;
  311.                 insert(sp,&lsyms);
  312.                 }
  313.         else    {
  314.                 if( sp->storage_class != sc_ulabel )
  315.                         error(ERR_LABEL);
  316.                 else
  317.                         sp->storage_class = sc_label;
  318.                 }
  319.         getsym();       /* get past id */
  320.         needpunc(colon);
  321.         if( sp->storage_class == sc_label ) {
  322.                 snp->label = sp->value.i;
  323.                 snp->next = 0;
  324.                 return snp;
  325.                 }
  326.         return 0;
  327. }
  328.  
  329. struct snode    *gotostmt()
  330. /*
  331.  *      gotostmt processes the goto statement and puts undefined
  332.  *      labels into the symbol table.
  333.  */
  334. {       struct snode    *snp;
  335.         SYM             *sp;
  336.         getsym();
  337.         if( lastst != id ) {
  338.                 error(ERR_IDEXPECT);
  339.                 return 0;
  340.                 }
  341.         snp = xalloc(sizeof(struct snode));
  342.         if( (sp = search(lastid,lsyms.head)) == 0 ) {
  343.                 sp = xalloc(sizeof(SYM));
  344.                 sp->name = litlate(lastid);
  345.                 sp->value.i = nextlabel++;
  346.                 sp->storage_class = sc_ulabel;
  347.                 sp->tp = 0;
  348.                 insert(sp,&lsyms);
  349.                 }
  350.         getsym();       /* get past label name */
  351.         if( lastst != end )
  352.                 needpunc( semicolon );
  353.         if( sp->storage_class != sc_label && sp->storage_class != sc_ulabel)
  354.                 error( ERR_LABEL );
  355.         else    {
  356.                 snp->stype = st_goto;
  357.                 snp->label = sp->value.i;
  358.                 snp->next = 0;
  359.                 return snp;
  360.                 }
  361.         return 0;
  362. }
  363.  
  364. struct snode    *statement()
  365. /*
  366.  *      statement figures out which of the statement processors
  367.  *      should be called and transfers control to the proper
  368.  *      routine.
  369.  */
  370. {       struct snode    *snp;
  371.         switch( lastst ) {
  372.                 case semicolon:
  373.                         getsym();
  374.                         snp = 0;
  375.                         break;
  376.                 case begin:
  377.                         getsym();
  378.                         snp = compound();
  379.                         return snp;
  380.                 case kw_if:
  381.                         snp = ifstmt();
  382.                         break;
  383.                 case kw_while:
  384.                         snp = whilestmt();
  385.                         break;
  386.                 case kw_for:
  387.                         snp = forstmt();
  388.                         break;
  389.                 case kw_return:
  390.                         snp = retstmt();
  391.                         break;
  392.                 case kw_break:
  393.                         snp = breakstmt();
  394.                         break;
  395.                 case kw_goto:
  396.                         snp = gotostmt();
  397.                         break;
  398.                 case kw_continue:
  399.                         snp = contstmt();
  400.                         break;
  401.                 case kw_do:
  402.                         snp = dostmt();
  403.                         break;
  404.                 case kw_switch:
  405.                         snp = switchstmt();
  406.                         break;
  407.                 case id:
  408.                         while( isspace(lastch) )
  409.                                 getch();
  410.                         if( lastch == ':' )
  411.                                 return labelstmt();
  412.                         /* else fall through to process expression */
  413.                 default:
  414.                         snp = exprstmt();
  415.                         break;
  416.                 }
  417.         if( snp != 0 )
  418.                 snp->next = 0;
  419.         return snp;
  420. }
  421.  
  422.