From bd056b6eeaee036c2eb8fc4c463d96ec751f6dcc Mon Sep 17 00:00:00 2001 From: rillig Date: Tue, 9 Mar 2021 18:21:01 +0000 Subject: [PATCH] indent: extract reduce_stmt from reduce This refactoring reduces the indentation of the code, as well as removing any ambiguity as to which 'switch' statement a 'break' belongs, as there are no more nested 'switch' statements. No functional change. --- usr.bin/indent/parse.c | 172 ++++++++++++++++------------------------- 1 file changed, 67 insertions(+), 105 deletions(-) diff --git a/usr.bin/indent/parse.c b/usr.bin/indent/parse.c index c21de076d71b..a4b764799b15 100644 --- a/usr.bin/indent/parse.c +++ b/usr.bin/indent/parse.c @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.15 2021/03/09 16:48:28 rillig Exp $ */ +/* $NetBSD: parse.c,v 1.16 2021/03/09 18:21:01 rillig Exp $ */ /*- * SPDX-License-Identifier: BSD-4-Clause @@ -232,116 +232,78 @@ parse(token_type tk) /* tk: the code for the construct scanned */ #endif } -/* - * NAME: reduce - * - * FUNCTION: Implements the reduce part of the parsing algorithm - * - * ALGORITHM: The following reductions are done. Reductions are repeated - * until no more are possible. - * - * Old TOS New TOS - * - * - * do "dostmt" - * if "ifstmt" - * switch - * decl - * "ifelse" - * for - * while - * "dostmt" while - * - * On each reduction, ps.i_l_follow (the indentation for the following line) - * is set to the indentation level associated with the old TOS. - * - * PARAMETERS: None - * - * RETURNS: Nothing - * - * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = - * - * CALLS: None - * - * CALLED BY: parse - * - * HISTORY: initial coding November 1976 D A Willcox of CAC - * - */ /*----------------------------------------------*\ | REDUCTION PHASE | \*----------------------------------------------*/ + +/* + * Try to combine the statement on the top of the parse stack with the symbol + * directly below it, replacing these two symbols with a single symbol. + */ +static int +reduce_stmt(void) +{ + switch (ps.p_stack[ps.tos - 1]) { + + case stmt: /* stmt stmt */ + case stmtl: /* stmtl stmt */ + ps.p_stack[--ps.tos] = stmtl; + return true; + + case dolit: /* do */ + ps.p_stack[--ps.tos] = dohead; + ps.i_l_follow = ps.il[ps.tos]; + return true; + + case ifstmt: /* if () */ + ps.p_stack[--ps.tos] = ifhead; + int i = ps.tos - 1; + while (ps.p_stack[i] != stmt && + ps.p_stack[i] != stmtl && + ps.p_stack[i] != lbrace) + --i; + ps.i_l_follow = ps.il[i]; + /* + * for the time being, we will assume that there is no else on + * this if, and set the indentation level accordingly. If an + * else is scanned, it will be fixed up later + */ + return true; + + case swstmt: /* switch () */ + case_ind = ps.cstk[ps.tos - 1]; + /* FALLTHROUGH */ + case decl: /* finish of a declaration */ + case elsehead: /* if () else */ + case forstmt: /* for (<...>) */ + case whilestmt: /* while () */ + ps.p_stack[--ps.tos] = stmt; + ps.i_l_follow = ps.il[ps.tos]; + return true; + + default: /* */ + return false; + } +} + +/* + * Repeatedly try to reduce the top two symbols on the parse stack to a + * single symbol, until no more reductions are possible. + * + * On each reduction, ps.i_l_follow (the indentation for the following line) + * is set to the indentation level associated with the old TOS. + */ static void reduce(void) { - int i; - - for (;;) { /* keep looping until there is nothing left to - * reduce */ - - switch (ps.p_stack[ps.tos]) { - - case stmt: - switch (ps.p_stack[ps.tos - 1]) { - - case stmt: /* stmt stmt */ - case stmtl: /* stmtl stmt */ - ps.p_stack[--ps.tos] = stmtl; - break; - - case dolit: /* */ - ps.p_stack[--ps.tos] = dohead; - ps.i_l_follow = ps.il[ps.tos]; - break; - - case ifstmt: /* */ - ps.p_stack[--ps.tos] = ifhead; - for (i = ps.tos - 1; - ( - ps.p_stack[i] != stmt - && - ps.p_stack[i] != stmtl - && - ps.p_stack[i] != lbrace - ); - --i); - ps.i_l_follow = ps.il[i]; - /* - * for the time being, we will assume that there is no else on - * this if, and set the indentation level accordingly. If an - * else is scanned, it will be fixed up later - */ - break; - - case swstmt: /* */ - case_ind = ps.cstk[ps.tos - 1]; - /* FALLTHROUGH */ - case decl: /* finish of a declaration */ - case elsehead: /* else> */ - case forstmt: /* */ - case whilestmt: /* */ - ps.p_stack[--ps.tos] = stmt; - ps.i_l_follow = ps.il[ps.tos]; - break; - - default: /* */ - return; - - } /* end of section for on top of stack */ - break; - - case whilestmt: /* while (...) on top */ - if (ps.p_stack[ps.tos - 1] == dohead) { - /* it is termination of a do while */ - ps.tos -= 2; - break; - } - else - return; - - default: /* anything else on top */ - return; - +again: + if (ps.p_stack[ps.tos] == stmt) { + if (reduce_stmt()) + goto again; + } else if (ps.p_stack[ps.tos] == whilestmt) { + if (ps.p_stack[ps.tos - 1] == dohead) { + ps.tos -= 2; + goto again; } } }