home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / program / d / indent / !Indent / c / parse < prev   
Encoding:
Text File  |  1991-02-22  |  11.7 KB  |  371 lines

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