11590Srgrimes/*
21590Srgrimes * Copyright (c) 1985 Sun Microsystems, Inc.
31590Srgrimes * Copyright (c) 1980, 1993
41590Srgrimes *	The Regents of the University of California.  All rights reserved.
51590Srgrimes * All rights reserved.
61590Srgrimes *
71590Srgrimes * Redistribution and use in source and binary forms, with or without
81590Srgrimes * modification, are permitted provided that the following conditions
91590Srgrimes * are met:
101590Srgrimes * 1. Redistributions of source code must retain the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer.
121590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
131590Srgrimes *    notice, this list of conditions and the following disclaimer in the
141590Srgrimes *    documentation and/or other materials provided with the distribution.
151590Srgrimes * 3. All advertising materials mentioning features or use of this software
161590Srgrimes *    must display the following acknowledgement:
171590Srgrimes *	This product includes software developed by the University of
181590Srgrimes *	California, Berkeley and its contributors.
191590Srgrimes * 4. Neither the name of the University nor the names of its contributors
201590Srgrimes *    may be used to endorse or promote products derived from this software
211590Srgrimes *    without specific prior written permission.
221590Srgrimes *
231590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
241590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
251590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
261590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
271590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
281590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
291590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
301590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
311590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
321590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
331590Srgrimes * SUCH DAMAGE.
341590Srgrimes */
35116390Scharnier
3685632Sschweikh#if 0
371590Srgrimes#ifndef lint
381590Srgrimesstatic char sccsid[] = "@(#)parse.c	8.1 (Berkeley) 6/6/93";
391590Srgrimes#endif /* not lint */
4085632Sschweikh#endif
41116390Scharnier
4299112Sobrien#include <sys/cdefs.h>
4399112Sobrien__FBSDID("$FreeBSD$");
441590Srgrimes
451590Srgrimes#include <stdio.h>
461590Srgrimes#include "indent_globs.h"
471590Srgrimes#include "indent_codes.h"
4885632Sschweikh#include "indent.h"
491590Srgrimes
5085632Sschweikhstatic void reduce(void);
5185632Sschweikh
5285632Sschweikhvoid
5385632Sschweikhparse(int tk) /* tk: the code for the construct scanned */
541590Srgrimes{
551590Srgrimes    int         i;
561590Srgrimes
571590Srgrimes#ifdef debug
581590Srgrimes    printf("%2d - %s\n", tk, token);
591590Srgrimes#endif
601590Srgrimes
611590Srgrimes    while (ps.p_stack[ps.tos] == ifhead && tk != elselit) {
621590Srgrimes	/* true if we have an if without an else */
631590Srgrimes	ps.p_stack[ps.tos] = stmt;	/* apply the if(..) stmt ::= stmt
641590Srgrimes					 * reduction */
651590Srgrimes	reduce();		/* see if this allows any reduction */
661590Srgrimes    }
671590Srgrimes
681590Srgrimes
691590Srgrimes    switch (tk) {		/* go on and figure out what to do with the
701590Srgrimes				 * input */
711590Srgrimes
721590Srgrimes    case decl:			/* scanned a declaration word */
731590Srgrimes	ps.search_brace = btype_2;
741590Srgrimes	/* indicate that following brace should be on same line */
751590Srgrimes	if (ps.p_stack[ps.tos] != decl) {	/* only put one declaration
761590Srgrimes						 * onto stack */
771590Srgrimes	    break_comma = true;	/* while in declaration, newline should be
781590Srgrimes				 * forced after comma */
791590Srgrimes	    ps.p_stack[++ps.tos] = decl;
801590Srgrimes	    ps.il[ps.tos] = ps.i_l_follow;
811590Srgrimes
821590Srgrimes	    if (ps.ljust_decl) {/* only do if we want left justified
831590Srgrimes				 * declarations */
841590Srgrimes		ps.ind_level = 0;
851590Srgrimes		for (i = ps.tos - 1; i > 0; --i)
861590Srgrimes		    if (ps.p_stack[i] == decl)
871590Srgrimes			++ps.ind_level;	/* indentation is number of
881590Srgrimes					 * declaration levels deep we are */
891590Srgrimes		ps.i_l_follow = ps.ind_level;
901590Srgrimes	    }
911590Srgrimes	}
921590Srgrimes	break;
931590Srgrimes
941590Srgrimes    case ifstmt:		/* scanned if (...) */
951590Srgrimes	if (ps.p_stack[ps.tos] == elsehead && ps.else_if)	/* "else if ..." */
961590Srgrimes	    ps.i_l_follow = ps.il[ps.tos];
971590Srgrimes    case dolit:		/* 'do' */
981590Srgrimes    case forstmt:		/* for (...) */
991590Srgrimes	ps.p_stack[++ps.tos] = tk;
1001590Srgrimes	ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
1011590Srgrimes	++ps.i_l_follow;	/* subsequent statements should be indented 1 */
1021590Srgrimes	ps.search_brace = btype_2;
1031590Srgrimes	break;
1041590Srgrimes
1051590Srgrimes    case lbrace:		/* scanned { */
1061590Srgrimes	break_comma = false;	/* don't break comma in an initial list */
1071590Srgrimes	if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
1081590Srgrimes		|| ps.p_stack[ps.tos] == stmtl)
1091590Srgrimes	    ++ps.i_l_follow;	/* it is a random, isolated stmt group or a
1101590Srgrimes				 * declaration */
1111590Srgrimes	else {
1121590Srgrimes	    if (s_code == e_code) {
1131590Srgrimes		/*
1141590Srgrimes		 * only do this if there is nothing on the line
1151590Srgrimes		 */
1161590Srgrimes		--ps.ind_level;
1171590Srgrimes		/*
1181590Srgrimes		 * it is a group as part of a while, for, etc.
1191590Srgrimes		 */
1201590Srgrimes		if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1)
1211590Srgrimes		    --ps.ind_level;
1221590Srgrimes		/*
1231590Srgrimes		 * for a switch, brace should be two levels out from the code
1241590Srgrimes		 */
1251590Srgrimes	    }
1261590Srgrimes	}
1271590Srgrimes
1281590Srgrimes	ps.p_stack[++ps.tos] = lbrace;
1291590Srgrimes	ps.il[ps.tos] = ps.ind_level;
1301590Srgrimes	ps.p_stack[++ps.tos] = stmt;
1311590Srgrimes	/* allow null stmt between braces */
1321590Srgrimes	ps.il[ps.tos] = ps.i_l_follow;
1331590Srgrimes	break;
1341590Srgrimes
1351590Srgrimes    case whilestmt:		/* scanned while (...) */
1361590Srgrimes	if (ps.p_stack[ps.tos] == dohead) {
1371590Srgrimes	    /* it is matched with do stmt */
1381590Srgrimes	    ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
1391590Srgrimes	    ps.p_stack[++ps.tos] = whilestmt;
1401590Srgrimes	    ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
1411590Srgrimes	}
1421590Srgrimes	else {			/* it is a while loop */
1431590Srgrimes	    ps.p_stack[++ps.tos] = whilestmt;
1441590Srgrimes	    ps.il[ps.tos] = ps.i_l_follow;
1451590Srgrimes	    ++ps.i_l_follow;
1461590Srgrimes	    ps.search_brace = btype_2;
1471590Srgrimes	}
1481590Srgrimes
1491590Srgrimes	break;
1501590Srgrimes
1511590Srgrimes    case elselit:		/* scanned an else */
1521590Srgrimes
1531590Srgrimes	if (ps.p_stack[ps.tos] != ifhead)
15485632Sschweikh	    diag2(1, "Unmatched 'else'");
1551590Srgrimes	else {
1561590Srgrimes	    ps.ind_level = ps.il[ps.tos];	/* indentation for else should
1571590Srgrimes						 * be same as for if */
1581590Srgrimes	    ps.i_l_follow = ps.ind_level + 1;	/* everything following should
1591590Srgrimes						 * be in 1 level */
1601590Srgrimes	    ps.p_stack[ps.tos] = elsehead;
1611590Srgrimes	    /* remember if with else */
1621590Srgrimes	    ps.search_brace = btype_2 | ps.else_if;
1631590Srgrimes	}
1641590Srgrimes	break;
1651590Srgrimes
1661590Srgrimes    case rbrace:		/* scanned a } */
1671590Srgrimes	/* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
1681590Srgrimes	if (ps.p_stack[ps.tos - 1] == lbrace) {
1691590Srgrimes	    ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
1701590Srgrimes	    ps.p_stack[ps.tos] = stmt;
1711590Srgrimes	}
1721590Srgrimes	else
173116390Scharnier	    diag2(1, "Statement nesting error");
1741590Srgrimes	break;
1751590Srgrimes
1761590Srgrimes    case swstmt:		/* had switch (...) */
1771590Srgrimes	ps.p_stack[++ps.tos] = swstmt;
1781590Srgrimes	ps.cstk[ps.tos] = case_ind;
1791590Srgrimes	/* save current case indent level */
1801590Srgrimes	ps.il[ps.tos] = ps.i_l_follow;
1811590Srgrimes	case_ind = ps.i_l_follow + ps.case_indent;	/* cases should be one
1821590Srgrimes							 * level down from
1831590Srgrimes							 * switch */
1841590Srgrimes	ps.i_l_follow += ps.case_indent + 1;	/* statements should be two
1851590Srgrimes						 * levels in */
1861590Srgrimes	ps.search_brace = btype_2;
1871590Srgrimes	break;
1881590Srgrimes
1891590Srgrimes    case semicolon:		/* this indicates a simple stmt */
1901590Srgrimes	break_comma = false;	/* turn off flag to break after commas in a
1911590Srgrimes				 * declaration */
1921590Srgrimes	ps.p_stack[++ps.tos] = stmt;
1931590Srgrimes	ps.il[ps.tos] = ps.ind_level;
1941590Srgrimes	break;
1951590Srgrimes
1961590Srgrimes    default:			/* this is an error */
19785632Sschweikh	diag2(1, "Unknown code to parser");
1981590Srgrimes	return;
1991590Srgrimes
2001590Srgrimes
2011590Srgrimes    }				/* end of switch */
2021590Srgrimes
2031590Srgrimes    reduce();			/* see if any reduction can be done */
2041590Srgrimes
2051590Srgrimes#ifdef debug
2061590Srgrimes    for (i = 1; i <= ps.tos; ++i)
2071590Srgrimes	printf("(%d %d)", ps.p_stack[i], ps.il[i]);
2081590Srgrimes    printf("\n");
2091590Srgrimes#endif
2101590Srgrimes
2111590Srgrimes    return;
2121590Srgrimes}
2131590Srgrimes
2141590Srgrimes/*
2151590Srgrimes * NAME: reduce
2168874Srgrimes *
2171590Srgrimes * FUNCTION: Implements the reduce part of the parsing algorithm
2188874Srgrimes *
2191590Srgrimes * ALGORITHM: The following reductions are done.  Reductions are repeated
2201590Srgrimes *	until no more are possible.
2218874Srgrimes *
2221590Srgrimes * Old TOS		New TOS
2231590Srgrimes * <stmt> <stmt>	<stmtl>
2241590Srgrimes * <stmtl> <stmt>	<stmtl>
2251590Srgrimes * do <stmt>		"dostmt"
2261590Srgrimes * if <stmt>		"ifstmt"
2271590Srgrimes * switch <stmt>	<stmt>
2281590Srgrimes * decl <stmt>		<stmt>
2291590Srgrimes * "ifelse" <stmt>	<stmt>
2301590Srgrimes * for <stmt>		<stmt>
2311590Srgrimes * while <stmt>		<stmt>
2321590Srgrimes * "dostmt" while	<stmt>
2338874Srgrimes *
2341590Srgrimes * On each reduction, ps.i_l_follow (the indentation for the following line)
2351590Srgrimes * is set to the indentation level associated with the old TOS.
2368874Srgrimes *
2371590Srgrimes * PARAMETERS: None
2388874Srgrimes *
2391590Srgrimes * RETURNS: Nothing
2408874Srgrimes *
2411590Srgrimes * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
2428874Srgrimes *
2431590Srgrimes * CALLS: None
2448874Srgrimes *
2451590Srgrimes * CALLED BY: parse
2468874Srgrimes *
2471590Srgrimes * HISTORY: initial coding 	November 1976	D A Willcox of CAC
2488874Srgrimes *
2491590Srgrimes */
2501590Srgrimes/*----------------------------------------------*\
2511590Srgrimes|   REDUCTION PHASE				    |
2521590Srgrimes\*----------------------------------------------*/
25385632Sschweikhstatic void
25485632Sschweikhreduce(void)
2551590Srgrimes{
25698771Sjmallett    int i;
2571590Srgrimes
2581590Srgrimes    for (;;) {			/* keep looping until there is nothing left to
2591590Srgrimes				 * reduce */
2601590Srgrimes
2611590Srgrimes	switch (ps.p_stack[ps.tos]) {
2621590Srgrimes
2631590Srgrimes	case stmt:
2641590Srgrimes	    switch (ps.p_stack[ps.tos - 1]) {
2651590Srgrimes
2661590Srgrimes	    case stmt:
2671590Srgrimes	    case stmtl:
2681590Srgrimes		/* stmtl stmt or stmt stmt */
2691590Srgrimes		ps.p_stack[--ps.tos] = stmtl;
2701590Srgrimes		break;
2711590Srgrimes
2721590Srgrimes	    case dolit:	/* <do> <stmt> */
2731590Srgrimes		ps.p_stack[--ps.tos] = dohead;
2741590Srgrimes		ps.i_l_follow = ps.il[ps.tos];
2751590Srgrimes		break;
2761590Srgrimes
2771590Srgrimes	    case ifstmt:
2781590Srgrimes		/* <if> <stmt> */
2791590Srgrimes		ps.p_stack[--ps.tos] = ifhead;
2801590Srgrimes		for (i = ps.tos - 1;
2811590Srgrimes			(
2821590Srgrimes			 ps.p_stack[i] != stmt
2831590Srgrimes			 &&
2841590Srgrimes			 ps.p_stack[i] != stmtl
2851590Srgrimes			 &&
2861590Srgrimes			 ps.p_stack[i] != lbrace
2871590Srgrimes			 );
2881590Srgrimes			--i);
2891590Srgrimes		ps.i_l_follow = ps.il[i];
2901590Srgrimes		/*
2911590Srgrimes		 * for the time being, we will assume that there is no else on
2921590Srgrimes		 * this if, and set the indentation level accordingly. If an
2931590Srgrimes		 * else is scanned, it will be fixed up later
2941590Srgrimes		 */
2951590Srgrimes		break;
2961590Srgrimes
2971590Srgrimes	    case swstmt:
2981590Srgrimes		/* <switch> <stmt> */
2991590Srgrimes		case_ind = ps.cstk[ps.tos - 1];
3001590Srgrimes
3011590Srgrimes	    case decl:		/* finish of a declaration */
3021590Srgrimes	    case elsehead:
3031590Srgrimes		/* <<if> <stmt> else> <stmt> */
3041590Srgrimes	    case forstmt:
3051590Srgrimes		/* <for> <stmt> */
3061590Srgrimes	    case whilestmt:
3071590Srgrimes		/* <while> <stmt> */
3081590Srgrimes		ps.p_stack[--ps.tos] = stmt;
3091590Srgrimes		ps.i_l_follow = ps.il[ps.tos];
3101590Srgrimes		break;
3111590Srgrimes
3121590Srgrimes	    default:		/* <anything else> <stmt> */
3131590Srgrimes		return;
3141590Srgrimes
3151590Srgrimes	    }			/* end of section for <stmt> on top of stack */
3161590Srgrimes	    break;
3171590Srgrimes
3181590Srgrimes	case whilestmt:	/* while (...) on top */
3191590Srgrimes	    if (ps.p_stack[ps.tos - 1] == dohead) {
3201590Srgrimes		/* it is termination of a do while */
32147361Srnordier		ps.tos -= 2;
3221590Srgrimes		break;
3231590Srgrimes	    }
3241590Srgrimes	    else
3251590Srgrimes		return;
3261590Srgrimes
3271590Srgrimes	default:		/* anything else on top */
3281590Srgrimes	    return;
3291590Srgrimes
3301590Srgrimes	}
3311590Srgrimes    }
3321590Srgrimes}
333