home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / mip / cgram.y < prev    next >
Encoding:
Text File  |  1979-01-10  |  19.0 KB  |  925 lines

  1. %term NAME  2
  2. %term STRING  3
  3. %term ICON  4
  4. %term FCON  5
  5. %term PLUS   6
  6. %term MINUS   8
  7. %term MUL   11
  8. %term AND   14
  9. %term OR   17
  10. %term ER   19
  11. %term QUEST  21
  12. %term COLON  22
  13. %term ANDAND  23
  14. %term OROR  24
  15.  
  16. /*    special interfaces for yacc alone */
  17. /*    These serve as abbreviations of 2 or more ops:
  18.     ASOP    =, = ops
  19.     RELOP    LE,LT,GE,GT
  20.     EQUOP    EQ,NE
  21.     DIVOP    DIV,MOD
  22.     SHIFTOP    LS,RS
  23.     ICOP    ICR,DECR
  24.     UNOP    NOT,COMPL
  25.     STROP    DOT,STREF
  26.  
  27.     */
  28. %term ASOP  25
  29. %term RELOP  26
  30. %term EQUOP  27
  31. %term DIVOP  28
  32. %term SHIFTOP  29
  33. %term INCOP  30
  34. %term UNOP  31
  35. %term STROP  32
  36.  
  37. /*    reserved words, etc */
  38. %term TYPE  33
  39. %term CLASS  34
  40. %term STRUCT  35
  41. %term RETURN  36
  42. %term GOTO  37
  43. %term IF  38
  44. %term ELSE  39
  45. %term SWITCH  40
  46. %term BREAK  41
  47. %term CONTINUE  42
  48. %term WHILE  43
  49. %term DO  44
  50. %term FOR  45
  51. %term DEFAULT  46
  52. %term CASE  47
  53. %term SIZEOF  48
  54. %term ENUM 49
  55.  
  56.  
  57. /*    little symbols, etc. */
  58. /*    namely,
  59.  
  60.     LP    (
  61.     RP    )
  62.  
  63.     LC    {
  64.     RC    }
  65.  
  66.     LB    [
  67.     RB    ]
  68.  
  69.     CM    ,
  70.     SM    ;
  71.  
  72.     */
  73.  
  74. %term LP  50
  75. %term RP  51
  76. %term LC  52
  77. %term RC  53
  78. %term LB  54
  79. %term RB  55
  80. %term CM  56
  81. %term SM  57
  82. %term ASSIGN  58
  83.  
  84. /* at last count, there were 7 shift/reduce, 1 reduce/reduce conflicts
  85. /* these involved:
  86.     if/else
  87.     recognizing functions in various contexts, including declarations
  88.     error recovery
  89.     */
  90.  
  91. %left CM
  92. %right ASOP ASSIGN
  93. %right QUEST COLON
  94. %left OROR
  95. %left ANDAND
  96. %left OR
  97. %left ER
  98. %left AND
  99. %left EQUOP
  100. %left RELOP
  101. %left SHIFTOP
  102. %left PLUS MINUS
  103. %left MUL DIVOP
  104. %right UNOP
  105. %right INCOP SIZEOF
  106. %left LB LP STROP
  107. %{
  108. # include "mfile1"
  109. %}
  110.  
  111.     /* define types */
  112. %start ext_def_list
  113.  
  114. %type <intval> con_e ifelprefix ifprefix whprefix forprefix doprefix switchpart
  115.         enum_head str_head name_lp
  116. %type <nodep> e .e term attributes oattributes type enum_dcl struct_dcl
  117.         cast_type null_decl funct_idn declarator fdeclarator nfdeclarator
  118.         elist
  119.  
  120. %token <intval> CLASS NAME STRUCT RELOP CM DIVOP PLUS MINUS SHIFTOP MUL AND OR ER ANDAND OROR
  121.         ASSIGN STROP INCOP UNOP ICON
  122. %token <nodep> TYPE
  123.  
  124. %%
  125.  
  126. %{
  127.     static int fake = 0;
  128.     static char fakename[NCHNAM+1];
  129. %}
  130.  
  131. ext_def_list:       ext_def_list external_def
  132.         |
  133.             =ftnend();
  134.         ;
  135. external_def:       data_def
  136.             ={ curclass = SNULL;  blevel = 0; }
  137.         |  error
  138.             ={ curclass = SNULL;  blevel = 0; }
  139.         ;
  140. data_def:
  141.            oattributes  SM
  142.             ={  $1->op = FREE; }
  143.         |  oattributes init_dcl_list  SM
  144.             ={  $1->op = FREE; }
  145.         |  oattributes fdeclarator {
  146.                 defid( tymerge($1,$2), curclass==STATIC?STATIC:EXTDEF );
  147.                 }  function_body
  148.             ={  
  149.                 if( blevel ) cerror( "function level error" );
  150.                 if( reached ) retstat |= NRETVAL; 
  151.                 $1->op = FREE;
  152.                 ftnend();
  153.                 }
  154.         ;
  155.  
  156. function_body:       arg_dcl_list compoundstmt
  157.         ;
  158. arg_dcl_list:       arg_dcl_list declaration
  159.         |     ={  blevel = 1; }
  160.         ;
  161.  
  162. stmt_list:       stmt_list statement
  163.         |  /* empty */
  164.             ={  bccode();
  165.                 locctr(PROG);
  166.                 }
  167.         ;
  168.  
  169. dcl_stat_list    :  dcl_stat_list attributes SM
  170.             ={  $2->op = FREE; }
  171.         |  dcl_stat_list attributes init_dcl_list SM
  172.             ={  $2->op = FREE; }
  173.         |  /* empty */
  174.         ;
  175. declaration:       attributes declarator_list  SM
  176.             ={ curclass = SNULL;  $1->op = FREE; }
  177.         |  attributes SM
  178.             ={ curclass = SNULL;  $1->op = FREE; }
  179.         |  error  SM
  180.             ={  curclass = SNULL; }
  181.         ;
  182. oattributes:      attributes
  183.         |  /* VOID */
  184.             ={  $$ = mkty(INT,0,INT);  curclass = SNULL; }
  185.         ;
  186. attributes:       class type
  187.             ={  $$ = $2; }
  188.         |  type class
  189.         |  class
  190.             ={  $$ = mkty(INT,0,INT); }
  191.         |  type
  192.             ={ curclass = SNULL ; }
  193.         ;
  194.  
  195.  
  196. class:          CLASS
  197.             ={  curclass = $1; }
  198.         ;
  199.  
  200. type:           TYPE
  201.         |  TYPE TYPE
  202.             ={  $1->type = types( $1->type, $2->type, UNDEF );
  203.                 $2->op = FREE;
  204.                 }
  205.         |  TYPE TYPE TYPE
  206.             ={  $1->type = types( $1->type, $2->type, $3->type );
  207.                 $2->op = $3->op = FREE;
  208.                 }
  209.         |  struct_dcl
  210.         |  enum_dcl
  211.         ;
  212.  
  213. enum_dcl:       enum_head LC moe_list optcomma RC
  214.             ={ $$ = dclstruct($1); }
  215.         |  ENUM NAME
  216.             ={  $$ = rstruct($2,0);  stwart = instruct; }
  217.         ;
  218.  
  219. enum_head:       ENUM
  220.             ={  $$ = bstruct(-1,0); }
  221.         |  ENUM NAME
  222.             ={  $$ = bstruct($2,0); }
  223.         ;
  224.  
  225. moe_list:       moe
  226.         |  moe_list CM moe
  227.         ;
  228.  
  229. moe:           NAME
  230.             ={  moedef( $1 ); }
  231.         |  NAME ASSIGN con_e
  232.             ={  strucoff = $3;  moedef( $1 ); }
  233.         ;
  234.  
  235. struct_dcl:       str_head LC type_dcl_list optsemi RC
  236.             ={ $$ = dclstruct($1);  }
  237.         |  STRUCT NAME
  238.             ={  $$ = rstruct($2,$1); }
  239.         ;
  240.  
  241. str_head:       STRUCT
  242.             ={  $$ = bstruct(-1,$1);  stwart=0; }
  243.         |  STRUCT NAME
  244.             ={  $$ = bstruct($2,$1);  stwart=0;  }
  245.         ;
  246.  
  247. type_dcl_list:       type_declaration
  248.         |  type_dcl_list SM type_declaration
  249.         ;
  250.  
  251. type_declaration:  type declarator_list
  252.             ={ curclass = SNULL;  stwart=0; $1->op = FREE; }
  253.         |  type
  254.             ={  if( curclass != MOU ){
  255.                 curclass = SNULL;
  256.                 }
  257.                 else {
  258.                 sprintf( fakename, "$%dFAKE", fake++ );
  259.                 defid( tymerge($1, bdty(NAME,NIL,lookup( fakename, SMOS ))), curclass );
  260.                 }
  261.                 stwart = 0;
  262.                 $1->op = FREE;
  263.                 }
  264.         ;
  265.  
  266.  
  267. declarator_list:   declarator
  268.             ={ defid( tymerge($<nodep>0,$1), curclass);  stwart = instruct; }
  269.         |  declarator_list  CM {$<nodep>$=$<nodep>0;}  declarator
  270.             ={ defid( tymerge($<nodep>0,$4), curclass);  stwart = instruct; }
  271.         ;
  272. declarator:       fdeclarator
  273.         |  nfdeclarator
  274.         |  nfdeclarator COLON con_e
  275.             %prec CM
  276.             ={  if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" );
  277.                 if( $3<0 || $3 >= FIELD ){
  278.                 uerror( "illegal field size" );
  279.                 $3 = 1;
  280.                 }
  281.                 defid( tymerge($<nodep>0,$1), FIELD|$3 );
  282.                 $$ = NIL;
  283.                 }
  284.         |  COLON con_e
  285.             %prec CM
  286.             ={  if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" );
  287.                 falloc( stab, $2, -1, $<nodep>0 );  /* alignment or hole */
  288.                 $$ = NIL;
  289.                 }
  290.         |  error
  291.             ={  $$ = NIL; }
  292.         ;
  293.  
  294.         /* int (a)();   is not a function --- sorry! */
  295. nfdeclarator:       MUL nfdeclarator        
  296.             ={  umul:
  297.                 $$ = bdty( UNARY MUL, $2, 0 ); }
  298.         |  nfdeclarator  LP   RP        
  299.             ={  uftn:
  300.                 $$ = bdty( UNARY CALL, $1, 0 );  }
  301.         |  nfdeclarator LB RB        
  302.             ={  uary:
  303.                 $$ = bdty( LB, $1, 0 );  }
  304.         |  nfdeclarator LB con_e RB    
  305.             ={  bary:
  306.                 if( (int)$3 <= 0 ) werror( "zero or negative subscript" );
  307.                 $$ = bdty( LB, $1, $3 );  }
  308.         |  NAME          
  309.             ={  $$ = bdty( NAME, NIL, $1 );  }
  310.         |   LP  nfdeclarator  RP         
  311.             ={ $$=$2; }
  312.         ;
  313. fdeclarator:       MUL fdeclarator
  314.             ={  goto umul; }
  315.         |  fdeclarator  LP   RP
  316.             ={  goto uftn; }
  317.         |  fdeclarator LB RB
  318.             ={  goto uary; }
  319.         |  fdeclarator LB con_e RB
  320.             ={  goto bary; }
  321.         |   LP  fdeclarator  RP
  322.             ={ $$ = $2; }
  323.         |  name_lp  name_list  RP
  324.             ={
  325.                 if( blevel!=0 ) uerror("function declaration in bad context");
  326.                 $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 );
  327.                 stwart = 0;
  328.                 }
  329.         |  name_lp RP
  330.             ={
  331.                 $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 );
  332.                 stwart = 0;
  333.                 }
  334.         ;
  335.  
  336. name_lp:      NAME LP
  337.             ={
  338.                 /* turn off typedefs for argument names */
  339.                 stwart = SEENAME;
  340.                 }
  341.         ;
  342.  
  343. name_list:       NAME            
  344.             ={ ftnarg( $1 );  stwart = SEENAME; }
  345.         |  name_list  CM  NAME 
  346.             ={ ftnarg( $3 );  stwart = SEENAME; }
  347.         ;
  348.         /* always preceeded by attributes: thus the $<nodep>0's */
  349. init_dcl_list:       init_declarator
  350.             %prec CM
  351.         |  init_dcl_list  CM {$<nodep>$=$<nodep>0;}  init_declarator
  352.         ;
  353.         /* always preceeded by attributes */
  354. xnfdeclarator:       nfdeclarator
  355.             ={  defid( $1 = tymerge($<nodep>0,$1), curclass);
  356.                 beginit($1->rval);
  357.                 }
  358.         |  error
  359.         ;
  360.         /* always preceeded by attributes */
  361. init_declarator:   nfdeclarator
  362.             ={  nidcl( tymerge($<nodep>0,$1) ); }
  363.         |  fdeclarator
  364.             ={  defid( tymerge($<nodep>0,$1), uclass(curclass) );
  365.             }
  366.         |  xnfdeclarator optasgn e
  367.             %prec CM
  368.             ={  doinit( $3 );
  369.                 endinit(); }
  370.         |  xnfdeclarator optasgn LC init_list optcomma RC
  371.             ={  endinit(); }
  372.         ;
  373.  
  374. init_list:       initializer
  375.             %prec CM
  376.         |  init_list  CM  initializer
  377.         ;
  378. initializer:       e
  379.             %prec CM
  380.             ={  doinit( $1 ); }
  381.         |  ibrace init_list optcomma RC
  382.             ={  irbrace(); }
  383.         ;
  384.  
  385. optcomma    :    /* VOID */
  386.         |  CM
  387.         ;
  388.  
  389. optsemi        :    /* VOID */
  390.         |  SM
  391.         ;
  392.  
  393. optasgn        :    /* VOID */
  394.             ={  werror( "old-fashioned initialization: use =" ); }
  395.         |  ASSIGN
  396.         ;
  397.  
  398. ibrace        : LC
  399.             ={  ilbrace(); }
  400.         ;
  401.  
  402. /*    STATEMENTS    */
  403.  
  404. compoundstmt:       begin dcl_stat_list stmt_list RC
  405.             ={  --blevel;
  406.                 if( blevel == 1 ) blevel = 0;
  407.                 clearst( blevel );
  408.                 checkst( blevel );
  409.                 autooff = *--psavbc;
  410.                 regvar = *--psavbc;
  411.                 }
  412.         ;
  413.  
  414. begin:          LC
  415.             ={  if( blevel == 1 ) dclargs();
  416.                 ++blevel;
  417.                 if( psavbc > &asavbc[BCSZ-2] ) cerror( "nesting too deep" );
  418.                 *psavbc++ = regvar;
  419.                 *psavbc++ = autooff;
  420.                 }
  421.         ;
  422.  
  423. statement:       e   SM
  424.             ={ ecomp( $1 ); }
  425.         |  compoundstmt
  426.         |  ifprefix statement
  427.             ={ deflab($1);
  428.                reached = 1;
  429.                }
  430.         |  ifelprefix statement
  431.             ={  if( $1 != NOLAB ){
  432.                 deflab( $1 );
  433.                 reached = 1;
  434.                 }
  435.                 }
  436.         |  whprefix statement
  437.             ={  branch(  contlab );
  438.                 deflab( brklab );
  439.                 if( (flostat&FBRK) || !(flostat&FLOOP)) reached = 1;
  440.                 else reached = 0;
  441.                 resetbc(0);
  442.                 }
  443.         |  doprefix statement WHILE  LP  e  RP   SM
  444.             ={  deflab( contlab );
  445.                 if( flostat & FCONT ) reached = 1;
  446.                 ecomp( buildtree( CBRANCH, buildtree( NOT, $5, NIL ), bcon( $1 ) ) );
  447.                 deflab( brklab );
  448.                 reached = 1;
  449.                 resetbc(0);
  450.                 }
  451.         |  forprefix .e RP statement
  452.             ={  deflab( contlab );
  453.                 if( flostat&FCONT ) reached = 1;
  454.                 if( $2 ) ecomp( $2 );
  455.                 branch( $1 );
  456.                 deflab( brklab );
  457.                 if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1;
  458.                 else reached = 0;
  459.                 resetbc(0);
  460.                 }
  461.         | switchpart statement
  462.             ={  if( reached ) branch( brklab );
  463.                 deflab( $1 );
  464.                swend();
  465.                 deflab(brklab);
  466.                 if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1;
  467.                 resetbc(FCONT);
  468.                 }
  469.         |  BREAK  SM
  470.             ={  if( brklab == NOLAB ) uerror( "illegal break");
  471.                 else if(reached) branch( brklab );
  472.                 flostat |= FBRK;
  473.                 if( brkflag ) goto rch;
  474.                 reached = 0;
  475.                 }
  476.         |  CONTINUE  SM
  477.             ={  if( contlab == NOLAB ) uerror( "illegal continue");
  478.                 else branch( contlab );
  479.                 flostat |= FCONT;
  480.                 goto rch;
  481.                 }
  482.         |  RETURN  SM
  483.             ={  retstat |= NRETVAL;
  484.                 branch( retlab );
  485.             rch:
  486.                 if( !reached ) werror( "statement not reached");
  487.                 reached = 0;
  488.                 }
  489.         |  RETURN e  SM
  490.             ={  register NODE *temp;
  491.                 idname = curftn;
  492.                 temp = buildtree( NAME, NIL, NIL );
  493.                 temp->type = DECREF( temp->type );
  494.                 temp = buildtree( RETURN, temp, $2 );
  495.                 /* now, we have the type of the RHS correct */
  496.                 temp->left->op = FREE;
  497.                 temp->op = FREE;
  498.                 ecomp( buildtree( FORCE, temp->right, NIL ) );
  499.                 retstat |= RETVAL;
  500.                 branch( retlab );
  501.                 reached = 0;
  502.                 }
  503.         |  GOTO NAME SM
  504.             ={  register NODE *q;
  505.                 q = block( FREE, NIL, NIL, INT|ARY, 0, INT );
  506.                 q->rval = idname = $2;
  507.                 defid( q, ULABEL );
  508.                 stab[idname].suse = -lineno;
  509.                 branch( stab[idname].offset );
  510.                 goto rch;
  511.                 }
  512.         |   SM
  513.         |  error  SM
  514.         |  error RC
  515.         |  label statement
  516.         ;
  517. label:           NAME COLON
  518.             ={  register NODE *q;
  519.                 q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL );
  520.                 q->rval = $1;
  521.                 defid( q, LABEL );
  522.                 reached = 1;
  523.                 }
  524.         |  CASE e COLON
  525.             ={  addcase($2);
  526.                 reached = 1;
  527.                 }
  528.         |  DEFAULT COLON
  529.             ={  reached = 1;
  530.                 adddef();
  531.                 flostat |= FDEF;
  532.                 }
  533.         ;
  534. doprefix:    DO
  535.             ={  savebc();
  536.                 if( !reached ) werror( "loop not entered at top");
  537.                 brklab = getlab();
  538.                 contlab = getlab();
  539.                 deflab( $$ = getlab() );
  540.                 reached = 1;
  541.                 }
  542.         ;
  543. ifprefix:    IF LP e RP
  544.             ={  ecomp( buildtree( CBRANCH, $3, bcon( $$=getlab()) ) ) ;
  545.                 reached = 1;
  546.                 }
  547.         ;
  548. ifelprefix:      ifprefix statement ELSE
  549.             ={  if( reached ) branch( $$ = getlab() );
  550.                 else $$ = NOLAB;
  551.                 deflab( $1 );
  552.                 reached = 1;
  553.                 }
  554.         ;
  555.  
  556. whprefix:      WHILE  LP  e  RP
  557.             ={  savebc();
  558.                 if( !reached ) werror( "loop not entered at top");
  559.                 if( $3->op == ICON && $3->lval != 0 ) flostat = FLOOP;
  560.                 deflab( contlab = getlab() );
  561.                 reached = 1;
  562.                 brklab = getlab();
  563.                 if( flostat == FLOOP ) tfree( $3 );
  564.                 else ecomp( buildtree( CBRANCH, $3, bcon( brklab) ) );
  565.                 }
  566.         ;
  567. forprefix:      FOR  LP  .e  SM .e  SM 
  568.             ={  if( $3 ) ecomp( $3 );
  569.                 else if( !reached ) werror( "loop not entered at top");
  570.                 savebc();
  571.                 contlab = getlab();
  572.                 brklab = getlab();
  573.                 deflab( $$ = getlab() );
  574.                 reached = 1;
  575.                 if( $5 ) ecomp( buildtree( CBRANCH, $5, bcon( brklab) ) );
  576.                 else flostat |= FLOOP;
  577.                 }
  578.         ;
  579. switchpart:       SWITCH  LP  e  RP
  580.             ={  savebc();
  581.                 brklab = getlab();
  582.                 ecomp( buildtree( FORCE, $3, NIL ) );
  583.                 branch( $$ = getlab() );
  584.                 swstart();
  585.                 reached = 0;
  586.                 }
  587.         ;
  588. /*    EXPRESSIONS    */
  589. con_e:           { $<intval>$=instruct; stwart=instruct=0; } e
  590.             %prec CM
  591.             ={  $$ = icons( $2 );  instruct=$<intval>1; }
  592.         ;
  593. .e:           e
  594.         |
  595.             ={ $$=0; }
  596.         ;
  597. elist:           e
  598.             %prec CM
  599.         |  elist  CM  e
  600.             ={  goto bop; }
  601.         ;
  602.  
  603. e:           e RELOP e
  604.             ={
  605.             preconf:
  606.                 if( yychar==RELOP||yychar==EQUOP||yychar==AND||yychar==OR||yychar==ER ){
  607.                 precplaint:
  608.                 if( hflag ) werror( "precedence confusion possible: parenthesize!" );
  609.                 }
  610.             bop:
  611.                 $$ = buildtree( $2, $1, $3 );
  612.                 }
  613.         |  e CM e
  614.             ={  $2 = COMOP;
  615.                 goto bop;
  616.                 }
  617.         |  e DIVOP e
  618.             ={  goto bop; }
  619.         |  e PLUS e
  620.             ={  if(yychar==SHIFTOP) goto precplaint; else goto bop; }
  621.         |  e MINUS e
  622.             ={  if(yychar==SHIFTOP ) goto precplaint; else goto bop; }
  623.         |  e SHIFTOP e
  624.             ={  if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; }
  625.         |  e MUL e
  626.             ={  goto bop; }
  627.         |  e EQUOP  e
  628.             ={  goto preconf; }
  629.         |  e AND e
  630.             ={  if( yychar==RELOP||yychar==EQUOP ) goto preconf;  else goto bop; }
  631.         |  e OR e
  632.             ={  if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; }
  633.         |  e ER e
  634.             ={  if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; }
  635.         |  e ANDAND e
  636.             ={  goto bop; }
  637.         |  e OROR e
  638.             ={  goto bop; }
  639.         |  e MUL ASSIGN e
  640.             ={  abop:
  641.                 $$ = buildtree( ASG $2, $1, $4 );
  642.                 }
  643.         |  e DIVOP ASSIGN e
  644.             ={  goto abop; }
  645.         |  e PLUS ASSIGN e
  646.             ={  goto abop; }
  647.         |  e MINUS ASSIGN e
  648.             ={  goto abop; }
  649.         |  e SHIFTOP ASSIGN e
  650.             ={  goto abop; }
  651.         |  e AND ASSIGN e
  652.             ={  goto abop; }
  653.         |  e OR ASSIGN e
  654.             ={  goto abop; }
  655.         |  e ER ASSIGN e
  656.             ={  goto abop; }
  657.         |  e QUEST e COLON e
  658.             ={  $$=buildtree(QUEST, $1, buildtree( COLON, $3, $5 ) );
  659.                 }
  660.         |  e ASOP e
  661.             ={  werror( "old-fashioned assignment operator" );  goto bop; }
  662.         |  e ASSIGN e
  663.             ={  goto bop; }
  664.         |  term
  665.         ;
  666. term:           term INCOP
  667.             ={  $$ = buildtree( $2, $1, bcon(1) ); }
  668.         |  MUL term
  669.             ={ ubop:
  670.                 $$ = buildtree( UNARY $1, $2, NIL );
  671.                 }
  672.         |  AND term
  673.             ={  if( ISFTN($2->type) || ISARY($2->type) ){
  674.                 werror( "& before array or function: ignored" );
  675.                 $$ = $2;
  676.                 }
  677.                 else goto ubop;
  678.                 }
  679.         |  MINUS term
  680.             ={  goto ubop; }
  681.         |  UNOP term
  682.             ={
  683.                 $$ = buildtree( $1, $2, NIL );
  684.                 }
  685.         |  INCOP term
  686.             ={  $$ = buildtree( $1==INCR ? ASG PLUS : ASG MINUS,
  687.                         $2,
  688.                         bcon(1)  );
  689.                 }
  690.         |  SIZEOF term
  691.             ={  $$ = doszof( $2 ); }
  692.         |  LP cast_type RP term  %prec INCOP
  693.             ={  $$ = buildtree( CAST, $2, $4 );
  694.                 $$->left->op = FREE;
  695.                 $$->op = FREE;
  696.                 $$ = $$->right;
  697.                 }
  698.         |  SIZEOF LP cast_type RP  %prec SIZEOF
  699.             ={  $$ = doszof( $3 ); }
  700.         |  term LB e RB
  701.             ={  $$ = buildtree( UNARY MUL, buildtree( PLUS, $1, $3 ), NIL ); }
  702.         |  funct_idn  RP
  703.             ={  $$=buildtree(UNARY CALL,$1,NIL); }
  704.         |  funct_idn elist  RP
  705.             ={  $$=buildtree(CALL,$1,$2); }
  706.         |  term STROP NAME
  707.             ={  if( $2 == DOT ){
  708.                 $1 = buildtree( UNARY AND, $1, NIL );
  709.                 }
  710.                 idname = $3;
  711.                 $$ = buildtree( STREF, $1, buildtree( NAME, NIL, NIL ) );
  712.                 }
  713.         |  NAME
  714.             ={  idname = $1;
  715.                 /* recognize identifiers in initializations */
  716.                 if( blevel==0 && stab[idname].stype == UNDEF ) {
  717.                 register NODE *q;
  718.                 werror( "undeclared initializer name %.8s", stab[idname].sname );
  719.                 q = block( FREE, NIL, NIL, INT, 0, INT );
  720.                 q->rval = idname;
  721.                 defid( q, EXTERN );
  722.                 }
  723.                 $$=buildtree(NAME,NIL,NIL);
  724.                 stab[$1].suse = -lineno;
  725.             }
  726.         |  ICON
  727.             ={  $$=bcon(0);
  728.                 $$->lval = lastcon;
  729.                 $$->rval = NONAME;
  730.                 if( $1 ) $$->csiz = $$->type = ctype(LONG);
  731.                 }
  732.         |  FCON
  733.             ={  $$=buildtree(FCON,NIL,NIL);
  734.                 $$->dval = dcon;
  735.                 }
  736.         |  STRING
  737.             ={  $$ = getstr(); /* get string contents */ }
  738.         |   LP  e  RP
  739.             ={ $$=$2; }
  740.         ;
  741.  
  742. cast_type:      type null_decl
  743.             ={
  744.             $$ = tymerge( $1, $2 );
  745.             $$->op = NAME;
  746.             $1->op = FREE;
  747.             }
  748.         ;
  749.  
  750. null_decl:       /* empty */
  751.             ={ $$ = bdty( NAME, NIL, -1 ); }
  752.         |  LP RP
  753.             ={ $$ = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); }
  754.         |  LP null_decl RP LP RP
  755.             ={  $$ = bdty( UNARY CALL, $2, 0 ); }
  756.         |  MUL null_decl
  757.             ={  goto umul; }
  758.         |  null_decl LB RB
  759.             ={  goto uary; }
  760.         |  null_decl LB con_e RB
  761.             ={  goto bary;  }
  762.         |  LP null_decl RP
  763.             ={ $$ = $2; }
  764.         ;
  765.  
  766. funct_idn:       NAME  LP 
  767.             ={  if( stab[$1].stype == UNDEF ){
  768.                 register NODE *q;
  769.                 q = block( FREE, NIL, NIL, FTN|INT, 0, INT );
  770.                 q->rval = $1;
  771.                 defid( q, EXTERN );
  772.                 }
  773.                 idname = $1;
  774.                 $$=buildtree(NAME,NIL,NIL);
  775.                 stab[idname].suse = -lineno;
  776.             }
  777.         |  term  LP 
  778.         ;
  779. %%
  780.  
  781. NODE *
  782. mkty( t, d, s ) unsigned t; {
  783.     return( block( TYPE, NIL, NIL, t, d, s ) );
  784.     }
  785.  
  786. NODE *
  787. bdty( op, p, v ) NODE *p; {
  788.     register NODE *q;
  789.  
  790.     q = block( op, p, NIL, INT, 0, INT );
  791.  
  792.     switch( op ){
  793.  
  794.     case UNARY MUL:
  795.     case UNARY CALL:
  796.         break;
  797.  
  798.     case LB:
  799.         q->right = bcon(v);
  800.         break;
  801.  
  802.     case NAME:
  803.         q->rval = v;
  804.         break;
  805.  
  806.     default:
  807.         cerror( "bad bdty" );
  808.         }
  809.  
  810.     return( q );
  811.     }
  812.  
  813. dstash( n ){ /* put n into the dimension table */
  814.     if( curdim >= DIMTABSZ-1 ){
  815.         cerror( "dimension table overflow");
  816.         }
  817.     dimtab[ curdim++ ] = n;
  818.     }
  819.  
  820. savebc() {
  821.     if( psavbc > & asavbc[BCSZ-4 ] ){
  822.         cerror( "whiles, fors, etc. too deeply nested");
  823.         }
  824.     *psavbc++ = brklab;
  825.     *psavbc++ = contlab;
  826.     *psavbc++ = flostat;
  827.     *psavbc++ = swx;
  828.     flostat = 0;
  829.     }
  830.  
  831. resetbc(mask){
  832.  
  833.     swx = *--psavbc;
  834.     flostat = *--psavbc | (flostat&mask);
  835.     contlab = *--psavbc;
  836.     brklab = *--psavbc;
  837.  
  838.     }
  839.  
  840. addcase(p) NODE *p; { /* add case to switch */
  841.  
  842.     p = optim( p );  /* change enum to ints */
  843.     if( p->op != ICON ){
  844.         uerror( "non-constant case expression");
  845.         return;
  846.         }
  847.     if( swp == swtab ){
  848.         uerror( "case not in switch");
  849.         return;
  850.         }
  851.     if( swp >= &swtab[SWITSZ] ){
  852.         cerror( "switch table overflow");
  853.         }
  854.     swp->sval = p->lval;
  855.     deflab( swp->slab = getlab() );
  856.     ++swp;
  857.     tfree(p);
  858.     }
  859.  
  860. adddef(){ /* add default case to switch */
  861.     if( swtab[swx].slab >= 0 ){
  862.         uerror( "duplicate default in switch");
  863.         return;
  864.         }
  865.     if( swp == swtab ){
  866.         uerror( "default not inside switch");
  867.         return;
  868.         }
  869.     deflab( swtab[swx].slab = getlab() );
  870.     }
  871.  
  872. swstart(){
  873.     /* begin a switch block */
  874.     if( swp >= &swtab[SWITSZ] ){
  875.         cerror( "switch table overflow");
  876.         }
  877.     swx = swp - swtab;
  878.     swp->slab = -1;
  879.     ++swp;
  880.     }
  881.  
  882. swend(){ /* end a switch block */
  883.  
  884.     register struct sw *swbeg, *p, *q, *r, *r1;
  885.     CONSZ temp;
  886.     int tempi;
  887.  
  888.     swbeg = &swtab[swx+1];
  889.  
  890.     /* sort */
  891.  
  892.     r1 = swbeg;
  893.     r = swp-1;
  894.  
  895.     while( swbeg < r ){
  896.         /* bubble largest to end */
  897.         for( q=swbeg; q<r; ++q ){
  898.             if( q->sval > (q+1)->sval ){
  899.                 /* swap */
  900.                 r1 = q+1;
  901.                 temp = q->sval;
  902.                 q->sval = r1->sval;
  903.                 r1->sval = temp;
  904.                 tempi = q->slab;
  905.                 q->slab = r1->slab;
  906.                 r1->slab = tempi;
  907.                 }
  908.             }
  909.         r = r1;
  910.         r1 = swbeg;
  911.         }
  912.  
  913.     /* it is now sorted */
  914.  
  915.     for( p = swbeg+1; p<swp; ++p ){
  916.         if( p->sval == (p-1)->sval ){
  917.             uerror( "duplicate case in switch, %d", tempi=p->sval );
  918.             return;
  919.             }
  920.         }
  921.  
  922.     genswitch( swbeg-1, swp-swbeg );
  923.     swp = swbeg-1;
  924.     }
  925.