121971Sdist /* 221971Sdist * Copyright (c) 1980 Regents of the University of California. 3*33767Sbostic * Copyright (c) 1976 Board of Trustees of the University of Illinois. 4*33767Sbostic * All rights reserved. 5*33767Sbostic * 6*33767Sbostic * Redistribution and use in source and binary forms are permitted 7*33767Sbostic * provided that this notice is preserved and that due credit is given 8*33767Sbostic * to the University of California at Berkeley and the University of 9*33767Sbostic * Illinois at Urbana. The name of either University may not be used 10*33767Sbostic * to endorse or promote products derived from this software without 11*33767Sbostic * specific prior written permission. This software is provided 12*33767Sbostic * ``as is'' without express or implied warranty. 1321971Sdist */ 148805Smckusick 1521971Sdist #ifndef lint 16*33767Sbostic static char sccsid[] = "@(#)parse.c 5.5 (Berkeley) 03/22/88"; 17*33767Sbostic #endif /* not lint */ 1821971Sdist 19*33767Sbostic /* 2024456Smckusick * FILE NAME: 2124456Smckusick * parse.c 2224456Smckusick * 2324456Smckusick * PURPOSE: 2424456Smckusick * Contains the routines which keep track of the parse stack. 2524456Smckusick * 2624456Smckusick * GLOBALS: 2724456Smckusick * ps.p_stack = The parse stack, set by both routines 2824456Smckusick * ps.il = Stack of indentation levels, set by parse 2924456Smckusick * ps.cstk = Stack of case statement indentation levels, set by parse 3024456Smckusick * ps.tos = Pointer to top of stack, set by both routines. 3124456Smckusick * 3224456Smckusick * FUNCTIONS: 3324456Smckusick * parse 3424456Smckusick * reduce 3524456Smckusick */ 3624456Smckusick /*- 3724456Smckusick * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 3824456Smckusick * 3924456Smckusick * All rights reserved 4024456Smckusick * 4124456Smckusick * 4224456Smckusick * NAME: parse 4324456Smckusick * 4424456Smckusick * FUNCTION: Parse is given one input which is a "maxi token" just scanned 4524456Smckusick * from input. Maxi tokens are signifigant constructs such as else, {, 4624456Smckusick * do, if (...), etc. Parse works with reduce to maintain a parse stack 4724456Smckusick * of these constructs. Parse is responsible for the "shift" portion of 4824456Smckusick * the parse algorithm, and reduce handles the "reduce" portion. 4924456Smckusick * 5024456Smckusick * HISTORY: initial coding November 1976 D A Willcox of CAC 5124456Smckusick * 5224456Smckusick */ 538805Smckusick 5433231Sbostic #include "./indent_globs.h" 5533231Sbostic #include "./indent_codes.h" 568805Smckusick 578805Smckusick 588805Smckusick 598805Smckusick 6024456Smckusick parse(tk) 6124456Smckusick int tk; /* the code for the construct scanned */ 628805Smckusick { 6324456Smckusick int i; 648805Smckusick 658805Smckusick #ifdef debug 6624456Smckusick printf("%2d - %s\n", tk, token); 678805Smckusick #endif 6824456Smckusick while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { 6924456Smckusick /* true if we have an if without an else */ 7024456Smckusick ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt 7124456Smckusick * reduction */ 7224456Smckusick reduce(); /* see if this allows any reduction */ 738805Smckusick } 748805Smckusick 758805Smckusick 7624456Smckusick switch (tk) { /* go on and figure out what to do with 7724456Smckusick * the input */ 788805Smckusick 7924456Smckusick case decl: /* scanned a declaration word */ 8024456Smckusick ps.search_brace = btype_2; 8124456Smckusick /* indicate that following brace should be on same line */ 8224456Smckusick if (ps.p_stack[ps.tos] != decl) { /* only put one declaration onto 8324456Smckusick * stack */ 8424456Smckusick break_comma = true; /* while in declaration, newline 8524456Smckusick * should be forced after comma */ 8624456Smckusick ps.p_stack[++ps.tos] = decl; 8724456Smckusick ps.il[ps.tos] = ps.i_l_follow; 888805Smckusick 8924456Smckusick if (ps.ljust_decl) { /* only do if we want left 9024456Smckusick * justified declarations */ 9124456Smckusick ps.ind_level = 0; 9224456Smckusick for (i = ps.tos - 1; i > 0; --i) 9324456Smckusick if (ps.p_stack[i] == decl) 9424456Smckusick ++ps.ind_level; /* indentation is number 9524456Smckusick * of declaration levels 9624456Smckusick * deep we are */ 9724456Smckusick ps.i_l_follow = ps.ind_level; 988805Smckusick } 998805Smckusick } 1008805Smckusick break; 1018805Smckusick 10224456Smckusick case ifstmt: /* scanned if (...) */ 10324456Smckusick if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ 10424456Smckusick ps.i_l_follow = ps.il[ps.tos]; 10524456Smckusick case dolit: /* 'do' */ 10624456Smckusick case forstmt: /* for (...) */ 10724456Smckusick ps.p_stack[++ps.tos] = tk; 10824456Smckusick ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 10924456Smckusick ++ps.i_l_follow; /* subsequent statements should be 11024456Smckusick * indented 1 */ 11124456Smckusick ps.search_brace = btype_2; 1128805Smckusick break; 1138805Smckusick 11424456Smckusick case lbrace: /* scanned { */ 11524456Smckusick break_comma = false;/* don't break comma in an initial list */ 11624456Smckusick if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl 11724456Smckusick || ps.p_stack[ps.tos] == stmtl) 11824456Smckusick ++ps.i_l_follow; /* it is a random, isolated stmt group or 11924456Smckusick * a declaration */ 1208805Smckusick else { 1218805Smckusick if (s_code == e_code) { 12224456Smckusick /* only do this if there is nothing on the line */ 12324456Smckusick --ps.ind_level; 12424456Smckusick /* it is a group as part of a while, for, etc. */ 12524456Smckusick if (ps.p_stack[ps.tos] == swstmt && ps.case_indent) 12624456Smckusick --ps.ind_level; 12724456Smckusick /* 12824456Smckusick * for a switch, brace should be two levels out from 12924456Smckusick * the code 13024456Smckusick */ 1318805Smckusick } 1328805Smckusick } 1338805Smckusick 13424456Smckusick ps.p_stack[++ps.tos] = lbrace; 13524456Smckusick ps.il[ps.tos] = ps.ind_level; 13624456Smckusick ps.p_stack[++ps.tos] = stmt; 13724456Smckusick /* allow null stmt between braces */ 13824456Smckusick ps.il[ps.tos] = ps.i_l_follow; 1398805Smckusick break; 1408805Smckusick 14124456Smckusick case whilestmt: /* scanned while (...) */ 14224456Smckusick if (ps.p_stack[ps.tos] == dohead) { 14324456Smckusick /* it is matched with do stmt */ 14424456Smckusick ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; 14524456Smckusick ps.p_stack[++ps.tos] = whilestmt; 14624456Smckusick ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 1478805Smckusick } 14824456Smckusick else { /* it is a while loop */ 14924456Smckusick ps.p_stack[++ps.tos] = whilestmt; 15024456Smckusick ps.il[ps.tos] = ps.i_l_follow; 15124456Smckusick ++ps.i_l_follow; 15224456Smckusick ps.search_brace = btype_2; 1538805Smckusick } 1548805Smckusick 1558805Smckusick break; 1568805Smckusick 15724456Smckusick case elselit: /* scanned an else */ 1588805Smckusick 15924456Smckusick if (ps.p_stack[ps.tos] != ifhead) 16024456Smckusick diag(1,"Unmatched 'else'"); 1618805Smckusick else { 16224456Smckusick ps.ind_level = ps.il[ps.tos]; /* indentation for else should be same as for if */ 16324456Smckusick ps.i_l_follow = ps.ind_level + 1; /* everything following should be in 1 level */ 16424456Smckusick ps.p_stack[ps.tos] = elsehead; 16524456Smckusick /* remember if with else */ 16624456Smckusick ps.search_brace = btype_2; 1678805Smckusick } 1688805Smckusick 1698805Smckusick break; 1708805Smckusick 17124456Smckusick case rbrace: /* scanned a } */ 17224456Smckusick /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ 17324456Smckusick if (ps.p_stack[ps.tos - 1] == lbrace) { 17424456Smckusick ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; 17524456Smckusick ps.p_stack[ps.tos] = stmt; 1768805Smckusick } 17724456Smckusick else 17824456Smckusick diag(1,"Stmt nesting error."); 1798805Smckusick break; 1808805Smckusick 18124456Smckusick case swstmt: /* had switch (...) */ 18224456Smckusick ps.p_stack[++ps.tos] = swstmt; 18324456Smckusick ps.cstk[ps.tos] = case_ind; 18424456Smckusick /* save current case indent level */ 18524456Smckusick ps.il[ps.tos] = ps.i_l_follow; 18624456Smckusick case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one 18724456Smckusick * level down from 18824456Smckusick * switch */ 18933231Sbostic ps.i_l_follow += ps.case_indent + 1; /* statements should be 19024456Smckusick * two levels in */ 19124456Smckusick ps.search_brace = btype_2; 1928805Smckusick break; 1938805Smckusick 19424456Smckusick case semicolon: /* this indicates a simple stmt */ 19524456Smckusick break_comma = false;/* turn off flag to break after commas in 19624456Smckusick * a declaration */ 19724456Smckusick ps.p_stack[++ps.tos] = stmt; 19824456Smckusick ps.il[ps.tos] = ps.ind_level; 1998805Smckusick break; 2008805Smckusick 20124456Smckusick default: /* this is an error */ 20224456Smckusick diag(1,"Unknown code to parser"); 2038805Smckusick return; 2048805Smckusick 2058805Smckusick 20624456Smckusick } /* end of switch */ 2078805Smckusick 20824456Smckusick reduce(); /* see if any reduction can be done */ 2098805Smckusick #ifdef debug 21024456Smckusick for (i = 1; i <= ps.tos; ++i) 21124456Smckusick printf("(%d %d)", ps.p_stack[i], ps.il[i]); 21224456Smckusick printf("\n"); 2138805Smckusick #endif 2148805Smckusick return; 2158805Smckusick } 21624456Smckusick /* 21724456Smckusick * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 21824456Smckusick * 21924456Smckusick * All rights reserved 22024456Smckusick * 22124456Smckusick * 22224456Smckusick * NAME: reduce 22324456Smckusick * 22424456Smckusick * FUNCTION: Implements the reduce part of the parsing algorithm 22524456Smckusick * 22624456Smckusick * ALGORITHM: The following reductions are done. Reductions are repeated 22724456Smckusick * until no more are possible. 22824456Smckusick * 22924456Smckusick * Old TOS New TOS <stmt> <stmt> <stmtl> <stmtl> <stmt> <stmtl> do 23024456Smckusick * <stmt> "dostmt" if <stmt> "ifstmt" switch <stmt> <stmt> 23124456Smckusick * decl <stmt> <stmt> "ifelse" <stmt> <stmt> for <stmt> <stmt> 23224456Smckusick * while <stmt> <stmt> "dostmt" while <stmt> 23324456Smckusick * 23424456Smckusick * On each reduction, ps.i_l_follow (the indentation for the following line) is 23524456Smckusick * set to the indentation level associated with the old TOS. 23624456Smckusick * 23724456Smckusick * PARAMETERS: None 23824456Smckusick * 23924456Smckusick * RETURNS: Nothing 24024456Smckusick * 24124456Smckusick * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = 24224456Smckusick * 24324456Smckusick * CALLS: None 24424456Smckusick * 24524456Smckusick * CALLED BY: parse 24624456Smckusick * 24724456Smckusick * HISTORY: initial coding November 1976 D A Willcox of CAC 24824456Smckusick * 24924456Smckusick */ 2508805Smckusick /*----------------------------------------------*\ 25124456Smckusick * | REDUCTION PHASE 2528805Smckusick \*----------------------------------------------*/ 25324456Smckusick reduce() { 2548805Smckusick 25524456Smckusick register int i; 2568805Smckusick 25724456Smckusick for (;;) { /* keep looping until there is nothing 25824456Smckusick * left to reduce */ 2598805Smckusick 26024456Smckusick switch (ps.p_stack[ps.tos]) { 2618805Smckusick 2628805Smckusick case stmt: 26324456Smckusick switch (ps.p_stack[ps.tos - 1]) { 2648805Smckusick 2658805Smckusick case stmt: 2668805Smckusick case stmtl: 26724456Smckusick /* stmtl stmt or stmt stmt */ 26824456Smckusick ps.p_stack[--ps.tos] = stmtl; 2698805Smckusick break; 2708805Smckusick 27124456Smckusick case dolit: /* <do> <stmt> */ 27224456Smckusick ps.p_stack[--ps.tos] = dohead; 27324456Smckusick ps.i_l_follow = ps.il[ps.tos]; 2748805Smckusick break; 2758805Smckusick 2768805Smckusick case ifstmt: 27724456Smckusick /* <if> <stmt> */ 27824456Smckusick ps.p_stack[--ps.tos] = ifhead; 27924456Smckusick for (i = ps.tos - 1; 2808805Smckusick ( 28124456Smckusick ps.p_stack[i] != stmt 2828805Smckusick && 28324456Smckusick ps.p_stack[i] != stmtl 2848805Smckusick && 28524456Smckusick ps.p_stack[i] != lbrace 2868805Smckusick ); 2878805Smckusick --i); 28824456Smckusick ps.i_l_follow = ps.il[i]; 28924456Smckusick /* 29024456Smckusick * for the time being, we will assume that there 29124456Smckusick * is no else on this if, and set the indentation 29224456Smckusick * level accordingly. If an else is scanned, it 29324456Smckusick * will be fixed up later 29424456Smckusick */ 2958805Smckusick break; 2968805Smckusick 2978805Smckusick case swstmt: 29824456Smckusick /* <switch> <stmt> */ 29924456Smckusick case_ind = ps.cstk[ps.tos - 1]; 3008805Smckusick 30124456Smckusick case decl: /* finish of a declaration */ 3028805Smckusick case elsehead: 30324456Smckusick /* <<if> <stmt> else> <stmt> */ 3048805Smckusick case forstmt: 30524456Smckusick /* <for> <stmt> */ 3068805Smckusick case whilestmt: 30724456Smckusick /* <while> <stmt> */ 30824456Smckusick ps.p_stack[--ps.tos] = stmt; 30924456Smckusick ps.i_l_follow = ps.il[ps.tos]; 3108805Smckusick break; 3118805Smckusick 31224456Smckusick default: /* <anything else> <stmt> */ 3138805Smckusick return; 3148805Smckusick 31524456Smckusick } /* end of section for <stmt> on top of 31624456Smckusick * stack */ 3178805Smckusick break; 3188805Smckusick 31924456Smckusick case whilestmt: /* while (...) on top */ 32024456Smckusick if (ps.p_stack[ps.tos - 1] == dohead) { 32124456Smckusick /* it is termination of a do while */ 32224456Smckusick ps.p_stack[--ps.tos] = stmt; 3238805Smckusick break; 3248805Smckusick } 3258805Smckusick else 3268805Smckusick return; 3278805Smckusick 32824456Smckusick default: /* anything else on top */ 3298805Smckusick return; 3308805Smckusick 33124456Smckusick } 33224456Smckusick } 3338805Smckusick } 334