home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / INDENT1.ZIP / PARSE.C < prev    next >
C/C++ Source or Header  |  1991-07-04  |  9KB  |  330 lines

  1. /*
  2.  * Copyright (c) 1985 Sun Microsystems, Inc. Copyright (c) 1980 The Regents
  3.  * of the University of California. Copyright (c) 1976 Board of Trustees of
  4.  * the University of Illinois. All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms are permitted provided that
  7.  * the above copyright notice and this paragraph are duplicated in all such
  8.  * forms and that any documentation, advertising materials, and other
  9.  * materials related to such distribution and use acknowledge that the
  10.  * software was developed by the University of California, Berkeley, the
  11.  * University of Illinois, Urbana, and Sun Microsystems, Inc.  The name of
  12.  * either University or Sun Microsystems may not be used to endorse or
  13.  * promote products derived from this software without specific prior written
  14.  * permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  15.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
  16.  * OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  17.  */
  18.  
  19. #ifndef lint
  20. static char     sccsid[] = "@(#)parse.c    5.8 (Berkeley) 9/15/88";
  21.  
  22. #endif                                    /* not lint */
  23.  
  24. #include "globs.h"
  25. #include "codes.h"
  26.  
  27.  
  28.  
  29.  
  30. parse(tk)
  31. int             tk;                        /* the code for the construct scanned */
  32. {
  33.     int             i;
  34.  
  35. #ifdef debug
  36.     printf("%2d - %s\n", tk, token);
  37. #endif
  38.  
  39.     while (ps.p_stack[ps.tos] == ifhead && tk != elselit)
  40.     {
  41.         /* true if we have an if without an else */
  42.         ps.p_stack[ps.tos] = stmt;        /* apply the if(..) stmt ::= stmt
  43.                                          * reduction */
  44.         reduce();                        /* see if this allows any reduction */
  45.     }
  46.  
  47.  
  48.     switch (tk)
  49.     {                                    /* go on and figure out what to do
  50.                                          * with the input */
  51.  
  52.     case decl:                            /* scanned a declaration word */
  53.         ps.search_brace = btype_2;
  54.         /* indicate that following brace should be on same line */
  55.         if (ps.p_stack[ps.tos] != decl)
  56.         {                                /* only put one declaration onto
  57.                                          * stack */
  58.             break_comma = true;            /* while in declaration, newline
  59.                                          * should be forced after comma */
  60.             ps.p_stack[++ps.tos] = decl;
  61.             ps.il[ps.tos] = ps.i_l_follow;
  62.  
  63.             if (ps.ljust_decl)
  64.             {                            /* only do if we want left justified
  65.                                          * declarations */
  66.                 ps.ind_level = 0;
  67.                 for (i = ps.tos - 1; i > 0; --i)
  68.                     if (ps.p_stack[i] == decl)
  69.                         ++ps.ind_level;    /* indentation is number of
  70.                                          * declaration levels deep we are */
  71.                 ps.i_l_follow = ps.ind_level;
  72.             }
  73.         }
  74.         break;
  75.  
  76.     case ifstmt:                        /* scanned if (...) */
  77.         if (ps.p_stack[ps.tos] == elsehead && ps.else_if)        /* "else if ..." */
  78.             ps.i_l_follow = ps.il[ps.tos];
  79.     case dolit:                        /* 'do' */
  80.     case forstmt:                        /* for (...) */
  81.         ps.p_stack[++ps.tos] = tk;
  82.         ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
  83.         ++ps.i_l_follow;                /* subsequent statements should be
  84.                                          * indented 1 */
  85.         ps.search_brace = btype_2;
  86.         break;
  87.  
  88.     case lbrace:                        /* scanned { */
  89.         break_comma = false;            /* don't break comma in an initial
  90.                                          * list */
  91.         if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
  92.             || ps.p_stack[ps.tos] == stmtl)
  93.             ++ps.i_l_follow;            /* it is a random, isolated stmt
  94.                                          * group or a declaration */
  95.         else
  96.         {
  97.             if (s_code == e_code)
  98.             {
  99.  
  100.                 /*
  101.                  * only do this if there is nothing on the line
  102.                  */
  103.                 --ps.ind_level;
  104.  
  105.                 /*
  106.                  * it is a group as part of a while, for, etc.
  107.                  */
  108.                 if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1)
  109.                     --ps.ind_level;
  110.  
  111.                 /*
  112.                  * for a switch, brace should be two levels out from the code
  113.                  */
  114.             }
  115.         }
  116.  
  117.         ps.p_stack[++ps.tos] = lbrace;
  118.         ps.il[ps.tos] = ps.ind_level;
  119.         ps.p_stack[++ps.tos] = stmt;
  120.         /* allow null stmt between braces */
  121.         ps.il[ps.tos] = ps.i_l_follow;
  122.         break;
  123.  
  124.     case whilestmt:                    /* scanned while (...) */
  125.         if (ps.p_stack[ps.tos] == dohead)
  126.         {
  127.             /* it is matched with do stmt */
  128.             ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
  129.             ps.p_stack[++ps.tos] = whilestmt;
  130.             ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
  131.         }
  132.         else
  133.         {                                /* it is a while loop */
  134.             ps.p_stack[++ps.tos] = whilestmt;
  135.             ps.il[ps.tos] = ps.i_l_follow;
  136.             ++ps.i_l_follow;
  137.             ps.search_brace = btype_2;
  138.         }
  139.  
  140.         break;
  141.  
  142.     case elselit:                        /* scanned an else */
  143.  
  144.         if (ps.p_stack[ps.tos] != ifhead)
  145.             diag(1, "Unmatched 'else'");
  146.         else
  147.         {
  148.             ps.ind_level = ps.il[ps.tos];        /* indentation for else
  149.                                                  * should be same as for if */
  150.             ps.i_l_follow = ps.ind_level + 1;    /* everything following
  151.                                                  * should be in 1 level */
  152.             ps.p_stack[ps.tos] = elsehead;
  153.             /* remember if with else */
  154.             ps.search_brace = btype_2 | ps.else_if;
  155.         }
  156.         break;
  157.  
  158.     case rbrace:                        /* scanned a } */
  159.         /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
  160.         if (ps.p_stack[ps.tos - 1] == lbrace)
  161.         {
  162.             ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
  163.             ps.p_stack[ps.tos] = stmt;
  164.         }
  165.         else
  166.             diag(1, "Stmt nesting error.");
  167.         break;
  168.  
  169.     case swstmt:                        /* had switch (...) */
  170.         ps.p_stack[++ps.tos] = swstmt;
  171.         ps.cstk[ps.tos] = case_ind;
  172.         /* save current case indent level */
  173.         ps.il[ps.tos] = ps.i_l_follow;
  174.         case_ind = ps.i_l_follow + ps.case_indent;        /* cases should be one
  175.                                                          * level down from
  176.                                                          * switch */
  177.         ps.i_l_follow += ps.case_indent + 1;    /* statements should be two
  178.                                                  * levels in */
  179.         ps.search_brace = btype_2;
  180.         break;
  181.  
  182.     case semicolon:                    /* this indicates a simple stmt */
  183.         break_comma = false;            /* turn off flag to break after
  184.                                          * commas in a declaration */
  185.         ps.p_stack[++ps.tos] = stmt;
  186.         ps.il[ps.tos] = ps.ind_level;
  187.         break;
  188.  
  189.     default:                            /* this is an error */
  190.         diag(1, "Unknown code to parser");
  191.         return;
  192.  
  193.  
  194.     }                                    /* end of switch */
  195.  
  196.     reduce();                            /* see if any reduction can be done */
  197.  
  198. #ifdef debug
  199.     for (i = 1; i <= ps.tos; ++i)
  200.         printf("(%d %d)", ps.p_stack[i], ps.il[i]);
  201.     printf("\n");
  202. #endif
  203.  
  204.     return;
  205. }
  206.  
  207. /*
  208.  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
  209.  * 
  210.  * All rights reserved
  211.  * 
  212.  * 
  213.  * NAME: reduce
  214.  * 
  215.  * FUNCTION: Implements the reduce part of the parsing algorithm
  216.  * 
  217.  * ALGORITHM: The following reductions are done.  Reductions are repeated until
  218.  * no more are possible.
  219.  * 
  220.  * Old TOS        New TOS <stmt> <stmt>    <stmtl> <stmtl> <stmt>    <stmtl> do <stmt>
  221.  * "dostmt" if <stmt>    "ifstmt" switch <stmt>    <stmt> decl <stmt>    <stmt>
  222.  * "ifelse" <stmt>    <stmt> for <stmt>    <stmt> while <stmt>    <stmt> "dostmt"
  223.  * while    <stmt>
  224.  * 
  225.  * On each reduction, ps.i_l_follow (the indentation for the following line) is
  226.  * set to the indentation level associated with the old TOS.
  227.  * 
  228.  * PARAMETERS: None
  229.  * 
  230.  * RETURNS: Nothing
  231.  * 
  232.  * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
  233.  * 
  234.  * CALLS: None
  235.  * 
  236.  * CALLED BY: parse
  237.  * 
  238.  * HISTORY: initial coding     November 1976    D A Willcox of CAC
  239.  * 
  240.  */
  241. /*----------------------------------------------*\
  242. |   REDUCTION PHASE                    |
  243. \*----------------------------------------------*/
  244. reduce()
  245. {
  246.  
  247.     register int    i;
  248.  
  249.     for (;;)
  250.     {                                    /* keep looping until there is
  251.                                          * nothing left to reduce */
  252.  
  253.         switch (ps.p_stack[ps.tos])
  254.         {
  255.  
  256.         case stmt:
  257.             switch (ps.p_stack[ps.tos - 1])
  258.             {
  259.  
  260.             case stmt:
  261.             case stmtl:
  262.                 /* stmtl stmt or stmt stmt */
  263.                 ps.p_stack[--ps.tos] = stmtl;
  264.                 break;
  265.  
  266.             case dolit:                /* <do> <stmt> */
  267.                 ps.p_stack[--ps.tos] = dohead;
  268.                 ps.i_l_follow = ps.il[ps.tos];
  269.                 break;
  270.  
  271.             case ifstmt:
  272.                 /* <if> <stmt> */
  273.                 ps.p_stack[--ps.tos] = ifhead;
  274.                 for (i = ps.tos - 1;
  275.                      (
  276.                       ps.p_stack[i] != stmt
  277.                       &&
  278.                       ps.p_stack[i] != stmtl
  279.                       &&
  280.                       ps.p_stack[i] != lbrace
  281.                       );
  282.                      --i);
  283.                 ps.i_l_follow = ps.il[i];
  284.  
  285.                 /*
  286.                  * for the time being, we will assume that there is no else
  287.                  * on this if, and set the indentation level accordingly. If
  288.                  * an else is scanned, it will be fixed up later
  289.                  */
  290.                 break;
  291.  
  292.             case swstmt:
  293.                 /* <switch> <stmt> */
  294.                 case_ind = ps.cstk[ps.tos - 1];
  295.  
  296.             case decl:                    /* finish of a declaration */
  297.             case elsehead:
  298.                 /* <<if> <stmt> else> <stmt> */
  299.             case forstmt:
  300.                 /* <for> <stmt> */
  301.             case whilestmt:
  302.                 /* <while> <stmt> */
  303.                 ps.p_stack[--ps.tos] = stmt;
  304.                 ps.i_l_follow = ps.il[ps.tos];
  305.                 break;
  306.  
  307.             default:                    /* <anything else> <stmt> */
  308.                 return;
  309.  
  310.             }                            /* end of section for <stmt> on top
  311.                                          * of stack */
  312.             break;
  313.  
  314.         case whilestmt:                /* while (...) on top */
  315.             if (ps.p_stack[ps.tos - 1] == dohead)
  316.             {
  317.                 /* it is termination of a do while */
  318.                 ps.p_stack[--ps.tos] = stmt;
  319.                 break;
  320.             }
  321.             else
  322.                 return;
  323.  
  324.         default:                        /* anything else on top */
  325.             return;
  326.  
  327.         }
  328.     }
  329. }
  330.