121971Sdist /* 235500Sbostic * Copyright (c) 1985 Sun Microsystems, Inc. 335500Sbostic * Copyright (c) 1980 The Regents of the University of California. 433767Sbostic * Copyright (c) 1976 Board of Trustees of the University of Illinois. 533767Sbostic * All rights reserved. 633767Sbostic * 733767Sbostic * Redistribution and use in source and binary forms are permitted 834885Sbostic * provided that the above copyright notice and this paragraph are 934885Sbostic * duplicated in all such forms and that any documentation, 1034885Sbostic * advertising materials, and other materials related to such 1134885Sbostic * distribution and use acknowledge that the software was developed 1235500Sbostic * by the University of California, Berkeley, the University of Illinois, 1335500Sbostic * Urbana, and Sun Microsystems, Inc. The name of either University 1435500Sbostic * or Sun Microsystems may not be used to endorse or promote products 1535500Sbostic * derived from this software without specific prior written permission. 1634885Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1734885Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1834885Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1921971Sdist */ 208805Smckusick 2121971Sdist #ifndef lint 22*35502Sbostic static char sccsid[] = "@(#)parse.c 5.8 (Berkeley) 09/15/88"; 2333767Sbostic #endif /* not lint */ 2421971Sdist 25*35502Sbostic #include "./indent_globs.h" 26*35502Sbostic #include "./indent_codes.h" 278805Smckusick 288805Smckusick 298805Smckusick 308805Smckusick 3124456Smckusick parse(tk) 3224456Smckusick int tk; /* the code for the construct scanned */ 338805Smckusick { 3424456Smckusick int i; 358805Smckusick 368805Smckusick #ifdef debug 3724456Smckusick printf("%2d - %s\n", tk, token); 388805Smckusick #endif 3935500Sbostic 4024456Smckusick while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { 4124456Smckusick /* true if we have an if without an else */ 4224456Smckusick ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt 4335500Sbostic * reduction */ 4424456Smckusick reduce(); /* see if this allows any reduction */ 458805Smckusick } 468805Smckusick 478805Smckusick 4835500Sbostic switch (tk) { /* go on and figure out what to do with the 4935500Sbostic * input */ 508805Smckusick 5135500Sbostic case decl: /* scanned a declaration word */ 5235500Sbostic ps.search_brace = btype_2; 5335500Sbostic /* indicate that following brace should be on same line */ 5435500Sbostic if (ps.p_stack[ps.tos] != decl) { /* only put one declaration 5535500Sbostic * onto stack */ 5635500Sbostic break_comma = true; /* while in declaration, newline should be 5735500Sbostic * forced after comma */ 5835500Sbostic ps.p_stack[++ps.tos] = decl; 5935500Sbostic ps.il[ps.tos] = ps.i_l_follow; 608805Smckusick 6135500Sbostic if (ps.ljust_decl) {/* only do if we want left justified 6235500Sbostic * declarations */ 6335500Sbostic ps.ind_level = 0; 6435500Sbostic for (i = ps.tos - 1; i > 0; --i) 6535500Sbostic if (ps.p_stack[i] == decl) 6635500Sbostic ++ps.ind_level; /* indentation is number of 6735500Sbostic * declaration levels deep we are */ 6835500Sbostic ps.i_l_follow = ps.ind_level; 698805Smckusick } 7035500Sbostic } 7135500Sbostic break; 728805Smckusick 7335500Sbostic case ifstmt: /* scanned if (...) */ 7435500Sbostic if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ 7535500Sbostic ps.i_l_follow = ps.il[ps.tos]; 7635500Sbostic case dolit: /* 'do' */ 7735500Sbostic case forstmt: /* for (...) */ 7835500Sbostic ps.p_stack[++ps.tos] = tk; 7935500Sbostic ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 8035500Sbostic ++ps.i_l_follow; /* subsequent statements should be indented 1 */ 8135500Sbostic ps.search_brace = btype_2; 8235500Sbostic break; 838805Smckusick 8435500Sbostic case lbrace: /* scanned { */ 8535500Sbostic break_comma = false; /* don't break comma in an initial list */ 8635500Sbostic if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl 8735500Sbostic || ps.p_stack[ps.tos] == stmtl) 8835500Sbostic ++ps.i_l_follow; /* it is a random, isolated stmt group or a 8935500Sbostic * declaration */ 9035500Sbostic else { 9135500Sbostic if (s_code == e_code) { 9235500Sbostic /* 9335500Sbostic * only do this if there is nothing on the line 9435500Sbostic */ 9535500Sbostic --ps.ind_level; 9635500Sbostic /* 9735500Sbostic * it is a group as part of a while, for, etc. 9835500Sbostic */ 9935500Sbostic if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) 10024456Smckusick --ps.ind_level; 10135500Sbostic /* 10235500Sbostic * for a switch, brace should be two levels out from the code 10335500Sbostic */ 1048805Smckusick } 10535500Sbostic } 1068805Smckusick 10735500Sbostic ps.p_stack[++ps.tos] = lbrace; 10835500Sbostic ps.il[ps.tos] = ps.ind_level; 10935500Sbostic ps.p_stack[++ps.tos] = stmt; 11035500Sbostic /* allow null stmt between braces */ 11135500Sbostic ps.il[ps.tos] = ps.i_l_follow; 11235500Sbostic break; 11335500Sbostic 11435500Sbostic case whilestmt: /* scanned while (...) */ 11535500Sbostic if (ps.p_stack[ps.tos] == dohead) { 11635500Sbostic /* it is matched with do stmt */ 11735500Sbostic ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; 11835500Sbostic ps.p_stack[++ps.tos] = whilestmt; 11935500Sbostic ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 12035500Sbostic } 12135500Sbostic else { /* it is a while loop */ 12235500Sbostic ps.p_stack[++ps.tos] = whilestmt; 12324456Smckusick ps.il[ps.tos] = ps.i_l_follow; 12435500Sbostic ++ps.i_l_follow; 12535500Sbostic ps.search_brace = btype_2; 12635500Sbostic } 1278805Smckusick 12835500Sbostic break; 1298805Smckusick 13035500Sbostic case elselit: /* scanned an else */ 1318805Smckusick 13235500Sbostic if (ps.p_stack[ps.tos] != ifhead) 13335500Sbostic diag(1, "Unmatched 'else'"); 13435500Sbostic else { 13535500Sbostic ps.ind_level = ps.il[ps.tos]; /* indentation for else should 13635500Sbostic * be same as for if */ 13735500Sbostic ps.i_l_follow = ps.ind_level + 1; /* everything following should 13835500Sbostic * be in 1 level */ 13935500Sbostic ps.p_stack[ps.tos] = elsehead; 14035500Sbostic /* remember if with else */ 14135500Sbostic ps.search_brace = btype_2 | ps.else_if; 14235500Sbostic } 14335500Sbostic break; 1448805Smckusick 14535500Sbostic case rbrace: /* scanned a } */ 14635500Sbostic /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ 14735500Sbostic if (ps.p_stack[ps.tos - 1] == lbrace) { 14835500Sbostic ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; 14935500Sbostic ps.p_stack[ps.tos] = stmt; 15035500Sbostic } 15135500Sbostic else 15235500Sbostic diag(1, "Stmt nesting error."); 15335500Sbostic break; 1548805Smckusick 15535500Sbostic case swstmt: /* had switch (...) */ 15635500Sbostic ps.p_stack[++ps.tos] = swstmt; 15735500Sbostic ps.cstk[ps.tos] = case_ind; 15835500Sbostic /* save current case indent level */ 15935500Sbostic ps.il[ps.tos] = ps.i_l_follow; 16035500Sbostic case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one 16124456Smckusick * level down from 16224456Smckusick * switch */ 163*35502Sbostic ps.i_l_follow += ps.case_indent + 1; /* statements should be two 16435500Sbostic * levels in */ 16535500Sbostic ps.search_brace = btype_2; 16635500Sbostic break; 1678805Smckusick 16835500Sbostic case semicolon: /* this indicates a simple stmt */ 16935500Sbostic break_comma = false; /* turn off flag to break after commas in a 17035500Sbostic * declaration */ 17135500Sbostic ps.p_stack[++ps.tos] = stmt; 17235500Sbostic ps.il[ps.tos] = ps.ind_level; 17335500Sbostic break; 1748805Smckusick 17535500Sbostic default: /* this is an error */ 17635500Sbostic diag(1, "Unknown code to parser"); 17735500Sbostic return; 1788805Smckusick 1798805Smckusick 18024456Smckusick } /* end of switch */ 1818805Smckusick 18224456Smckusick reduce(); /* see if any reduction can be done */ 18335500Sbostic 1848805Smckusick #ifdef debug 18524456Smckusick for (i = 1; i <= ps.tos; ++i) 18624456Smckusick printf("(%d %d)", ps.p_stack[i], ps.il[i]); 18724456Smckusick printf("\n"); 1888805Smckusick #endif 18935500Sbostic 1908805Smckusick return; 1918805Smckusick } 19235500Sbostic 19335500Sbostic /* 19435500Sbostic * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 19535500Sbostic * 19635500Sbostic * All rights reserved 19735500Sbostic * 19835500Sbostic * 19935500Sbostic * NAME: reduce 20035500Sbostic * 20135500Sbostic * FUNCTION: Implements the reduce part of the parsing algorithm 20235500Sbostic * 20335500Sbostic * ALGORITHM: The following reductions are done. Reductions are repeated until 20435500Sbostic * no more are possible. 20535500Sbostic * 20624456Smckusick * Old TOS New TOS <stmt> <stmt> <stmtl> <stmtl> <stmt> <stmtl> do 20735500Sbostic * <stmt> "dostmt" if <stmt> "ifstmt" switch <stmt> <stmt> decl 20835500Sbostic * <stmt> <stmt> "ifelse" <stmt> <stmt> for <stmt> <stmt> while 20935500Sbostic * <stmt> <stmt> "dostmt" while <stmt> 21035500Sbostic * 21124456Smckusick * On each reduction, ps.i_l_follow (the indentation for the following line) is 21235500Sbostic * set to the indentation level associated with the old TOS. 21335500Sbostic * 21435500Sbostic * PARAMETERS: None 21535500Sbostic * 21635500Sbostic * RETURNS: Nothing 21735500Sbostic * 21835500Sbostic * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = 21935500Sbostic * 22035500Sbostic * CALLS: None 22135500Sbostic * 22224456Smckusick * CALLED BY: parse 22335500Sbostic * 22435500Sbostic * HISTORY: initial coding November 1976 D A Willcox of CAC 22535500Sbostic * 22624456Smckusick */ 2278805Smckusick /*----------------------------------------------*\ 22835500Sbostic | REDUCTION PHASE | 2298805Smckusick \*----------------------------------------------*/ 23035500Sbostic reduce() 23135500Sbostic { 2328805Smckusick 23324456Smckusick register int i; 2348805Smckusick 23535500Sbostic for (;;) { /* keep looping until there is nothing left to 23635500Sbostic * reduce */ 2378805Smckusick 23824456Smckusick switch (ps.p_stack[ps.tos]) { 2398805Smckusick 24035500Sbostic case stmt: 24135500Sbostic switch (ps.p_stack[ps.tos - 1]) { 2428805Smckusick 24335500Sbostic case stmt: 24435500Sbostic case stmtl: 24535500Sbostic /* stmtl stmt or stmt stmt */ 24635500Sbostic ps.p_stack[--ps.tos] = stmtl; 24735500Sbostic break; 2488805Smckusick 24935500Sbostic case dolit: /* <do> <stmt> */ 25035500Sbostic ps.p_stack[--ps.tos] = dohead; 25135500Sbostic ps.i_l_follow = ps.il[ps.tos]; 25235500Sbostic break; 2538805Smckusick 25435500Sbostic case ifstmt: 25535500Sbostic /* <if> <stmt> */ 25635500Sbostic ps.p_stack[--ps.tos] = ifhead; 25735500Sbostic for (i = ps.tos - 1; 25835500Sbostic ( 25935500Sbostic ps.p_stack[i] != stmt 26035500Sbostic && 26135500Sbostic ps.p_stack[i] != stmtl 26235500Sbostic && 26335500Sbostic ps.p_stack[i] != lbrace 26435500Sbostic ); 26535500Sbostic --i); 26635500Sbostic ps.i_l_follow = ps.il[i]; 26735500Sbostic /* 26835500Sbostic * for the time being, we will assume that there is no else on 26935500Sbostic * this if, and set the indentation level accordingly. If an 27035500Sbostic * else is scanned, it will be fixed up later 27135500Sbostic */ 27235500Sbostic break; 2738805Smckusick 27435500Sbostic case swstmt: 27535500Sbostic /* <switch> <stmt> */ 27635500Sbostic case_ind = ps.cstk[ps.tos - 1]; 2778805Smckusick 27835500Sbostic case decl: /* finish of a declaration */ 27935500Sbostic case elsehead: 28035500Sbostic /* <<if> <stmt> else> <stmt> */ 28135500Sbostic case forstmt: 28235500Sbostic /* <for> <stmt> */ 28335500Sbostic case whilestmt: 28435500Sbostic /* <while> <stmt> */ 28535500Sbostic ps.p_stack[--ps.tos] = stmt; 28635500Sbostic ps.i_l_follow = ps.il[ps.tos]; 28735500Sbostic break; 2888805Smckusick 28935500Sbostic default: /* <anything else> <stmt> */ 29035500Sbostic return; 2918805Smckusick 29235500Sbostic } /* end of section for <stmt> on top of stack */ 29335500Sbostic break; 29435500Sbostic 29535500Sbostic case whilestmt: /* while (...) on top */ 29635500Sbostic if (ps.p_stack[ps.tos - 1] == dohead) { 29735500Sbostic /* it is termination of a do while */ 29835500Sbostic ps.p_stack[--ps.tos] = stmt; 2998805Smckusick break; 30035500Sbostic } 30135500Sbostic else 30235500Sbostic return; 3038805Smckusick 30435500Sbostic default: /* anything else on top */ 30535500Sbostic return; 3068805Smckusick 30724456Smckusick } 30824456Smckusick } 3098805Smckusick } 310