xref: /csrg-svn/usr.bin/indent/parse.c (revision 21971)
1*21971Sdist /*
2*21971Sdist  * Copyright (c) 1980 Regents of the University of California.
3*21971Sdist  * All rights reserved.  The Berkeley software License Agreement
4*21971Sdist  * specifies the terms and conditions for redistribution.
5*21971Sdist  */
68805Smckusick 
7*21971Sdist #ifndef lint
8*21971Sdist static char sccsid[] = "@(#)parse.c	5.1 (Berkeley) 06/04/85";
9*21971Sdist #endif not lint
10*21971Sdist 
118805Smckusick /*
128805Smckusick 
138805Smckusick 			  Copyright (C) 1976
148805Smckusick 				by the
158805Smckusick 			  Board of Trustees
168805Smckusick 				of the
178805Smckusick 			University of Illinois
188805Smckusick 
198805Smckusick 			 All rights reserved
208805Smckusick 
218805Smckusick 
228805Smckusick FILE NAME:
238805Smckusick 	parse.c
248805Smckusick 
258805Smckusick PURPOSE:
268805Smckusick 	Contains the routines which keep track of the parse stack.
278805Smckusick 
288805Smckusick GLOBALS:
298805Smckusick 	p_stack =	The parse stack, set by both routines
308805Smckusick 	il =		Stack of indentation levels, set by parse
318805Smckusick 	cstk =		Stack of case statement indentation levels, set by parse
328805Smckusick 	tos =		Pointer to top of stack, set by both routines.
338805Smckusick 
348805Smckusick FUNCTIONS:
358805Smckusick 	parse
368805Smckusick 	reduce
378805Smckusick */
388805Smckusick /*
398805Smckusick 
408805Smckusick 			  Copyright (C) 1976
418805Smckusick 				by the
428805Smckusick 			  Board of Trustees
438805Smckusick 				of the
448805Smckusick 			University of Illinois
458805Smckusick 
468805Smckusick 			 All rights reserved
478805Smckusick 
488805Smckusick 
498805Smckusick NAME:
508805Smckusick 	parse
518805Smckusick 
528805Smckusick FUNCTION:
538805Smckusick 	Parse is given one input which is a "maxi token" just scanned from
548805Smckusick 	input.  Maxi tokens are signifigant constructs such as else, {, do,
558805Smckusick 	if (...), etc.  Parse works with reduce to maintain a parse stack
568805Smckusick 	of these constructs.  Parse is responsible for the "shift" portion
578805Smckusick 	of the parse algorithm, and reduce handles the "reduce" portion.
588805Smckusick 
598805Smckusick ALGORITHM:
608805Smckusick 	1) If there is "ifstmt" on the stack and input is anything other than
618805Smckusick 	   an else, then change the top of stack (TOS) to <stmt>.  Do a reduce.
628805Smckusick 	2) Use a switch statement to implement the following shift operations:
638805Smckusick 
648805Smckusick 	   TOS___		Input_____		Stack_____		Note____
658805Smckusick 	decl		decl		nothing
668805Smckusick 	anything else	decl		decl
678805Smckusick 	"dostmt"	while (..)			Change TOS to <stmt>
688805Smckusick 	anything else	while (..)	while
698805Smckusick 	"ifstmt"	else				Change TOS to "ifelse"
708805Smckusick 	{ <stmtl>	}				Change { <stmtl>
718805Smckusick 								to <stmtl>
728805Smckusick 			switch (..)	switch
738805Smckusick 			do		do
748805Smckusick 			for(..)		for
758805Smckusick 			;		<stmt>
768805Smckusick 			{		{ <stmt>
778805Smckusick 
788805Smckusick PARAMETERS:
798805Smckusick 	tk	An integer code for the maxi token scanned
808805Smckusick 
818805Smckusick RETURNS:
828805Smckusick 	Nothing
838805Smckusick 
848805Smckusick GLOBALS:
858805Smckusick 	break_comma =	Set to true when in a declaration but not initialization
868805Smckusick 	btype_2
878805Smckusick 	case_ind =
888805Smckusick 	cstk =
898805Smckusick 	i_l_follow =
908805Smckusick 	il =		Stack of indentation levels
918805Smckusick 	ind_level =
928805Smckusick 	p_stack =	Stack of token codes
938805Smckusick 	search_brace =	Set to true if we must look for possibility of moving a
948805Smckusick 			brace
958805Smckusick 	tos =		Pointer to top of p_stack, il, and cstk
968805Smckusick 
978805Smckusick CALLS:
988805Smckusick 	printf (lib)
998805Smckusick 	reduce
1008805Smckusick 
1018805Smckusick CALLED BY:
1028805Smckusick 	main
1038805Smckusick 
1048805Smckusick HISTORY:
1058805Smckusick 	initial coding 	November 1976	D A Willcox of CAC
1068805Smckusick 
1078805Smckusick */
1088805Smckusick 
1098805Smckusick #include "./indent_globs.h";
1108805Smckusick #include "./indent_codes.h";
1118805Smckusick 
1128805Smckusick 
1138805Smckusick int     p_stack[50] = stmt;
1148805Smckusick  /* this is the parser's stack */
1158805Smckusick int     il[50];    /* this stack stores indentation levels */
1168805Smckusick int     cstk[50];  /* used to store case stmt indentation levels */
1178805Smckusick int     tos = 0;   /* pointer to top of stack */
1188805Smckusick 
1198805Smckusick 
1208805Smckusick parse (tk)
1218805Smckusick int     tk;	   /* the code for the construct scanned */
1228805Smckusick {
1238805Smckusick     int     i;
1248805Smckusick 
1258805Smckusick #ifdef debug
1268805Smckusick     printf ("%2d - %s\n", tk, token);
1278805Smckusick #endif
1288805Smckusick     while (p_stack[tos] == ifhead && tk != elselit) {
1298805Smckusick     /* true if we have an if without an else */
1308805Smckusick 	p_stack[tos] = stmt;   /* apply the if(..) stmt ::= stmt reduction */
1318805Smckusick 	reduce ();	       /* see if this allows any reduction */
1328805Smckusick     }
1338805Smckusick 
1348805Smckusick 
1358805Smckusick     switch (tk) {	       /* go on and figure out what to do with the
1368805Smckusick 			          input */
1378805Smckusick 
1388805Smckusick 	case decl: 	       /* scanned a declaration word */
1398805Smckusick 	    search_brace = btype_2;
1408805Smckusick 	/* indicate that following brace should be on same line */
1418805Smckusick 	    if (p_stack[tos] != decl) {
1428805Smckusick 	    /* only put one declaration onto stack */
1438805Smckusick 		break_comma = true;
1448805Smckusick 	    /* while in declaration, newline should be forced after comma */
1458805Smckusick 		p_stack[++tos] = decl;
1468805Smckusick 		il[tos] = i_l_follow;
1478805Smckusick 
1488805Smckusick 		if (ljust_decl) {
1498805Smckusick 		/* only do if we want left justified declarations */
1508805Smckusick 		    ind_level = 0;
1518805Smckusick 		    for (i = tos - 1; i > 0; --i)
1528805Smckusick 			if (p_stack[i] == decl)
1538805Smckusick 			    ++ind_level;
1548805Smckusick 		/* indentation is number of declaration levels deep we are */
1558805Smckusick 		    i_l_follow = ind_level;
1568805Smckusick 		}
1578805Smckusick 	    }
1588805Smckusick 	    break;
1598805Smckusick 
1608805Smckusick 	case ifstmt: 	       /* scanned if (...) */
1618805Smckusick 	case dolit: 	       /* 'do' */
1628805Smckusick 	case forstmt: 	       /* for (...) */
1638805Smckusick 	    p_stack[++tos] = tk;
1648805Smckusick 	    il[tos] = ind_level = i_l_follow;
1658805Smckusick 	    ++i_l_follow;      /* subsequent statements should be indented 1 */
1668805Smckusick 	    search_brace = btype_2;
1678805Smckusick 	    break;
1688805Smckusick 
1698805Smckusick 	case lbrace: 	       /* scanned { */
1708805Smckusick 	    break_comma = false;
1718805Smckusick 	/* don't break comma in an initial list */
1728805Smckusick 	    if (p_stack[tos] == stmt || p_stack[tos] == decl
1738805Smckusick 				     || p_stack[tos] == stmtl)
1748805Smckusick 		++i_l_follow;  /* it is a random, isolated stmt group or a
1758805Smckusick 			          declaration */
1768805Smckusick 	    else {
1778805Smckusick 		if (s_code == e_code) {
1788805Smckusick 		/* only do this if there is nothing on the line */
1798805Smckusick 		    --ind_level;
1808805Smckusick 		/* it is a group as part of a while, for, etc. */
1818805Smckusick 		    if (p_stack[tos] == swstmt)
1828805Smckusick 			--ind_level;
1838805Smckusick 		/* for a switch, brace should be two levels out from the code
1848805Smckusick 		*/
1858805Smckusick 		}
1868805Smckusick 	    }
1878805Smckusick 
1888805Smckusick 	    p_stack[++tos] = lbrace;
1898805Smckusick 	    il[tos] = ind_level;
1908805Smckusick 	    p_stack[++tos] = stmt;
1918805Smckusick 	/* allow null stmt between braces */
1928805Smckusick 	    il[tos] = i_l_follow;
1938805Smckusick 	    break;
1948805Smckusick 
1958805Smckusick 	case whilestmt:        /* scanned while (...) */
1968805Smckusick 	    if (p_stack[tos] == dohead) {
1978805Smckusick 	    /* it is matched with do stmt */
1988805Smckusick 		ind_level = i_l_follow = il[tos];
1998805Smckusick 		p_stack[++tos] = whilestmt;
2008805Smckusick 		il[tos] = ind_level = i_l_follow;
2018805Smckusick 	    }
2028805Smckusick 	    else {	       /* it is a while loop */
2038805Smckusick 		p_stack[++tos] = whilestmt;
2048805Smckusick 		il[tos] = i_l_follow;
2058805Smckusick 		++i_l_follow;
2068805Smckusick 		search_brace = btype_2;
2078805Smckusick 	    }
2088805Smckusick 
2098805Smckusick 	    break;
2108805Smckusick 
2118805Smckusick 	case elselit: 	       /* scanned an else */
2128805Smckusick 
2138805Smckusick 	    if (p_stack[tos] != ifhead) {
2148805Smckusick 		printf ("%d: Unmatched else\n", line_no);
2158805Smckusick 	    }
2168805Smckusick 	    else {
2178805Smckusick 		ind_level = il[tos];
2188805Smckusick 	    /* indentation for else should be same as for if */
2198805Smckusick 		i_l_follow = ind_level + 1;
2208805Smckusick 	    /* everything following should be in 1 level */
2218805Smckusick 		p_stack[tos] = elsehead;
2228805Smckusick 	    /* remember if with else */
2238805Smckusick 		search_brace = btype_2;
2248805Smckusick 	    }
2258805Smckusick 
2268805Smckusick 	    break;
2278805Smckusick 
2288805Smckusick 	case rbrace: 	       /* scanned a } */
2298805Smckusick 	/* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
2308805Smckusick 	    if (p_stack[tos - 1] == lbrace) {
2318805Smckusick 		ind_level = i_l_follow = il[--tos];
2328805Smckusick 		p_stack[tos] = stmt;
2338805Smckusick 	    }
2348805Smckusick 	    else {
2358805Smckusick 		printf ("%d: Stmt nesting error\n", line_no);
2368805Smckusick 	    }
2378805Smckusick 
2388805Smckusick 	    break;
2398805Smckusick 
2408805Smckusick 	case swstmt: 	       /* had switch (...) */
2418805Smckusick 	    p_stack[++tos] = swstmt;
2428805Smckusick 	    cstk[tos] = case_ind;
2438805Smckusick 	/* save current case indent level */
2448805Smckusick 	    il[tos] = i_l_follow;
2458805Smckusick 	    case_ind = i_l_follow + 1;
2468805Smckusick 	/* cases should be one level down from switch */
2478805Smckusick 	    i_l_follow + = 2;  /* statements should be two levels in */
2488805Smckusick 	    search_brace = btype_2;
2498805Smckusick 	    break;
2508805Smckusick 
2518805Smckusick 	case semicolon:        /* this indicates a simple stmt */
2528805Smckusick 	    break_comma = false;
2538805Smckusick 	/* turn off flag to break after commas in a declaration */
2548805Smckusick 	    p_stack[++tos] = stmt;
2558805Smckusick 	    il[tos] = ind_level;
2568805Smckusick 	    break;
2578805Smckusick 
2588805Smckusick 	default: 	       /* this is an error */
2598805Smckusick 	    printf ("%d: Unknown code to parser - %d\n", line_no, tk);
2608805Smckusick 	    return;
2618805Smckusick 
2628805Smckusick 
2638805Smckusick     }			       /* end of switch */
2648805Smckusick 
2658805Smckusick     reduce ();		       /* see if any reduction can be done */
2668805Smckusick #ifdef debug
2678805Smckusick     for (i = 1; i <= tos; ++i)
2688805Smckusick 	printf ("(%d %d)", p_stack[i], il[i]);
2698805Smckusick     printf ("\n");
2708805Smckusick #endif
2718805Smckusick     return;
2728805Smckusick }
2738805Smckusick /*
2748805Smckusick 
2758805Smckusick 			  Copyright (C) 1976
2768805Smckusick 				by the
2778805Smckusick 			  Board of Trustees
2788805Smckusick 				of the
2798805Smckusick 			University of Illinois
2808805Smckusick 
2818805Smckusick 			 All rights reserved
2828805Smckusick 
2838805Smckusick 
2848805Smckusick NAME:
2858805Smckusick 	reduce
2868805Smckusick 
2878805Smckusick FUNCTION:
2888805Smckusick 	Implements the reduce part of the parsing algorithm
2898805Smckusick 
2908805Smckusick ALGORITHM:
2918805Smckusick 	The following reductions are done.  Reductions are repeated until no
2928805Smckusick 	more are possible.
2938805Smckusick 
2948805Smckusick 	Old___ TOS___		New___ TOS___
2958805Smckusick 	<stmt> <stmt>	<stmtl>
2968805Smckusick 	<stmtl> <stmt>	<stmtl>
2978805Smckusick 	do <stmt>	"dostmt"
2988805Smckusick 	if <stmt>	"ifstmt"
2998805Smckusick 	switch <stmt>	<stmt>
3008805Smckusick 	decl <stmt>	<stmt>
3018805Smckusick 	"ifelse" <stmt>	<stmt>
3028805Smckusick 	for <stmt>	<stmt>
3038805Smckusick 	while <stmt>	<stmt>
3048805Smckusick 	"dostmt" while	<stmt>
3058805Smckusick 
3068805Smckusick 	On each reduction, i_l_follow (the indentation for the following line)
3078805Smckusick 	is set to the indentation level associated with the old TOS.
3088805Smckusick 
3098805Smckusick PARAMETERS:
3108805Smckusick 	None
3118805Smckusick 
3128805Smckusick RETURNS:
3138805Smckusick 	Nothing
3148805Smckusick 
3158805Smckusick GLOBALS:
3168805Smckusick 	cstk
3178805Smckusick 	i_l_follow =
3188805Smckusick 	il
3198805Smckusick 	p_stack =
3208805Smckusick 	tos =
3218805Smckusick 
3228805Smckusick CALLS:
3238805Smckusick 	None
3248805Smckusick 
3258805Smckusick CALLED BY:
3268805Smckusick 	parse
3278805Smckusick 
3288805Smckusick HISTORY:
3298805Smckusick 	initial coding 	November 1976	D A Willcox of CAC
3308805Smckusick 
3318805Smckusick */
3328805Smckusick /*----------------------------------------------*\
3338805Smckusick |   REDUCTION PHASE
3348805Smckusick \*----------------------------------------------*/
3358805Smckusick reduce () {
3368805Smckusick 
3378805Smckusick     register int    i;
3388805Smckusick  /* local looping variable */
3398805Smckusick 
3408805Smckusick     for (;;) {		       /* keep looping until there is nothing left to
3418805Smckusick 			          reduce */
3428805Smckusick 
3438805Smckusick 	switch (p_stack[tos]) {
3448805Smckusick 
3458805Smckusick 	    case stmt:
3468805Smckusick 		switch (p_stack[tos - 1]) {
3478805Smckusick 
3488805Smckusick 		    case stmt:
3498805Smckusick 		    case stmtl:
3508805Smckusick 		    /* stmtl stmt or stmt stmt */
3518805Smckusick 			p_stack[--tos] = stmtl;
3528805Smckusick 			break;
3538805Smckusick 
3548805Smckusick 		    case dolit:
3558805Smckusick 		    /* <do> <stmt> */
3568805Smckusick 			p_stack[--tos] = dohead;
3578805Smckusick 			i_l_follow = il[tos];
3588805Smckusick 			break;
3598805Smckusick 
3608805Smckusick 		    case ifstmt:
3618805Smckusick 		    /* <if> <stmt> */
3628805Smckusick 			p_stack[--tos] = ifhead;
3638805Smckusick 			for (i = tos - 1;
3648805Smckusick 				(
3658805Smckusick 				    p_stack[i] != stmt
3668805Smckusick 				    &&
3678805Smckusick 				    p_stack[i] != stmtl
3688805Smckusick 				    &&
3698805Smckusick 				    p_stack[i] != lbrace
3708805Smckusick 				);
3718805Smckusick 				--i);
3728805Smckusick 			i_l_follow = il[i];
3738805Smckusick 		    /* for the time being, we will assume that there is no else
3748805Smckusick 		       on this if, and set the indentation level accordingly.
3758805Smckusick 		       If an else is scanned, it will be fixed up later */
3768805Smckusick 			break;
3778805Smckusick 
3788805Smckusick 		    case swstmt:
3798805Smckusick 		    /* <switch> <stmt> */
3808805Smckusick 			case_ind = cstk[tos - 1];
3818805Smckusick 
3828805Smckusick 		    case decl: /* finish of a declaration */
3838805Smckusick 		    case elsehead:
3848805Smckusick 		    /* <<if> <stmt> else> <stmt> */
3858805Smckusick 		    case forstmt:
3868805Smckusick 		    /* <for> <stmt> */
3878805Smckusick 		    case whilestmt:
3888805Smckusick 		    /* <while> <stmt> */
3898805Smckusick 			p_stack[--tos] = stmt;
3908805Smckusick 			i_l_follow = il[tos];
3918805Smckusick 			break;
3928805Smckusick 
3938805Smckusick 		    default:   /* <anything else> <stmt> */
3948805Smckusick 			return;
3958805Smckusick 
3968805Smckusick 		}	       /* end of section for <stmt> on top of stack */
3978805Smckusick 		break;
3988805Smckusick 
3998805Smckusick 	    case whilestmt:    /* while (...) on top */
4008805Smckusick 		if (p_stack[tos - 1] == dohead) {
4018805Smckusick 		/* it is termination of a do while */
4028805Smckusick 		    p_stack[--tos] = stmt;
4038805Smckusick 		    break;
4048805Smckusick 		}
4058805Smckusick 		else
4068805Smckusick 		    return;
4078805Smckusick 
4088805Smckusick 	    default: 	       /* anything else on top */
4098805Smckusick 		return;
4108805Smckusick 
4118805Smckusick 	}		       /* end of big switch */
4128805Smckusick 
4138805Smckusick     }			       /* end of reduction phase for (;;) */
4148805Smckusick }
415