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