121971Sdist /* 221971Sdist * Copyright (c) 1980 Regents of the University of California. 321971Sdist * All rights reserved. The Berkeley software License Agreement 421971Sdist * specifies the terms and conditions for redistribution. 521971Sdist */ 68805Smckusick 721971Sdist #ifndef lint 8*24456Smckusick static char sccsid[] = "@(#)parse.c 5.2 (Berkeley) 08/28/85"; 921971Sdist #endif not lint 1021971Sdist 11*24456Smckusick /*- 12*24456Smckusick * 13*24456Smckusick * Copyright (C) 1976 14*24456Smckusick * by the 15*24456Smckusick * Board of Trustees 16*24456Smckusick * of the 17*24456Smckusick * University of Illinois 18*24456Smckusick * 19*24456Smckusick * All rights reserved 20*24456Smckusick * 21*24456Smckusick * 22*24456Smckusick * FILE NAME: 23*24456Smckusick * parse.c 24*24456Smckusick * 25*24456Smckusick * PURPOSE: 26*24456Smckusick * Contains the routines which keep track of the parse stack. 27*24456Smckusick * 28*24456Smckusick * GLOBALS: 29*24456Smckusick * ps.p_stack = The parse stack, set by both routines 30*24456Smckusick * ps.il = Stack of indentation levels, set by parse 31*24456Smckusick * ps.cstk = Stack of case statement indentation levels, set by parse 32*24456Smckusick * ps.tos = Pointer to top of stack, set by both routines. 33*24456Smckusick * 34*24456Smckusick * FUNCTIONS: 35*24456Smckusick * parse 36*24456Smckusick * reduce 37*24456Smckusick */ 38*24456Smckusick /*- 39*24456Smckusick * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 40*24456Smckusick * 41*24456Smckusick * All rights reserved 42*24456Smckusick * 43*24456Smckusick * 44*24456Smckusick * NAME: parse 45*24456Smckusick * 46*24456Smckusick * FUNCTION: Parse is given one input which is a "maxi token" just scanned 47*24456Smckusick * from input. Maxi tokens are signifigant constructs such as else, {, 48*24456Smckusick * do, if (...), etc. Parse works with reduce to maintain a parse stack 49*24456Smckusick * of these constructs. Parse is responsible for the "shift" portion of 50*24456Smckusick * the parse algorithm, and reduce handles the "reduce" portion. 51*24456Smckusick * 52*24456Smckusick * HISTORY: initial coding November 1976 D A Willcox of CAC 53*24456Smckusick * 54*24456Smckusick */ 558805Smckusick 568805Smckusick #include "./indent_globs.h"; 578805Smckusick #include "./indent_codes.h"; 588805Smckusick 598805Smckusick 608805Smckusick 618805Smckusick 62*24456Smckusick parse(tk) 63*24456Smckusick int tk; /* the code for the construct scanned */ 648805Smckusick { 65*24456Smckusick int i; 668805Smckusick 678805Smckusick #ifdef debug 68*24456Smckusick printf("%2d - %s\n", tk, token); 698805Smckusick #endif 70*24456Smckusick while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { 71*24456Smckusick /* true if we have an if without an else */ 72*24456Smckusick ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt 73*24456Smckusick * reduction */ 74*24456Smckusick reduce(); /* see if this allows any reduction */ 758805Smckusick } 768805Smckusick 778805Smckusick 78*24456Smckusick switch (tk) { /* go on and figure out what to do with 79*24456Smckusick * the input */ 808805Smckusick 81*24456Smckusick case decl: /* scanned a declaration word */ 82*24456Smckusick ps.search_brace = btype_2; 83*24456Smckusick /* indicate that following brace should be on same line */ 84*24456Smckusick if (ps.p_stack[ps.tos] != decl) { /* only put one declaration onto 85*24456Smckusick * stack */ 86*24456Smckusick break_comma = true; /* while in declaration, newline 87*24456Smckusick * should be forced after comma */ 88*24456Smckusick ps.p_stack[++ps.tos] = decl; 89*24456Smckusick ps.il[ps.tos] = ps.i_l_follow; 908805Smckusick 91*24456Smckusick if (ps.ljust_decl) { /* only do if we want left 92*24456Smckusick * justified declarations */ 93*24456Smckusick ps.ind_level = 0; 94*24456Smckusick for (i = ps.tos - 1; i > 0; --i) 95*24456Smckusick if (ps.p_stack[i] == decl) 96*24456Smckusick ++ps.ind_level; /* indentation is number 97*24456Smckusick * of declaration levels 98*24456Smckusick * deep we are */ 99*24456Smckusick ps.i_l_follow = ps.ind_level; 1008805Smckusick } 1018805Smckusick } 1028805Smckusick break; 1038805Smckusick 104*24456Smckusick case ifstmt: /* scanned if (...) */ 105*24456Smckusick if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ 106*24456Smckusick ps.i_l_follow = ps.il[ps.tos]; 107*24456Smckusick case dolit: /* 'do' */ 108*24456Smckusick case forstmt: /* for (...) */ 109*24456Smckusick ps.p_stack[++ps.tos] = tk; 110*24456Smckusick ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 111*24456Smckusick ++ps.i_l_follow; /* subsequent statements should be 112*24456Smckusick * indented 1 */ 113*24456Smckusick ps.search_brace = btype_2; 1148805Smckusick break; 1158805Smckusick 116*24456Smckusick case lbrace: /* scanned { */ 117*24456Smckusick break_comma = false;/* don't break comma in an initial list */ 118*24456Smckusick if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl 119*24456Smckusick || ps.p_stack[ps.tos] == stmtl) 120*24456Smckusick ++ps.i_l_follow; /* it is a random, isolated stmt group or 121*24456Smckusick * a declaration */ 1228805Smckusick else { 1238805Smckusick if (s_code == e_code) { 124*24456Smckusick /* only do this if there is nothing on the line */ 125*24456Smckusick --ps.ind_level; 126*24456Smckusick /* it is a group as part of a while, for, etc. */ 127*24456Smckusick if (ps.p_stack[ps.tos] == swstmt && ps.case_indent) 128*24456Smckusick --ps.ind_level; 129*24456Smckusick /* 130*24456Smckusick * for a switch, brace should be two levels out from 131*24456Smckusick * the code 132*24456Smckusick */ 1338805Smckusick } 1348805Smckusick } 1358805Smckusick 136*24456Smckusick ps.p_stack[++ps.tos] = lbrace; 137*24456Smckusick ps.il[ps.tos] = ps.ind_level; 138*24456Smckusick ps.p_stack[++ps.tos] = stmt; 139*24456Smckusick /* allow null stmt between braces */ 140*24456Smckusick ps.il[ps.tos] = ps.i_l_follow; 1418805Smckusick break; 1428805Smckusick 143*24456Smckusick case whilestmt: /* scanned while (...) */ 144*24456Smckusick if (ps.p_stack[ps.tos] == dohead) { 145*24456Smckusick /* it is matched with do stmt */ 146*24456Smckusick ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; 147*24456Smckusick ps.p_stack[++ps.tos] = whilestmt; 148*24456Smckusick ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 1498805Smckusick } 150*24456Smckusick else { /* it is a while loop */ 151*24456Smckusick ps.p_stack[++ps.tos] = whilestmt; 152*24456Smckusick ps.il[ps.tos] = ps.i_l_follow; 153*24456Smckusick ++ps.i_l_follow; 154*24456Smckusick ps.search_brace = btype_2; 1558805Smckusick } 1568805Smckusick 1578805Smckusick break; 1588805Smckusick 159*24456Smckusick case elselit: /* scanned an else */ 1608805Smckusick 161*24456Smckusick if (ps.p_stack[ps.tos] != ifhead) 162*24456Smckusick diag(1,"Unmatched 'else'"); 1638805Smckusick else { 164*24456Smckusick ps.ind_level = ps.il[ps.tos]; /* indentation for else should be same as for if */ 165*24456Smckusick ps.i_l_follow = ps.ind_level + 1; /* everything following should be in 1 level */ 166*24456Smckusick ps.p_stack[ps.tos] = elsehead; 167*24456Smckusick /* remember if with else */ 168*24456Smckusick ps.search_brace = btype_2; 1698805Smckusick } 1708805Smckusick 1718805Smckusick break; 1728805Smckusick 173*24456Smckusick case rbrace: /* scanned a } */ 174*24456Smckusick /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ 175*24456Smckusick if (ps.p_stack[ps.tos - 1] == lbrace) { 176*24456Smckusick ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; 177*24456Smckusick ps.p_stack[ps.tos] = stmt; 1788805Smckusick } 179*24456Smckusick else 180*24456Smckusick diag(1,"Stmt nesting error."); 1818805Smckusick break; 1828805Smckusick 183*24456Smckusick case swstmt: /* had switch (...) */ 184*24456Smckusick ps.p_stack[++ps.tos] = swstmt; 185*24456Smckusick ps.cstk[ps.tos] = case_ind; 186*24456Smckusick /* save current case indent level */ 187*24456Smckusick ps.il[ps.tos] = ps.i_l_follow; 188*24456Smckusick case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one 189*24456Smckusick * level down from 190*24456Smckusick * switch */ 191*24456Smckusick ps.i_l_follow + = ps.case_indent + 1; /* statements should be 192*24456Smckusick * two levels in */ 193*24456Smckusick ps.search_brace = btype_2; 1948805Smckusick break; 1958805Smckusick 196*24456Smckusick case semicolon: /* this indicates a simple stmt */ 197*24456Smckusick break_comma = false;/* turn off flag to break after commas in 198*24456Smckusick * a declaration */ 199*24456Smckusick ps.p_stack[++ps.tos] = stmt; 200*24456Smckusick ps.il[ps.tos] = ps.ind_level; 2018805Smckusick break; 2028805Smckusick 203*24456Smckusick default: /* this is an error */ 204*24456Smckusick diag(1,"Unknown code to parser"); 2058805Smckusick return; 2068805Smckusick 2078805Smckusick 208*24456Smckusick } /* end of switch */ 2098805Smckusick 210*24456Smckusick reduce(); /* see if any reduction can be done */ 2118805Smckusick #ifdef debug 212*24456Smckusick for (i = 1; i <= ps.tos; ++i) 213*24456Smckusick printf("(%d %d)", ps.p_stack[i], ps.il[i]); 214*24456Smckusick printf("\n"); 2158805Smckusick #endif 2168805Smckusick return; 2178805Smckusick } 218*24456Smckusick /* 219*24456Smckusick * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 220*24456Smckusick * 221*24456Smckusick * All rights reserved 222*24456Smckusick * 223*24456Smckusick * 224*24456Smckusick * NAME: reduce 225*24456Smckusick * 226*24456Smckusick * FUNCTION: Implements the reduce part of the parsing algorithm 227*24456Smckusick * 228*24456Smckusick * ALGORITHM: The following reductions are done. Reductions are repeated 229*24456Smckusick * until no more are possible. 230*24456Smckusick * 231*24456Smckusick * Old TOS New TOS <stmt> <stmt> <stmtl> <stmtl> <stmt> <stmtl> do 232*24456Smckusick * <stmt> "dostmt" if <stmt> "ifstmt" switch <stmt> <stmt> 233*24456Smckusick * decl <stmt> <stmt> "ifelse" <stmt> <stmt> for <stmt> <stmt> 234*24456Smckusick * while <stmt> <stmt> "dostmt" while <stmt> 235*24456Smckusick * 236*24456Smckusick * On each reduction, ps.i_l_follow (the indentation for the following line) is 237*24456Smckusick * set to the indentation level associated with the old TOS. 238*24456Smckusick * 239*24456Smckusick * PARAMETERS: None 240*24456Smckusick * 241*24456Smckusick * RETURNS: Nothing 242*24456Smckusick * 243*24456Smckusick * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = 244*24456Smckusick * 245*24456Smckusick * CALLS: None 246*24456Smckusick * 247*24456Smckusick * CALLED BY: parse 248*24456Smckusick * 249*24456Smckusick * HISTORY: initial coding November 1976 D A Willcox of CAC 250*24456Smckusick * 251*24456Smckusick */ 2528805Smckusick /*----------------------------------------------*\ 253*24456Smckusick * | REDUCTION PHASE 2548805Smckusick \*----------------------------------------------*/ 255*24456Smckusick reduce() { 2568805Smckusick 257*24456Smckusick register int i; 2588805Smckusick 259*24456Smckusick for (;;) { /* keep looping until there is nothing 260*24456Smckusick * left to reduce */ 2618805Smckusick 262*24456Smckusick switch (ps.p_stack[ps.tos]) { 2638805Smckusick 2648805Smckusick case stmt: 265*24456Smckusick switch (ps.p_stack[ps.tos - 1]) { 2668805Smckusick 2678805Smckusick case stmt: 2688805Smckusick case stmtl: 269*24456Smckusick /* stmtl stmt or stmt stmt */ 270*24456Smckusick ps.p_stack[--ps.tos] = stmtl; 2718805Smckusick break; 2728805Smckusick 273*24456Smckusick case dolit: /* <do> <stmt> */ 274*24456Smckusick ps.p_stack[--ps.tos] = dohead; 275*24456Smckusick ps.i_l_follow = ps.il[ps.tos]; 2768805Smckusick break; 2778805Smckusick 2788805Smckusick case ifstmt: 279*24456Smckusick /* <if> <stmt> */ 280*24456Smckusick ps.p_stack[--ps.tos] = ifhead; 281*24456Smckusick for (i = ps.tos - 1; 2828805Smckusick ( 283*24456Smckusick ps.p_stack[i] != stmt 2848805Smckusick && 285*24456Smckusick ps.p_stack[i] != stmtl 2868805Smckusick && 287*24456Smckusick ps.p_stack[i] != lbrace 2888805Smckusick ); 2898805Smckusick --i); 290*24456Smckusick ps.i_l_follow = ps.il[i]; 291*24456Smckusick /* 292*24456Smckusick * for the time being, we will assume that there 293*24456Smckusick * is no else on this if, and set the indentation 294*24456Smckusick * level accordingly. If an else is scanned, it 295*24456Smckusick * will be fixed up later 296*24456Smckusick */ 2978805Smckusick break; 2988805Smckusick 2998805Smckusick case swstmt: 300*24456Smckusick /* <switch> <stmt> */ 301*24456Smckusick case_ind = ps.cstk[ps.tos - 1]; 3028805Smckusick 303*24456Smckusick case decl: /* finish of a declaration */ 3048805Smckusick case elsehead: 305*24456Smckusick /* <<if> <stmt> else> <stmt> */ 3068805Smckusick case forstmt: 307*24456Smckusick /* <for> <stmt> */ 3088805Smckusick case whilestmt: 309*24456Smckusick /* <while> <stmt> */ 310*24456Smckusick ps.p_stack[--ps.tos] = stmt; 311*24456Smckusick ps.i_l_follow = ps.il[ps.tos]; 3128805Smckusick break; 3138805Smckusick 314*24456Smckusick default: /* <anything else> <stmt> */ 3158805Smckusick return; 3168805Smckusick 317*24456Smckusick } /* end of section for <stmt> on top of 318*24456Smckusick * stack */ 3198805Smckusick break; 3208805Smckusick 321*24456Smckusick case whilestmt: /* while (...) on top */ 322*24456Smckusick if (ps.p_stack[ps.tos - 1] == dohead) { 323*24456Smckusick /* it is termination of a do while */ 324*24456Smckusick ps.p_stack[--ps.tos] = stmt; 3258805Smckusick break; 3268805Smckusick } 3278805Smckusick else 3288805Smckusick return; 3298805Smckusick 330*24456Smckusick default: /* anything else on top */ 3318805Smckusick return; 3328805Smckusick 333*24456Smckusick } 334*24456Smckusick } 3358805Smckusick } 336