home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 109.lha / PD_C / src / Stmt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-20  |  12.4 KB  |  426 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. extern long    intexpr();
  26. extern char    *litlate();  
  27. extern SYM    *search();
  28.  
  29. /* 
  30.  *      the statement module handles all of the possible c statements 
  31.  *      and builds a parse tree of the statements. 
  32.  * 
  33.  *      each routine returns a pointer to a statement parse node which 
  34.  *      reflects the statement just parsed. 
  35.  */ 
  36.   
  37. struct snode    *statement();   /* forward declaration */ 
  38.   
  39. struct snode    *whilestmt() 
  40. /* 
  41.  *      whilestmt parses the c while statement. 
  42.  */ 
  43. {       struct snode    *snp; 
  44.         snp = xalloc(sizeof(struct snode)); 
  45.         snp->stype = st_while; 
  46.         getsym(); 
  47.         if( lastst != openpa ) 
  48.                 error(ERR_EXPREXPECT); 
  49.         else    { 
  50.                 getsym(); 
  51.                 if( expression(&(snp->exp)) == 0 ) 
  52.                         error(ERR_EXPREXPECT); 
  53.                 needpunc( closepa ); 
  54.                 snp->s1 = statement(); 
  55.                 } 
  56.         return snp; 
  57.   
  58. struct snode    *dostmt() 
  59. /* 
  60.  *      dostmt parses the c do-while construct. 
  61.  */ 
  62. {       struct snode    *snp; 
  63.         snp = xalloc(sizeof(struct snode)); 
  64.         snp->stype = st_do; 
  65.         getsym(); 
  66.         snp->s1 = statement(); 
  67.         if( lastst != kw_while ) 
  68.                 error(ERR_WHILEXPECT); 
  69.         else    { 
  70.                 getsym(); 
  71.                 if( lastst != openpa ) 
  72.                         error(ERR_EXPREXPECT); 
  73.                 else    { 
  74.                         getsym(); 
  75.                         if( expression(&(snp->exp)) == 0 ) 
  76.                                 error(ERR_EXPREXPECT); 
  77.                         needpunc(closepa); 
  78.                         } 
  79.                 if( lastst != end )
  80.                         needpunc( semicolon );
  81.                 } 
  82.         return snp; 
  83.   
  84. struct snode    *forstmt() 
  85. {       struct snode    *snp; 
  86.         snp = xalloc(sizeof(struct snode)); 
  87.         getsym(); 
  88.         needpunc(openpa); 
  89.         if( expression(&(snp->label)) == 0 ) 
  90.                 snp->label = 0; 
  91.         needpunc(semicolon); 
  92.         snp->stype = st_for; 
  93.         if( expression(&(snp->exp)) == 0 ) 
  94.                 snp->exp = 0; 
  95.         needpunc(semicolon); 
  96.         if( expression(&(snp->s2)) == 0 ) 
  97.                 snp->s2 = 0; 
  98.         needpunc(closepa); 
  99.         snp->s1 = statement(); 
  100.         return snp; 
  101.   
  102. struct snode    *ifstmt() 
  103. /* 
  104.  *      ifstmt parses the c if statement and an else clause if 
  105.  *      one is present. 
  106.  */ 
  107. {       struct snode    *snp; 
  108.         snp = xalloc(sizeof(struct snode)); 
  109.         snp->stype = st_if; 
  110.         getsym(); 
  111.         if( lastst != openpa ) 
  112.                 error(ERR_EXPREXPECT); 
  113.         else    { 
  114.                 getsym(); 
  115.                 if( expression(&(snp->exp)) == 0 ) 
  116.                         error(ERR_EXPREXPECT); 
  117.                 needpunc( closepa ); 
  118.                 snp->s1 = statement(); 
  119.                 if( lastst == kw_else ) { 
  120.                         getsym(); 
  121.                         snp->s2 = statement(); 
  122.                         } 
  123.                 else 
  124.                         snp->s2 = 0; 
  125.                 } 
  126.         return snp; 
  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 = (struct snode *)0;
  140.                 snp->stype = st_case;
  141.                 snp->label = intexpr(); 
  142.                 } 
  143.         else if( lastst == kw_default) { 
  144.                 getsym(); 
  145.                 snp->s2 = (struct snode *)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. int     checkcases(head) 
  169. /* 
  170.  *      checkcases will check to see if any duplicate cases 
  171.  *      exist in the case list pointed to by head. 
  172.  */ 
  173. struct snode    *head; 
  174. {     
  175.    struct snode*top, *cur;
  176.    cur = top = head;
  177.    while( top != 0 )
  178.      {
  179.     cur = top->next;
  180.     while( cur != 0 )
  181.       {
  182.         if( (!(cur->s1 || cur->s2) && cur->label == top->label)
  183.         || (cur->s2 && top->s2) )
  184.           {
  185.         printf(" duplicate case label %ld\n",cur->label);
  186.         return 1;
  187.           }
  188.         cur = cur->next;
  189.       }
  190.     top = top->next;
  191.      }
  192.    return 0;
  193.   
  194. struct snode    *switchstmt() 
  195. {       struct snode    *snp; 
  196.         struct snode    *head, *tail; 
  197.         snp = xalloc(sizeof(struct snode)); 
  198.         snp->stype = st_switch; 
  199.         getsym(); 
  200.         needpunc(openpa); 
  201.         if( expression(&(snp->exp)) == 0 ) 
  202.                 error(ERR_EXPREXPECT); 
  203.         needpunc(closepa); 
  204.         needpunc(begin); 
  205.         head = 0; 
  206.         while( lastst != end ) { 
  207.                 if( head == 0 ) 
  208.                         head = tail = casestmt(); 
  209.                 else    { 
  210.                         tail->next = casestmt(); 
  211.                         if( tail->next != 0 ) 
  212.                                 tail = tail->next; 
  213.                         } 
  214.                 tail->next = 0; 
  215.                 } 
  216.         snp->s1 = head; 
  217.         getsym(); 
  218.         if( checkcases(head) ) 
  219.                 error(ERR_DUPCASE); 
  220.         return snp; 
  221.   
  222. struct snode    *retstmt() 
  223. {       struct snode    *snp; 
  224.         snp = xalloc(sizeof(struct snode)); 
  225.         snp->stype = st_return; 
  226.         getsym(); 
  227.         expression(&(snp->exp));
  228.         if( lastst != end )
  229.                 needpunc( semicolon );
  230.         return snp; 
  231.   
  232. struct snode    *breakstmt() 
  233. {       struct snode    *snp; 
  234.         snp = xalloc(sizeof(struct snode)); 
  235.         snp->stype = st_break; 
  236.         getsym(); 
  237.         if( lastst != end )
  238.                 needpunc( semicolon );
  239.         return snp; 
  240.   
  241. struct snode    *contstmt() 
  242. {       struct snode    *snp; 
  243.         snp = xalloc(sizeof(struct snode)); 
  244.         snp->stype = st_continue; 
  245.         getsym();
  246.         if( lastst != end )
  247.                 needpunc( semicolon );
  248.         return snp;
  249.   
  250. struct snode    *exprstmt() 
  251. /* 
  252.  *      exprstmt is called whenever a statement does not begin 
  253.  *      with a keyword. the statement should be an expression. 
  254.  */ 
  255. {       struct snode    *snp; 
  256.         snp = xalloc(sizeof(struct snode)); 
  257.         snp->stype = st_expr; 
  258.         if( expression(&(snp->exp)) == 0 ) { 
  259.                 error(ERR_EXPREXPECT); 
  260.                 getsym(); 
  261.                 } 
  262.         if( lastst != end )
  263.                 needpunc( semicolon );
  264.         return snp; 
  265.   
  266. struct snode    *compound() 
  267. /* 
  268.  *      compound processes a block of statements and forms a linked 
  269.  *      list of the statements within the block. 
  270.  * 
  271.  *      compound expects the input pointer to already be past the 
  272.  *      begin symbol of the block. 
  273.  */ 
  274. {       struct snode    *head, *tail; 
  275.         head = 0; 
  276.         while( lastst != end ) { 
  277.                 if( head == 0 ) 
  278.                         head = tail = statement(); 
  279.                 else    { 
  280.                         tail->next = statement(); 
  281.                         if( tail->next != 0 ) 
  282.                                 tail = tail->next; 
  283.                         } 
  284.                 } 
  285.         getsym(); 
  286.         return head; 
  287.   
  288. struct snode    *labelstmt() 
  289. /* 
  290.  *      labelstmt processes a label that appears before a 
  291.  *      statement as a seperate statement. 
  292.  */ 
  293. {       struct snode    *snp; 
  294.         SYM             *sp; 
  295.         snp = xalloc(sizeof(struct snode)); 
  296.         snp->stype = st_label; 
  297.         if( (sp = search(lastid,lsyms.head)) == 0 ) { 
  298.                 sp = xalloc(sizeof(SYM)); 
  299.                 sp->name = litlate(lastid); 
  300.                 sp->storage_class = sc_label; 
  301.                 sp->tp = 0; 
  302.                 sp->value.i = nextlabel++; 
  303.                 insert(sp,&lsyms); 
  304.                 } 
  305.         else    { 
  306.                 if( sp->storage_class != sc_ulabel ) 
  307.                         error(ERR_LABEL); 
  308.                 else 
  309.                         sp->storage_class = sc_label; 
  310.                 } 
  311.         getsym();       /* get past id */ 
  312.         needpunc(colon); 
  313.         if( sp->storage_class == sc_label ) { 
  314.                 snp->label = (void *)sp->value.i; 
  315.                 snp->next = 0; 
  316.                 return snp; 
  317.                 } 
  318.         return 0; 
  319.   
  320. struct snode    *gotostmt() 
  321. /* 
  322.  *      gotostmt processes the goto statement and puts undefined 
  323.  *      labels into the symbol table. 
  324.  */ 
  325. {       struct snode    *snp; 
  326.         SYM             *sp; 
  327.         getsym(); 
  328.         if( lastst != id ) { 
  329.                 error(ERR_IDEXPECT); 
  330.                 return 0; 
  331.                 } 
  332.         snp = xalloc(sizeof(struct snode)); 
  333.         if( (sp = search(lastid,lsyms.head)) == 0 ) { 
  334.                 sp = xalloc(sizeof(SYM)); 
  335.                 sp->name = litlate(lastid); 
  336.                 sp->value.i = nextlabel++; 
  337.                 sp->storage_class = sc_ulabel; 
  338.                 sp->tp = 0; 
  339.                 insert(sp,&lsyms); 
  340.                 } 
  341.         getsym();       /* get past label name */ 
  342.         if( lastst != end )
  343.                 needpunc( semicolon );
  344.         if( sp->storage_class != sc_label && sp->storage_class != sc_ulabel) 
  345.                 error( ERR_LABEL ); 
  346.         else    { 
  347.                 snp->stype = st_goto; 
  348.                 snp->label = (void *)(sp->value.i); 
  349.                 snp->next = 0; 
  350.                 return snp; 
  351.                 } 
  352.         return 0; 
  353.   
  354. struct snode    *statement() 
  355. /* 
  356.  *      statement figures out which of the statement processors 
  357.  *      should be called and transfers control to the proper 
  358.  *      routine. 
  359.  */ 
  360. {       struct snode    *snp; 
  361.         switch( lastst ) { 
  362.                 case semicolon: 
  363.                         getsym(); 
  364.                         snp = 0; 
  365.                         break; 
  366.                 case begin: 
  367.                         getsym(); 
  368.                         snp = compound(); 
  369.                         return snp; 
  370.                 case kw_if: 
  371.                         snp = ifstmt(); 
  372.                         break; 
  373.                 case kw_while: 
  374.                         snp = whilestmt(); 
  375.                         break; 
  376.                 case kw_for: 
  377.                         snp = forstmt(); 
  378.                         break; 
  379.                 case kw_return: 
  380.                         snp = retstmt(); 
  381.                         break; 
  382.                 case kw_break: 
  383.                         snp = breakstmt(); 
  384.                         break; 
  385.                 case kw_goto: 
  386.                         snp = gotostmt(); 
  387.                         break; 
  388.                 case kw_continue: 
  389.                         snp = contstmt(); 
  390.                         break; 
  391.                 case kw_do: 
  392.                         snp = dostmt(); 
  393.                         break; 
  394.                 case kw_switch: 
  395.                         snp = switchstmt(); 
  396.                         break; 
  397.                 case id: 
  398.                         while( isspace(lastch) ) 
  399.                                 getch(); 
  400.                         if( lastch == ':' ) 
  401.                                 return labelstmt(); 
  402.                         /* else fall through to process expression */ 
  403.                 default: 
  404.                         snp = exprstmt(); 
  405.                         break; 
  406.                 } 
  407.         if( snp != 0 ) 
  408.                 snp->next = 0; 
  409.         return snp; 
  410.  
  411.