121971Sdist /* 235500Sbostic * Copyright (c) 1985 Sun Microsystems, Inc. 335500Sbostic * Copyright (c) 1980 The Regents of the University of California. 433767Sbostic * Copyright (c) 1976 Board of Trustees of the University of Illinois. 533767Sbostic * All rights reserved. 633767Sbostic * 742688Sbostic * %sccs.include.redist.c% 821971Sdist */ 98805Smckusick 1021971Sdist #ifndef lint 11*46695Sbostic static char sccsid[] = "@(#)parse.c 5.12 (Berkeley) 02/26/91"; 1233767Sbostic #endif /* not lint */ 1321971Sdist 14*46695Sbostic #include <stdio.h> 1536969Sbostic #include "indent_globs.h" 1636969Sbostic #include "indent_codes.h" 178805Smckusick 1824456Smckusick parse(tk) 1924456Smckusick int tk; /* the code for the construct scanned */ 208805Smckusick { 2124456Smckusick int i; 228805Smckusick 238805Smckusick #ifdef debug 2424456Smckusick printf("%2d - %s\n", tk, token); 258805Smckusick #endif 2635500Sbostic 2724456Smckusick while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { 2824456Smckusick /* true if we have an if without an else */ 2924456Smckusick ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt 3035500Sbostic * reduction */ 3124456Smckusick reduce(); /* see if this allows any reduction */ 328805Smckusick } 338805Smckusick 348805Smckusick 3535500Sbostic switch (tk) { /* go on and figure out what to do with the 3635500Sbostic * input */ 378805Smckusick 3835500Sbostic case decl: /* scanned a declaration word */ 3935500Sbostic ps.search_brace = btype_2; 4035500Sbostic /* indicate that following brace should be on same line */ 4135500Sbostic if (ps.p_stack[ps.tos] != decl) { /* only put one declaration 4235500Sbostic * onto stack */ 4335500Sbostic break_comma = true; /* while in declaration, newline should be 4435500Sbostic * forced after comma */ 4535500Sbostic ps.p_stack[++ps.tos] = decl; 4635500Sbostic ps.il[ps.tos] = ps.i_l_follow; 478805Smckusick 4835500Sbostic if (ps.ljust_decl) {/* only do if we want left justified 4935500Sbostic * declarations */ 5035500Sbostic ps.ind_level = 0; 5135500Sbostic for (i = ps.tos - 1; i > 0; --i) 5235500Sbostic if (ps.p_stack[i] == decl) 5335500Sbostic ++ps.ind_level; /* indentation is number of 5435500Sbostic * declaration levels deep we are */ 5535500Sbostic ps.i_l_follow = ps.ind_level; 568805Smckusick } 5735500Sbostic } 5835500Sbostic break; 598805Smckusick 6035500Sbostic case ifstmt: /* scanned if (...) */ 6135500Sbostic if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ 6235500Sbostic ps.i_l_follow = ps.il[ps.tos]; 6335500Sbostic case dolit: /* 'do' */ 6435500Sbostic case forstmt: /* for (...) */ 6535500Sbostic ps.p_stack[++ps.tos] = tk; 6635500Sbostic ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 6735500Sbostic ++ps.i_l_follow; /* subsequent statements should be indented 1 */ 6835500Sbostic ps.search_brace = btype_2; 6935500Sbostic break; 708805Smckusick 7135500Sbostic case lbrace: /* scanned { */ 7235500Sbostic break_comma = false; /* don't break comma in an initial list */ 7335500Sbostic if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl 7435500Sbostic || ps.p_stack[ps.tos] == stmtl) 7535500Sbostic ++ps.i_l_follow; /* it is a random, isolated stmt group or a 7635500Sbostic * declaration */ 7735500Sbostic else { 7835500Sbostic if (s_code == e_code) { 7935500Sbostic /* 8035500Sbostic * only do this if there is nothing on the line 8135500Sbostic */ 8235500Sbostic --ps.ind_level; 8335500Sbostic /* 8435500Sbostic * it is a group as part of a while, for, etc. 8535500Sbostic */ 8635500Sbostic if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) 8724456Smckusick --ps.ind_level; 8835500Sbostic /* 8935500Sbostic * for a switch, brace should be two levels out from the code 9035500Sbostic */ 918805Smckusick } 9235500Sbostic } 938805Smckusick 9435500Sbostic ps.p_stack[++ps.tos] = lbrace; 9535500Sbostic ps.il[ps.tos] = ps.ind_level; 9635500Sbostic ps.p_stack[++ps.tos] = stmt; 9735500Sbostic /* allow null stmt between braces */ 9835500Sbostic ps.il[ps.tos] = ps.i_l_follow; 9935500Sbostic break; 10035500Sbostic 10135500Sbostic case whilestmt: /* scanned while (...) */ 10235500Sbostic if (ps.p_stack[ps.tos] == dohead) { 10335500Sbostic /* it is matched with do stmt */ 10435500Sbostic ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; 10535500Sbostic ps.p_stack[++ps.tos] = whilestmt; 10635500Sbostic ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 10735500Sbostic } 10835500Sbostic else { /* it is a while loop */ 10935500Sbostic ps.p_stack[++ps.tos] = whilestmt; 11024456Smckusick ps.il[ps.tos] = ps.i_l_follow; 11135500Sbostic ++ps.i_l_follow; 11235500Sbostic ps.search_brace = btype_2; 11335500Sbostic } 1148805Smckusick 11535500Sbostic break; 1168805Smckusick 11735500Sbostic case elselit: /* scanned an else */ 1188805Smckusick 11935500Sbostic if (ps.p_stack[ps.tos] != ifhead) 12035500Sbostic diag(1, "Unmatched 'else'"); 12135500Sbostic else { 12235500Sbostic ps.ind_level = ps.il[ps.tos]; /* indentation for else should 12335500Sbostic * be same as for if */ 12435500Sbostic ps.i_l_follow = ps.ind_level + 1; /* everything following should 12535500Sbostic * be in 1 level */ 12635500Sbostic ps.p_stack[ps.tos] = elsehead; 12735500Sbostic /* remember if with else */ 12835500Sbostic ps.search_brace = btype_2 | ps.else_if; 12935500Sbostic } 13035500Sbostic break; 1318805Smckusick 13235500Sbostic case rbrace: /* scanned a } */ 13335500Sbostic /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ 13435500Sbostic if (ps.p_stack[ps.tos - 1] == lbrace) { 13535500Sbostic ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; 13635500Sbostic ps.p_stack[ps.tos] = stmt; 13735500Sbostic } 13835500Sbostic else 13935500Sbostic diag(1, "Stmt nesting error."); 14035500Sbostic break; 1418805Smckusick 14235500Sbostic case swstmt: /* had switch (...) */ 14335500Sbostic ps.p_stack[++ps.tos] = swstmt; 14435500Sbostic ps.cstk[ps.tos] = case_ind; 14535500Sbostic /* save current case indent level */ 14635500Sbostic ps.il[ps.tos] = ps.i_l_follow; 14735500Sbostic case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one 14824456Smckusick * level down from 14924456Smckusick * switch */ 15035502Sbostic ps.i_l_follow += ps.case_indent + 1; /* statements should be two 15135500Sbostic * levels in */ 15235500Sbostic ps.search_brace = btype_2; 15335500Sbostic break; 1548805Smckusick 15535500Sbostic case semicolon: /* this indicates a simple stmt */ 15635500Sbostic break_comma = false; /* turn off flag to break after commas in a 15735500Sbostic * declaration */ 15835500Sbostic ps.p_stack[++ps.tos] = stmt; 15935500Sbostic ps.il[ps.tos] = ps.ind_level; 16035500Sbostic break; 1618805Smckusick 16235500Sbostic default: /* this is an error */ 16335500Sbostic diag(1, "Unknown code to parser"); 16435500Sbostic return; 1658805Smckusick 1668805Smckusick 16724456Smckusick } /* end of switch */ 1688805Smckusick 16924456Smckusick reduce(); /* see if any reduction can be done */ 17035500Sbostic 1718805Smckusick #ifdef debug 17224456Smckusick for (i = 1; i <= ps.tos; ++i) 17324456Smckusick printf("(%d %d)", ps.p_stack[i], ps.il[i]); 17424456Smckusick printf("\n"); 1758805Smckusick #endif 17635500Sbostic 1778805Smckusick return; 1788805Smckusick } 17935500Sbostic 18035500Sbostic /* 18135500Sbostic * NAME: reduce 18235500Sbostic * 18335500Sbostic * FUNCTION: Implements the reduce part of the parsing algorithm 18435500Sbostic * 18536555Sbostic * ALGORITHM: The following reductions are done. Reductions are repeated 18636555Sbostic * until no more are possible. 18735500Sbostic * 18836555Sbostic * Old TOS New TOS 18936555Sbostic * <stmt> <stmt> <stmtl> 19036555Sbostic * <stmtl> <stmt> <stmtl> 19136555Sbostic * do <stmt> "dostmt" 19236555Sbostic * if <stmt> "ifstmt" 19336555Sbostic * switch <stmt> <stmt> 19436555Sbostic * decl <stmt> <stmt> 19536555Sbostic * "ifelse" <stmt> <stmt> 19636555Sbostic * for <stmt> <stmt> 19736555Sbostic * while <stmt> <stmt> 19836555Sbostic * "dostmt" while <stmt> 19935500Sbostic * 20036555Sbostic * On each reduction, ps.i_l_follow (the indentation for the following line) 20136555Sbostic * is set to the indentation level associated with the old TOS. 20235500Sbostic * 20335500Sbostic * PARAMETERS: None 20435500Sbostic * 20535500Sbostic * RETURNS: Nothing 20635500Sbostic * 20735500Sbostic * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = 20835500Sbostic * 20935500Sbostic * CALLS: None 21035500Sbostic * 21136555Sbostic * CALLED BY: parse 21235500Sbostic * 21335500Sbostic * HISTORY: initial coding November 1976 D A Willcox of CAC 21435500Sbostic * 21536555Sbostic */ 2168805Smckusick /*----------------------------------------------*\ 21735500Sbostic | REDUCTION PHASE | 2188805Smckusick \*----------------------------------------------*/ 21935500Sbostic reduce() 22035500Sbostic { 2218805Smckusick 22224456Smckusick register int i; 2238805Smckusick 22435500Sbostic for (;;) { /* keep looping until there is nothing left to 22535500Sbostic * reduce */ 2268805Smckusick 22724456Smckusick switch (ps.p_stack[ps.tos]) { 2288805Smckusick 22935500Sbostic case stmt: 23035500Sbostic switch (ps.p_stack[ps.tos - 1]) { 2318805Smckusick 23235500Sbostic case stmt: 23335500Sbostic case stmtl: 23435500Sbostic /* stmtl stmt or stmt stmt */ 23535500Sbostic ps.p_stack[--ps.tos] = stmtl; 23635500Sbostic break; 2378805Smckusick 23835500Sbostic case dolit: /* <do> <stmt> */ 23935500Sbostic ps.p_stack[--ps.tos] = dohead; 24035500Sbostic ps.i_l_follow = ps.il[ps.tos]; 24135500Sbostic break; 2428805Smckusick 24335500Sbostic case ifstmt: 24435500Sbostic /* <if> <stmt> */ 24535500Sbostic ps.p_stack[--ps.tos] = ifhead; 24635500Sbostic for (i = ps.tos - 1; 24735500Sbostic ( 24835500Sbostic ps.p_stack[i] != stmt 24935500Sbostic && 25035500Sbostic ps.p_stack[i] != stmtl 25135500Sbostic && 25235500Sbostic ps.p_stack[i] != lbrace 25335500Sbostic ); 25435500Sbostic --i); 25535500Sbostic ps.i_l_follow = ps.il[i]; 25635500Sbostic /* 25735500Sbostic * for the time being, we will assume that there is no else on 25835500Sbostic * this if, and set the indentation level accordingly. If an 25935500Sbostic * else is scanned, it will be fixed up later 26035500Sbostic */ 26135500Sbostic break; 2628805Smckusick 26335500Sbostic case swstmt: 26435500Sbostic /* <switch> <stmt> */ 26535500Sbostic case_ind = ps.cstk[ps.tos - 1]; 2668805Smckusick 26735500Sbostic case decl: /* finish of a declaration */ 26835500Sbostic case elsehead: 26935500Sbostic /* <<if> <stmt> else> <stmt> */ 27035500Sbostic case forstmt: 27135500Sbostic /* <for> <stmt> */ 27235500Sbostic case whilestmt: 27335500Sbostic /* <while> <stmt> */ 27435500Sbostic ps.p_stack[--ps.tos] = stmt; 27535500Sbostic ps.i_l_follow = ps.il[ps.tos]; 27635500Sbostic break; 2778805Smckusick 27835500Sbostic default: /* <anything else> <stmt> */ 27935500Sbostic return; 2808805Smckusick 28135500Sbostic } /* end of section for <stmt> on top of stack */ 28235500Sbostic break; 28335500Sbostic 28435500Sbostic case whilestmt: /* while (...) on top */ 28535500Sbostic if (ps.p_stack[ps.tos - 1] == dohead) { 28635500Sbostic /* it is termination of a do while */ 28735500Sbostic ps.p_stack[--ps.tos] = stmt; 2888805Smckusick break; 28935500Sbostic } 29035500Sbostic else 29135500Sbostic return; 2928805Smckusick 29335500Sbostic default: /* anything else on top */ 29435500Sbostic return; 2958805Smckusick 29624456Smckusick } 29724456Smckusick } 2988805Smckusick } 299