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