1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)parse.c 5.2 (Berkeley) 08/28/85"; 9 #endif not lint 10 11 /*- 12 * 13 * Copyright (C) 1976 14 * by the 15 * Board of Trustees 16 * of the 17 * University of Illinois 18 * 19 * All rights reserved 20 * 21 * 22 * FILE NAME: 23 * parse.c 24 * 25 * PURPOSE: 26 * Contains the routines which keep track of the parse stack. 27 * 28 * GLOBALS: 29 * ps.p_stack = The parse stack, set by both routines 30 * ps.il = Stack of indentation levels, set by parse 31 * ps.cstk = Stack of case statement indentation levels, set by parse 32 * ps.tos = Pointer to top of stack, set by both routines. 33 * 34 * FUNCTIONS: 35 * parse 36 * reduce 37 */ 38 /*- 39 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 40 * 41 * All rights reserved 42 * 43 * 44 * NAME: parse 45 * 46 * FUNCTION: Parse is given one input which is a "maxi token" just scanned 47 * from input. Maxi tokens are signifigant constructs such as else, {, 48 * do, if (...), etc. Parse works with reduce to maintain a parse stack 49 * of these constructs. Parse is responsible for the "shift" portion of 50 * the parse algorithm, and reduce handles the "reduce" portion. 51 * 52 * HISTORY: initial coding November 1976 D A Willcox of CAC 53 * 54 */ 55 56 #include "./indent_globs.h"; 57 #include "./indent_codes.h"; 58 59 60 61 62 parse(tk) 63 int tk; /* the code for the construct scanned */ 64 { 65 int i; 66 67 #ifdef debug 68 printf("%2d - %s\n", tk, token); 69 #endif 70 while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { 71 /* true if we have an if without an else */ 72 ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt 73 * reduction */ 74 reduce(); /* see if this allows any reduction */ 75 } 76 77 78 switch (tk) { /* go on and figure out what to do with 79 * the input */ 80 81 case decl: /* scanned a declaration word */ 82 ps.search_brace = btype_2; 83 /* indicate that following brace should be on same line */ 84 if (ps.p_stack[ps.tos] != decl) { /* only put one declaration onto 85 * stack */ 86 break_comma = true; /* while in declaration, newline 87 * should be forced after comma */ 88 ps.p_stack[++ps.tos] = decl; 89 ps.il[ps.tos] = ps.i_l_follow; 90 91 if (ps.ljust_decl) { /* only do if we want left 92 * justified declarations */ 93 ps.ind_level = 0; 94 for (i = ps.tos - 1; i > 0; --i) 95 if (ps.p_stack[i] == decl) 96 ++ps.ind_level; /* indentation is number 97 * of declaration levels 98 * deep we are */ 99 ps.i_l_follow = ps.ind_level; 100 } 101 } 102 break; 103 104 case ifstmt: /* scanned if (...) */ 105 if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ 106 ps.i_l_follow = ps.il[ps.tos]; 107 case dolit: /* 'do' */ 108 case forstmt: /* for (...) */ 109 ps.p_stack[++ps.tos] = tk; 110 ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 111 ++ps.i_l_follow; /* subsequent statements should be 112 * indented 1 */ 113 ps.search_brace = btype_2; 114 break; 115 116 case lbrace: /* scanned { */ 117 break_comma = false;/* don't break comma in an initial list */ 118 if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl 119 || ps.p_stack[ps.tos] == stmtl) 120 ++ps.i_l_follow; /* it is a random, isolated stmt group or 121 * a declaration */ 122 else { 123 if (s_code == e_code) { 124 /* only do this if there is nothing on the line */ 125 --ps.ind_level; 126 /* it is a group as part of a while, for, etc. */ 127 if (ps.p_stack[ps.tos] == swstmt && ps.case_indent) 128 --ps.ind_level; 129 /* 130 * for a switch, brace should be two levels out from 131 * the code 132 */ 133 } 134 } 135 136 ps.p_stack[++ps.tos] = lbrace; 137 ps.il[ps.tos] = ps.ind_level; 138 ps.p_stack[++ps.tos] = stmt; 139 /* allow null stmt between braces */ 140 ps.il[ps.tos] = ps.i_l_follow; 141 break; 142 143 case whilestmt: /* scanned while (...) */ 144 if (ps.p_stack[ps.tos] == dohead) { 145 /* it is matched with do stmt */ 146 ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; 147 ps.p_stack[++ps.tos] = whilestmt; 148 ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 149 } 150 else { /* it is a while loop */ 151 ps.p_stack[++ps.tos] = whilestmt; 152 ps.il[ps.tos] = ps.i_l_follow; 153 ++ps.i_l_follow; 154 ps.search_brace = btype_2; 155 } 156 157 break; 158 159 case elselit: /* scanned an else */ 160 161 if (ps.p_stack[ps.tos] != ifhead) 162 diag(1,"Unmatched 'else'"); 163 else { 164 ps.ind_level = ps.il[ps.tos]; /* indentation for else should be same as for if */ 165 ps.i_l_follow = ps.ind_level + 1; /* everything following should be in 1 level */ 166 ps.p_stack[ps.tos] = elsehead; 167 /* remember if with else */ 168 ps.search_brace = btype_2; 169 } 170 171 break; 172 173 case rbrace: /* scanned a } */ 174 /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ 175 if (ps.p_stack[ps.tos - 1] == lbrace) { 176 ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; 177 ps.p_stack[ps.tos] = stmt; 178 } 179 else 180 diag(1,"Stmt nesting error."); 181 break; 182 183 case swstmt: /* had switch (...) */ 184 ps.p_stack[++ps.tos] = swstmt; 185 ps.cstk[ps.tos] = case_ind; 186 /* save current case indent level */ 187 ps.il[ps.tos] = ps.i_l_follow; 188 case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one 189 * level down from 190 * switch */ 191 ps.i_l_follow + = ps.case_indent + 1; /* statements should be 192 * two levels in */ 193 ps.search_brace = btype_2; 194 break; 195 196 case semicolon: /* this indicates a simple stmt */ 197 break_comma = false;/* turn off flag to break after commas in 198 * a declaration */ 199 ps.p_stack[++ps.tos] = stmt; 200 ps.il[ps.tos] = ps.ind_level; 201 break; 202 203 default: /* this is an error */ 204 diag(1,"Unknown code to parser"); 205 return; 206 207 208 } /* end of switch */ 209 210 reduce(); /* see if any reduction can be done */ 211 #ifdef debug 212 for (i = 1; i <= ps.tos; ++i) 213 printf("(%d %d)", ps.p_stack[i], ps.il[i]); 214 printf("\n"); 215 #endif 216 return; 217 } 218 /* 219 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 220 * 221 * All rights reserved 222 * 223 * 224 * NAME: reduce 225 * 226 * FUNCTION: Implements the reduce part of the parsing algorithm 227 * 228 * ALGORITHM: The following reductions are done. Reductions are repeated 229 * until no more are possible. 230 * 231 * Old TOS New TOS <stmt> <stmt> <stmtl> <stmtl> <stmt> <stmtl> do 232 * <stmt> "dostmt" if <stmt> "ifstmt" switch <stmt> <stmt> 233 * decl <stmt> <stmt> "ifelse" <stmt> <stmt> for <stmt> <stmt> 234 * while <stmt> <stmt> "dostmt" while <stmt> 235 * 236 * On each reduction, ps.i_l_follow (the indentation for the following line) is 237 * set to the indentation level associated with the old TOS. 238 * 239 * PARAMETERS: None 240 * 241 * RETURNS: Nothing 242 * 243 * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = 244 * 245 * CALLS: None 246 * 247 * CALLED BY: parse 248 * 249 * HISTORY: initial coding November 1976 D A Willcox of CAC 250 * 251 */ 252 /*----------------------------------------------*\ 253 * | REDUCTION PHASE 254 \*----------------------------------------------*/ 255 reduce() { 256 257 register int i; 258 259 for (;;) { /* keep looping until there is nothing 260 * left to reduce */ 261 262 switch (ps.p_stack[ps.tos]) { 263 264 case stmt: 265 switch (ps.p_stack[ps.tos - 1]) { 266 267 case stmt: 268 case stmtl: 269 /* stmtl stmt or stmt stmt */ 270 ps.p_stack[--ps.tos] = stmtl; 271 break; 272 273 case dolit: /* <do> <stmt> */ 274 ps.p_stack[--ps.tos] = dohead; 275 ps.i_l_follow = ps.il[ps.tos]; 276 break; 277 278 case ifstmt: 279 /* <if> <stmt> */ 280 ps.p_stack[--ps.tos] = ifhead; 281 for (i = ps.tos - 1; 282 ( 283 ps.p_stack[i] != stmt 284 && 285 ps.p_stack[i] != stmtl 286 && 287 ps.p_stack[i] != lbrace 288 ); 289 --i); 290 ps.i_l_follow = ps.il[i]; 291 /* 292 * for the time being, we will assume that there 293 * is no else on this if, and set the indentation 294 * level accordingly. If an else is scanned, it 295 * will be fixed up later 296 */ 297 break; 298 299 case swstmt: 300 /* <switch> <stmt> */ 301 case_ind = ps.cstk[ps.tos - 1]; 302 303 case decl: /* finish of a declaration */ 304 case elsehead: 305 /* <<if> <stmt> else> <stmt> */ 306 case forstmt: 307 /* <for> <stmt> */ 308 case whilestmt: 309 /* <while> <stmt> */ 310 ps.p_stack[--ps.tos] = stmt; 311 ps.i_l_follow = ps.il[ps.tos]; 312 break; 313 314 default: /* <anything else> <stmt> */ 315 return; 316 317 } /* end of section for <stmt> on top of 318 * stack */ 319 break; 320 321 case whilestmt: /* while (...) on top */ 322 if (ps.p_stack[ps.tos - 1] == dohead) { 323 /* it is termination of a do while */ 324 ps.p_stack[--ps.tos] = stmt; 325 break; 326 } 327 else 328 return; 329 330 default: /* anything else on top */ 331 return; 332 333 } 334 } 335 } 336