|
|
1.1 ! root 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.3 (Berkeley) 9/8/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.