/* * Copyright (c) 1985 Sun Microsystems, Inc. * Copyright (c) 1980 The Regents of the University of California. * Copyright (c) 1976 Board of Trustees of the University of Illinois. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley, the University of Illinois, * Urbana, and Sun Microsystems, Inc. The name of either University * or Sun Microsystems may not be used to endorse or promote products * derived from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static char sccsid[] = "@(#)parse.c 5.8 (Berkeley) 9/15/88"; #endif /* not lint */ #include "indent_globs.h" struct parser_state *parser_state_tos; /* like ++parser_state_tos->tos but checks for stack overflow and extends stack if necessary. */ static int inc_pstack () { if (++parser_state_tos->tos >= parser_state_tos->p_stack_size) { parser_state_tos->p_stack_size *= 2; parser_state_tos->p_stack = (enum codes *) xrealloc (parser_state_tos->p_stack, parser_state_tos->p_stack_size * sizeof (enum codes)); parser_state_tos->il = (int *) xrealloc (parser_state_tos->il, parser_state_tos->p_stack_size * sizeof (int)); parser_state_tos->cstk = (int *) xrealloc (parser_state_tos->cstk, parser_state_tos->p_stack_size * sizeof (int)); } return parser_state_tos->tos; } void parse(tk) enum codes tk; /* the code for the construct scanned */ { int i; #ifdef debug printf("%2d - %s\n", tk, token); #endif while (parser_state_tos->p_stack[parser_state_tos->tos] == ifhead && tk != elselit) { /* true if we have an if without an else */ parser_state_tos->p_stack[parser_state_tos->tos] = stmt; /* apply the if(..) stmt ::= stmt * reduction */ reduce(); /* see if this allows any reduction */ } switch (tk) { /* go on and figure out what to do with the * input */ case decl: /* scanned a declaration word */ parser_state_tos->search_brace = btype_2; /* indicate that following brace should be on same line */ if (parser_state_tos->p_stack[parser_state_tos->tos] != decl) { /* only put one declaration * onto stack */ break_comma = true; /* while in declaration, newline should be * forced after comma */ parser_state_tos->p_stack[inc_pstack()] = decl; parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow; if (ljust_decl) {/* only do if we want left justified * declarations */ parser_state_tos->ind_level = 0; for (i = parser_state_tos->tos - 1; i > 0; --i) if (parser_state_tos->p_stack[i] == decl) /* indentation is number of declaration levels deep we are times spaces per level */ parser_state_tos->ind_level += ind_size; parser_state_tos->i_l_follow = parser_state_tos->ind_level; } } break; case ifstmt: /* scanned if (...) */ if (parser_state_tos->p_stack[parser_state_tos->tos] == elsehead && else_if) /* "else if ..." */ parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos]; case dolit: /* 'do' */ case forstmt: /* for (...) */ inc_pstack(); parser_state_tos->p_stack[parser_state_tos->tos] = tk; parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level = parser_state_tos->i_l_follow; parser_state_tos->i_l_follow += ind_size; /* subsequent statements should be indented 1 */ parser_state_tos->search_brace = btype_2; break; case lbrace: /* scanned { */ break_comma = false; /* don't break comma in an initial list */ if (parser_state_tos->p_stack[parser_state_tos->tos] == stmt || parser_state_tos->p_stack[parser_state_tos->tos] == decl || parser_state_tos->p_stack[parser_state_tos->tos] == stmtl) /* it is a random, isolated stmt group or a declaration */ parser_state_tos->i_l_follow += ind_size; else { if (s_code == e_code) { /* * only do this if there is nothing on the line */ parser_state_tos->ind_level -= ind_size; /* * it is a group as part of a while, for, etc. */ /* For -bl formatting, indent by brace_indent additional spaces e.g. if (foo == bar) { <--> brace_indent spaces (in this example, 4) */ if (!btype_2) { parser_state_tos->ind_level += brace_indent; parser_state_tos->i_l_follow += brace_indent; if (parser_state_tos->p_stack[parser_state_tos->tos] == swstmt) case_ind += brace_indent; } if (parser_state_tos->p_stack[parser_state_tos->tos] == swstmt && case_indent >= ind_size) parser_state_tos->ind_level -= ind_size; /* * for a switch, brace should be two levels out from the code */ } } inc_pstack(); parser_state_tos->p_stack[parser_state_tos->tos] = lbrace; parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level; inc_pstack(); parser_state_tos->p_stack[parser_state_tos->tos] = stmt; /* allow null stmt between braces */ parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow; break; case whilestmt: /* scanned while (...) */ if (parser_state_tos->p_stack[parser_state_tos->tos] == dohead) { /* it is matched with do stmt */ parser_state_tos->ind_level = parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos]; inc_pstack(); parser_state_tos->p_stack[parser_state_tos->tos] = whilestmt; parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level = parser_state_tos->i_l_follow; } else { /* it is a while loop */ inc_pstack(); parser_state_tos->p_stack[parser_state_tos->tos] = whilestmt; parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow; parser_state_tos->i_l_follow += ind_size; parser_state_tos->search_brace = btype_2; } break; case elselit: /* scanned an else */ if (parser_state_tos->p_stack[parser_state_tos->tos] != ifhead) diag(1, "Unmatched 'else'"); else { parser_state_tos->ind_level = parser_state_tos->il[parser_state_tos->tos]; /* indentation for else should * be same as for if */ /* everything following should be in 1 level */ parser_state_tos->i_l_follow = parser_state_tos->ind_level + ind_size; parser_state_tos->p_stack[parser_state_tos->tos] = elsehead; /* remember if with else */ parser_state_tos->search_brace = btype_2 | else_if; } break; case rbrace: /* scanned a } */ /* stack should have or */ if (parser_state_tos->p_stack[parser_state_tos->tos - 1] == lbrace) { parser_state_tos->ind_level = parser_state_tos->i_l_follow = parser_state_tos->il[--parser_state_tos->tos]; parser_state_tos->p_stack[parser_state_tos->tos] = stmt; } else diag(1, "Stmt nesting error."); break; case swstmt: /* had switch (...) */ inc_pstack(); parser_state_tos->p_stack[parser_state_tos->tos] = swstmt; parser_state_tos->cstk[parser_state_tos->tos] = case_ind; /* save current case indent level */ parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow; case_ind = parser_state_tos->i_l_follow + case_indent; /* cases should be one * level down from * switch */ /* statements should be two levels in */ parser_state_tos->i_l_follow += case_indent + ind_size; parser_state_tos->search_brace = btype_2; break; case semicolon: /* this indicates a simple stmt */ break_comma = false; /* turn off flag to break after commas in a * declaration */ inc_pstack(); parser_state_tos->p_stack[parser_state_tos->tos] = stmt; parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level; break; default: /* this is an error */ diag(1, "Unknown code to parser"); return; } /* end of switch */ reduce(); /* see if any reduction can be done */ #ifdef debug for (i = 1; i <= parser_state_tos->tos; ++i) printf("(%d %d)", parser_state_tos->p_stack[i], parser_state_tos->il[i]); printf("\n"); #endif return; } /* * Copyright (C) 1976 by the Board of Trustees of the University of Illinois * * All rights reserved * * * NAME: reduce * * FUNCTION: Implements the reduce part of the parsing algorithm * * ALGORITHM: The following reductions are done. Reductions are repeated until * no more are possible. * * Old TOS New TOS do * "dostmt" if "ifstmt" switch decl * "ifelse" for while * "dostmt" while * * On each reduction, parser_state_tos->i_l_follow (the indentation for the following line) is * set to the indentation level associated with the old TOS. * * PARAMETERS: None * * RETURNS: Nothing * * GLOBALS: parser_state_tos->cstk parser_state_tos->i_l_follow = parser_state_tos->il parser_state_tos->p_stack = parser_state_tos->tos = * * CALLS: None * * CALLED BY: parse  * * HISTORY: initial coding November 1976 D A Willcox of CAC * */ /*----------------------------------------------*\ | REDUCTION PHASE | \*----------------------------------------------*/ reduce() { register int i; for (;;) { /* keep looping until there is nothing left to * reduce */ switch (parser_state_tos->p_stack[parser_state_tos->tos]) { case stmt: switch (parser_state_tos->p_stack[parser_state_tos->tos - 1]) { case stmt: case stmtl: /* stmtl stmt or stmt stmt */ parser_state_tos->p_stack[--parser_state_tos->tos] = stmtl; break; case dolit: /* */ parser_state_tos->p_stack[--parser_state_tos->tos] = dohead; parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos]; break; case ifstmt: /* */ parser_state_tos->p_stack[--parser_state_tos->tos] = ifhead; for (i = parser_state_tos->tos - 1; ( parser_state_tos->p_stack[i] != stmt && parser_state_tos->p_stack[i] != stmtl && parser_state_tos->p_stack[i] != lbrace ); --i); parser_state_tos->i_l_follow = parser_state_tos->il[i]; /* * for the time being, we will assume that there is no else on * this if, and set the indentation level accordingly. If an * else is scanned, it will be fixed up later */ break; case swstmt: /* */ case_ind = parser_state_tos->cstk[parser_state_tos->tos - 1]; case decl: /* finish of a declaration */ case elsehead: /* < else> */ case forstmt: /* */ case whilestmt: /* */ parser_state_tos->p_stack[--parser_state_tos->tos] = stmt; parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos]; break; default: /* */ return; } /* end of section for on top of stack */ break; case whilestmt: /* while (...) on top */ if (parser_state_tos->p_stack[parser_state_tos->tos - 1] == dohead) { /* it is termination of a do while */ parser_state_tos->p_stack[--parser_state_tos->tos] = stmt; break; } else return; default: /* anything else on top */ return; } } }