xref: /csrg-svn/usr.bin/indent/parse.c (revision 33767)
121971Sdist /*
221971Sdist  * Copyright (c) 1980 Regents of the University of California.
3*33767Sbostic  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
4*33767Sbostic  * All rights reserved.
5*33767Sbostic  *
6*33767Sbostic  * Redistribution and use in source and binary forms are permitted
7*33767Sbostic  * provided that this notice is preserved and that due credit is given
8*33767Sbostic  * to the University of California at Berkeley and the University of
9*33767Sbostic  * Illinois at Urbana.  The name of either University may not be used
10*33767Sbostic  * to endorse or promote products derived from this software without
11*33767Sbostic  * specific prior written permission. This software is provided
12*33767Sbostic  * ``as is'' without express or implied warranty.
1321971Sdist  */
148805Smckusick 
1521971Sdist #ifndef lint
16*33767Sbostic static char sccsid[] = "@(#)parse.c	5.5 (Berkeley) 03/22/88";
17*33767Sbostic #endif /* not lint */
1821971Sdist 
19*33767Sbostic /*
2024456Smckusick  * FILE NAME:
2124456Smckusick  *	parse.c
2224456Smckusick  *
2324456Smckusick  * PURPOSE:
2424456Smckusick  *	Contains the routines which keep track of the parse stack.
2524456Smckusick  *
2624456Smckusick  * GLOBALS:
2724456Smckusick  *	ps.p_stack =	The parse stack, set by both routines
2824456Smckusick  *	ps.il =		Stack of indentation levels, set by parse
2924456Smckusick  *	ps.cstk =		Stack of case statement indentation levels, set by parse
3024456Smckusick  *	ps.tos =		Pointer to top of stack, set by both routines.
3124456Smckusick  *
3224456Smckusick  * FUNCTIONS:
3324456Smckusick  *	parse
3424456Smckusick  *	reduce
3524456Smckusick  */
3624456Smckusick /*-
3724456Smckusick  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
3824456Smckusick  *
3924456Smckusick  * All rights reserved
4024456Smckusick  *
4124456Smckusick  *
4224456Smckusick  * NAME: parse
4324456Smckusick  *
4424456Smckusick  * FUNCTION: Parse is given one input which is a "maxi token" just scanned
4524456Smckusick  * from input.  Maxi tokens are signifigant constructs such as else, {,
4624456Smckusick  * do, if (...), etc.  Parse works with reduce to maintain a parse stack
4724456Smckusick  * of these constructs.  Parse is responsible for the "shift" portion of
4824456Smckusick  * the parse algorithm, and reduce handles the "reduce" portion.
4924456Smckusick  *
5024456Smckusick  * HISTORY: initial coding 	November 1976	D A Willcox of CAC
5124456Smckusick  *
5224456Smckusick  */
538805Smckusick 
5433231Sbostic #include "./indent_globs.h"
5533231Sbostic #include "./indent_codes.h"
568805Smckusick 
578805Smckusick 
588805Smckusick 
598805Smckusick 
6024456Smckusick parse(tk)
6124456Smckusick     int         tk;		/* the code for the construct scanned */
628805Smckusick {
6324456Smckusick     int         i;
648805Smckusick 
658805Smckusick #ifdef debug
6624456Smckusick     printf("%2d - %s\n", tk, token);
678805Smckusick #endif
6824456Smckusick     while (ps.p_stack[ps.tos] == ifhead && tk != elselit) {
6924456Smckusick 	/* true if we have an if without an else */
7024456Smckusick 	ps.p_stack[ps.tos] = stmt;	/* apply the if(..) stmt ::= stmt
7124456Smckusick 				 * reduction */
7224456Smckusick 	reduce();		/* see if this allows any reduction */
738805Smckusick     }
748805Smckusick 
758805Smckusick 
7624456Smckusick     switch (tk) {		/* go on and figure out what to do with
7724456Smckusick 				 * the input */
788805Smckusick 
7924456Smckusick 	case decl: 		/* scanned a declaration word */
8024456Smckusick 	    ps.search_brace = btype_2;
8124456Smckusick 	    /* indicate that following brace should be on same line */
8224456Smckusick 	    if (ps.p_stack[ps.tos] != decl) {	/* only put one declaration onto
8324456Smckusick 					 * stack */
8424456Smckusick 		break_comma = true;	/* while in declaration, newline
8524456Smckusick 					 * should be forced after comma */
8624456Smckusick 		ps.p_stack[++ps.tos] = decl;
8724456Smckusick 		ps.il[ps.tos] = ps.i_l_follow;
888805Smckusick 
8924456Smckusick 		if (ps.ljust_decl) {	/* only do if we want left
9024456Smckusick 					 * justified declarations */
9124456Smckusick 		    ps.ind_level = 0;
9224456Smckusick 		    for (i = ps.tos - 1; i > 0; --i)
9324456Smckusick 			if (ps.p_stack[i] == decl)
9424456Smckusick 			    ++ps.ind_level;	/* indentation is number
9524456Smckusick 						 * of declaration levels
9624456Smckusick 						 * deep we are */
9724456Smckusick 		    ps.i_l_follow = ps.ind_level;
988805Smckusick 		}
998805Smckusick 	    }
1008805Smckusick 	    break;
1018805Smckusick 
10224456Smckusick 	case ifstmt: 		/* scanned if (...) */
10324456Smckusick 	    if (ps.p_stack[ps.tos] == elsehead && ps.else_if)	/* "else if ..." */
10424456Smckusick 		ps.i_l_follow = ps.il[ps.tos];
10524456Smckusick 	case dolit: 		/* 'do' */
10624456Smckusick 	case forstmt: 		/* for (...) */
10724456Smckusick 	    ps.p_stack[++ps.tos] = tk;
10824456Smckusick 	    ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
10924456Smckusick 	    ++ps.i_l_follow;	/* subsequent statements should be
11024456Smckusick 				 * indented 1 */
11124456Smckusick 	    ps.search_brace = btype_2;
1128805Smckusick 	    break;
1138805Smckusick 
11424456Smckusick 	case lbrace: 		/* scanned { */
11524456Smckusick 	    break_comma = false;/* don't break comma in an initial list */
11624456Smckusick 	    if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
11724456Smckusick 		    || ps.p_stack[ps.tos] == stmtl)
11824456Smckusick 		++ps.i_l_follow;	/* it is a random, isolated stmt group or
11924456Smckusick 				 * a declaration */
1208805Smckusick 	    else {
1218805Smckusick 		if (s_code == e_code) {
12224456Smckusick 		    /* only do this if there is nothing on the line */
12324456Smckusick 		    --ps.ind_level;
12424456Smckusick 		    /* it is a group as part of a while, for, etc. */
12524456Smckusick 		    if (ps.p_stack[ps.tos] == swstmt && ps.case_indent)
12624456Smckusick 			--ps.ind_level;
12724456Smckusick 		    /*
12824456Smckusick 		     * for a switch, brace should be two levels out from
12924456Smckusick 		     * the code
13024456Smckusick 		     */
1318805Smckusick 		}
1328805Smckusick 	    }
1338805Smckusick 
13424456Smckusick 	    ps.p_stack[++ps.tos] = lbrace;
13524456Smckusick 	    ps.il[ps.tos] = ps.ind_level;
13624456Smckusick 	    ps.p_stack[++ps.tos] = stmt;
13724456Smckusick 	    /* allow null stmt between braces */
13824456Smckusick 	    ps.il[ps.tos] = ps.i_l_follow;
1398805Smckusick 	    break;
1408805Smckusick 
14124456Smckusick 	case whilestmt: 	/* scanned while (...) */
14224456Smckusick 	    if (ps.p_stack[ps.tos] == dohead) {
14324456Smckusick 		/* it is matched with do stmt */
14424456Smckusick 		ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
14524456Smckusick 		ps.p_stack[++ps.tos] = whilestmt;
14624456Smckusick 		ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
1478805Smckusick 	    }
14824456Smckusick 	    else {		/* it is a while loop */
14924456Smckusick 		ps.p_stack[++ps.tos] = whilestmt;
15024456Smckusick 		ps.il[ps.tos] = ps.i_l_follow;
15124456Smckusick 		++ps.i_l_follow;
15224456Smckusick 		ps.search_brace = btype_2;
1538805Smckusick 	    }
1548805Smckusick 
1558805Smckusick 	    break;
1568805Smckusick 
15724456Smckusick 	case elselit: 		/* scanned an else */
1588805Smckusick 
15924456Smckusick 	    if (ps.p_stack[ps.tos] != ifhead)
16024456Smckusick 		diag(1,"Unmatched 'else'");
1618805Smckusick 	    else {
16224456Smckusick 		ps.ind_level = ps.il[ps.tos];		/* indentation for else should be same as for if */
16324456Smckusick 		ps.i_l_follow = ps.ind_level + 1;	/* everything following should be in 1 level */
16424456Smckusick 		ps.p_stack[ps.tos] = elsehead;
16524456Smckusick 		/* remember if with else */
16624456Smckusick 		ps.search_brace = btype_2;
1678805Smckusick 	    }
1688805Smckusick 
1698805Smckusick 	    break;
1708805Smckusick 
17124456Smckusick 	case rbrace: 		/* scanned a } */
17224456Smckusick 	    /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
17324456Smckusick 	    if (ps.p_stack[ps.tos - 1] == lbrace) {
17424456Smckusick 		ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
17524456Smckusick 		ps.p_stack[ps.tos] = stmt;
1768805Smckusick 	    }
17724456Smckusick 	    else
17824456Smckusick 		diag(1,"Stmt nesting error.");
1798805Smckusick 	    break;
1808805Smckusick 
18124456Smckusick 	case swstmt: 		/* had switch (...) */
18224456Smckusick 	    ps.p_stack[++ps.tos] = swstmt;
18324456Smckusick 	    ps.cstk[ps.tos] = case_ind;
18424456Smckusick 	    /* save current case indent level */
18524456Smckusick 	    ps.il[ps.tos] = ps.i_l_follow;
18624456Smckusick 	    case_ind = ps.i_l_follow + ps.case_indent;	/* cases should be one
18724456Smckusick 							 * level down from
18824456Smckusick 							 * switch */
18933231Sbostic 	    ps.i_l_follow += ps.case_indent + 1;	/* statements should be
19024456Smckusick 						 * two levels in */
19124456Smckusick 	    ps.search_brace = btype_2;
1928805Smckusick 	    break;
1938805Smckusick 
19424456Smckusick 	case semicolon: 	/* this indicates a simple stmt */
19524456Smckusick 	    break_comma = false;/* turn off flag to break after commas in
19624456Smckusick 				 * a declaration */
19724456Smckusick 	    ps.p_stack[++ps.tos] = stmt;
19824456Smckusick 	    ps.il[ps.tos] = ps.ind_level;
1998805Smckusick 	    break;
2008805Smckusick 
20124456Smckusick 	default: 		/* this is an error */
20224456Smckusick 	    diag(1,"Unknown code to parser");
2038805Smckusick 	    return;
2048805Smckusick 
2058805Smckusick 
20624456Smckusick     }				/* end of switch */
2078805Smckusick 
20824456Smckusick     reduce();			/* see if any reduction can be done */
2098805Smckusick #ifdef debug
21024456Smckusick     for (i = 1; i <= ps.tos; ++i)
21124456Smckusick 	printf("(%d %d)", ps.p_stack[i], ps.il[i]);
21224456Smckusick     printf("\n");
2138805Smckusick #endif
2148805Smckusick     return;
2158805Smckusick }
21624456Smckusick /*
21724456Smckusick  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
21824456Smckusick  *
21924456Smckusick  * All rights reserved
22024456Smckusick  *
22124456Smckusick  *
22224456Smckusick  * NAME: reduce
22324456Smckusick  *
22424456Smckusick  * FUNCTION: Implements the reduce part of the parsing algorithm
22524456Smckusick  *
22624456Smckusick  * ALGORITHM: The following reductions are done.  Reductions are repeated
22724456Smckusick  * until no more are possible.
22824456Smckusick  *
22924456Smckusick  * Old TOS		New TOS <stmt> <stmt>	<stmtl> <stmtl> <stmt>	<stmtl> do
23024456Smckusick  * <stmt>	"dostmt" if <stmt>	"ifstmt" switch <stmt>	<stmt>
23124456Smckusick  * decl <stmt>	<stmt> "ifelse" <stmt>	<stmt> for <stmt>	<stmt>
23224456Smckusick  * while <stmt>	<stmt> "dostmt" while	<stmt>
23324456Smckusick  *
23424456Smckusick  * On each reduction, ps.i_l_follow (the indentation for the following line) is
23524456Smckusick  * set to the indentation level associated with the old TOS.
23624456Smckusick  *
23724456Smckusick  * PARAMETERS: None
23824456Smckusick  *
23924456Smckusick  * RETURNS: Nothing
24024456Smckusick  *
24124456Smckusick  * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
24224456Smckusick  *
24324456Smckusick  * CALLS: None
24424456Smckusick  *
24524456Smckusick  * CALLED BY: parse 
24624456Smckusick  *
24724456Smckusick  * HISTORY: initial coding 	November 1976	D A Willcox of CAC
24824456Smckusick  *
24924456Smckusick  */
2508805Smckusick /*----------------------------------------------*\
25124456Smckusick  * |   REDUCTION PHASE
2528805Smckusick \*----------------------------------------------*/
25324456Smckusick reduce() {
2548805Smckusick 
25524456Smckusick     register int i;
2568805Smckusick 
25724456Smckusick     for (;;) {			/* keep looping until there is nothing
25824456Smckusick 				 * left to reduce */
2598805Smckusick 
26024456Smckusick 	switch (ps.p_stack[ps.tos]) {
2618805Smckusick 
2628805Smckusick 	    case stmt:
26324456Smckusick 		switch (ps.p_stack[ps.tos - 1]) {
2648805Smckusick 
2658805Smckusick 		    case stmt:
2668805Smckusick 		    case stmtl:
26724456Smckusick 			/* stmtl stmt or stmt stmt */
26824456Smckusick 			ps.p_stack[--ps.tos] = stmtl;
2698805Smckusick 			break;
2708805Smckusick 
27124456Smckusick 		    case dolit: /* <do> <stmt> */
27224456Smckusick 			ps.p_stack[--ps.tos] = dohead;
27324456Smckusick 			ps.i_l_follow = ps.il[ps.tos];
2748805Smckusick 			break;
2758805Smckusick 
2768805Smckusick 		    case ifstmt:
27724456Smckusick 			/* <if> <stmt> */
27824456Smckusick 			ps.p_stack[--ps.tos] = ifhead;
27924456Smckusick 			for (i = ps.tos - 1;
2808805Smckusick 				(
28124456Smckusick 				    ps.p_stack[i] != stmt
2828805Smckusick 				    &&
28324456Smckusick 				    ps.p_stack[i] != stmtl
2848805Smckusick 				    &&
28524456Smckusick 				    ps.p_stack[i] != lbrace
2868805Smckusick 				);
2878805Smckusick 				--i);
28824456Smckusick 			ps.i_l_follow = ps.il[i];
28924456Smckusick 			/*
29024456Smckusick 			 * for the time being, we will assume that there
29124456Smckusick 			 * is no else on this if, and set the indentation
29224456Smckusick 			 * level accordingly. If an else is scanned, it
29324456Smckusick 			 * will be fixed up later
29424456Smckusick 			 */
2958805Smckusick 			break;
2968805Smckusick 
2978805Smckusick 		    case swstmt:
29824456Smckusick 			/* <switch> <stmt> */
29924456Smckusick 			case_ind = ps.cstk[ps.tos - 1];
3008805Smckusick 
30124456Smckusick 		    case decl: 	/* finish of a declaration */
3028805Smckusick 		    case elsehead:
30324456Smckusick 			/* <<if> <stmt> else> <stmt> */
3048805Smckusick 		    case forstmt:
30524456Smckusick 			/* <for> <stmt> */
3068805Smckusick 		    case whilestmt:
30724456Smckusick 			/* <while> <stmt> */
30824456Smckusick 			ps.p_stack[--ps.tos] = stmt;
30924456Smckusick 			ps.i_l_follow = ps.il[ps.tos];
3108805Smckusick 			break;
3118805Smckusick 
31224456Smckusick 		    default: 	/* <anything else> <stmt> */
3138805Smckusick 			return;
3148805Smckusick 
31524456Smckusick 		}		/* end of section for <stmt> on top of
31624456Smckusick 				 * stack */
3178805Smckusick 		break;
3188805Smckusick 
31924456Smckusick 	    case whilestmt: 	/* while (...) on top */
32024456Smckusick 		if (ps.p_stack[ps.tos - 1] == dohead) {
32124456Smckusick 		    /* it is termination of a do while */
32224456Smckusick 		    ps.p_stack[--ps.tos] = stmt;
3238805Smckusick 		    break;
3248805Smckusick 		}
3258805Smckusick 		else
3268805Smckusick 		    return;
3278805Smckusick 
32824456Smckusick 	    default: 		/* anything else on top */
3298805Smckusick 		return;
3308805Smckusick 
33124456Smckusick 	}
33224456Smckusick     }
3338805Smckusick }
334