11590Srgrimes/* 21590Srgrimes * Copyright (c) 1985 Sun Microsystems, Inc. 31590Srgrimes * Copyright (c) 1980, 1993 41590Srgrimes * The Regents of the University of California. All rights reserved. 51590Srgrimes * All rights reserved. 61590Srgrimes * 71590Srgrimes * Redistribution and use in source and binary forms, with or without 81590Srgrimes * modification, are permitted provided that the following conditions 91590Srgrimes * are met: 101590Srgrimes * 1. Redistributions of source code must retain the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer. 121590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 131590Srgrimes * notice, this list of conditions and the following disclaimer in the 141590Srgrimes * documentation and/or other materials provided with the distribution. 151590Srgrimes * 3. All advertising materials mentioning features or use of this software 161590Srgrimes * must display the following acknowledgement: 171590Srgrimes * This product includes software developed by the University of 181590Srgrimes * California, Berkeley and its contributors. 191590Srgrimes * 4. Neither the name of the University nor the names of its contributors 201590Srgrimes * may be used to endorse or promote products derived from this software 211590Srgrimes * without specific prior written permission. 221590Srgrimes * 231590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 241590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 251590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 261590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 271590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 281590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 291590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 301590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 311590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 321590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 331590Srgrimes * SUCH DAMAGE. 341590Srgrimes */ 35116390Scharnier 3685632Sschweikh#if 0 371590Srgrimes#ifndef lint 381590Srgrimesstatic char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93"; 391590Srgrimes#endif /* not lint */ 4085632Sschweikh#endif 41116390Scharnier 4299112Sobrien#include <sys/cdefs.h> 4399112Sobrien__FBSDID("$FreeBSD$"); 441590Srgrimes 451590Srgrimes#include <stdio.h> 461590Srgrimes#include "indent_globs.h" 471590Srgrimes#include "indent_codes.h" 4885632Sschweikh#include "indent.h" 491590Srgrimes 5085632Sschweikhstatic void reduce(void); 5185632Sschweikh 5285632Sschweikhvoid 5385632Sschweikhparse(int tk) /* tk: the code for the construct scanned */ 541590Srgrimes{ 551590Srgrimes int i; 561590Srgrimes 571590Srgrimes#ifdef debug 581590Srgrimes printf("%2d - %s\n", tk, token); 591590Srgrimes#endif 601590Srgrimes 611590Srgrimes while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { 621590Srgrimes /* true if we have an if without an else */ 631590Srgrimes ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt 641590Srgrimes * reduction */ 651590Srgrimes reduce(); /* see if this allows any reduction */ 661590Srgrimes } 671590Srgrimes 681590Srgrimes 691590Srgrimes switch (tk) { /* go on and figure out what to do with the 701590Srgrimes * input */ 711590Srgrimes 721590Srgrimes case decl: /* scanned a declaration word */ 731590Srgrimes ps.search_brace = btype_2; 741590Srgrimes /* indicate that following brace should be on same line */ 751590Srgrimes if (ps.p_stack[ps.tos] != decl) { /* only put one declaration 761590Srgrimes * onto stack */ 771590Srgrimes break_comma = true; /* while in declaration, newline should be 781590Srgrimes * forced after comma */ 791590Srgrimes ps.p_stack[++ps.tos] = decl; 801590Srgrimes ps.il[ps.tos] = ps.i_l_follow; 811590Srgrimes 821590Srgrimes if (ps.ljust_decl) {/* only do if we want left justified 831590Srgrimes * declarations */ 841590Srgrimes ps.ind_level = 0; 851590Srgrimes for (i = ps.tos - 1; i > 0; --i) 861590Srgrimes if (ps.p_stack[i] == decl) 871590Srgrimes ++ps.ind_level; /* indentation is number of 881590Srgrimes * declaration levels deep we are */ 891590Srgrimes ps.i_l_follow = ps.ind_level; 901590Srgrimes } 911590Srgrimes } 921590Srgrimes break; 931590Srgrimes 941590Srgrimes case ifstmt: /* scanned if (...) */ 951590Srgrimes if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ 961590Srgrimes ps.i_l_follow = ps.il[ps.tos]; 971590Srgrimes case dolit: /* 'do' */ 981590Srgrimes case forstmt: /* for (...) */ 991590Srgrimes ps.p_stack[++ps.tos] = tk; 1001590Srgrimes ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 1011590Srgrimes ++ps.i_l_follow; /* subsequent statements should be indented 1 */ 1021590Srgrimes ps.search_brace = btype_2; 1031590Srgrimes break; 1041590Srgrimes 1051590Srgrimes case lbrace: /* scanned { */ 1061590Srgrimes break_comma = false; /* don't break comma in an initial list */ 1071590Srgrimes if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl 1081590Srgrimes || ps.p_stack[ps.tos] == stmtl) 1091590Srgrimes ++ps.i_l_follow; /* it is a random, isolated stmt group or a 1101590Srgrimes * declaration */ 1111590Srgrimes else { 1121590Srgrimes if (s_code == e_code) { 1131590Srgrimes /* 1141590Srgrimes * only do this if there is nothing on the line 1151590Srgrimes */ 1161590Srgrimes --ps.ind_level; 1171590Srgrimes /* 1181590Srgrimes * it is a group as part of a while, for, etc. 1191590Srgrimes */ 1201590Srgrimes if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) 1211590Srgrimes --ps.ind_level; 1221590Srgrimes /* 1231590Srgrimes * for a switch, brace should be two levels out from the code 1241590Srgrimes */ 1251590Srgrimes } 1261590Srgrimes } 1271590Srgrimes 1281590Srgrimes ps.p_stack[++ps.tos] = lbrace; 1291590Srgrimes ps.il[ps.tos] = ps.ind_level; 1301590Srgrimes ps.p_stack[++ps.tos] = stmt; 1311590Srgrimes /* allow null stmt between braces */ 1321590Srgrimes ps.il[ps.tos] = ps.i_l_follow; 1331590Srgrimes break; 1341590Srgrimes 1351590Srgrimes case whilestmt: /* scanned while (...) */ 1361590Srgrimes if (ps.p_stack[ps.tos] == dohead) { 1371590Srgrimes /* it is matched with do stmt */ 1381590Srgrimes ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; 1391590Srgrimes ps.p_stack[++ps.tos] = whilestmt; 1401590Srgrimes ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 1411590Srgrimes } 1421590Srgrimes else { /* it is a while loop */ 1431590Srgrimes ps.p_stack[++ps.tos] = whilestmt; 1441590Srgrimes ps.il[ps.tos] = ps.i_l_follow; 1451590Srgrimes ++ps.i_l_follow; 1461590Srgrimes ps.search_brace = btype_2; 1471590Srgrimes } 1481590Srgrimes 1491590Srgrimes break; 1501590Srgrimes 1511590Srgrimes case elselit: /* scanned an else */ 1521590Srgrimes 1531590Srgrimes if (ps.p_stack[ps.tos] != ifhead) 15485632Sschweikh diag2(1, "Unmatched 'else'"); 1551590Srgrimes else { 1561590Srgrimes ps.ind_level = ps.il[ps.tos]; /* indentation for else should 1571590Srgrimes * be same as for if */ 1581590Srgrimes ps.i_l_follow = ps.ind_level + 1; /* everything following should 1591590Srgrimes * be in 1 level */ 1601590Srgrimes ps.p_stack[ps.tos] = elsehead; 1611590Srgrimes /* remember if with else */ 1621590Srgrimes ps.search_brace = btype_2 | ps.else_if; 1631590Srgrimes } 1641590Srgrimes break; 1651590Srgrimes 1661590Srgrimes case rbrace: /* scanned a } */ 1671590Srgrimes /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ 1681590Srgrimes if (ps.p_stack[ps.tos - 1] == lbrace) { 1691590Srgrimes ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; 1701590Srgrimes ps.p_stack[ps.tos] = stmt; 1711590Srgrimes } 1721590Srgrimes else 173116390Scharnier diag2(1, "Statement nesting error"); 1741590Srgrimes break; 1751590Srgrimes 1761590Srgrimes case swstmt: /* had switch (...) */ 1771590Srgrimes ps.p_stack[++ps.tos] = swstmt; 1781590Srgrimes ps.cstk[ps.tos] = case_ind; 1791590Srgrimes /* save current case indent level */ 1801590Srgrimes ps.il[ps.tos] = ps.i_l_follow; 1811590Srgrimes case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one 1821590Srgrimes * level down from 1831590Srgrimes * switch */ 1841590Srgrimes ps.i_l_follow += ps.case_indent + 1; /* statements should be two 1851590Srgrimes * levels in */ 1861590Srgrimes ps.search_brace = btype_2; 1871590Srgrimes break; 1881590Srgrimes 1891590Srgrimes case semicolon: /* this indicates a simple stmt */ 1901590Srgrimes break_comma = false; /* turn off flag to break after commas in a 1911590Srgrimes * declaration */ 1921590Srgrimes ps.p_stack[++ps.tos] = stmt; 1931590Srgrimes ps.il[ps.tos] = ps.ind_level; 1941590Srgrimes break; 1951590Srgrimes 1961590Srgrimes default: /* this is an error */ 19785632Sschweikh diag2(1, "Unknown code to parser"); 1981590Srgrimes return; 1991590Srgrimes 2001590Srgrimes 2011590Srgrimes } /* end of switch */ 2021590Srgrimes 2031590Srgrimes reduce(); /* see if any reduction can be done */ 2041590Srgrimes 2051590Srgrimes#ifdef debug 2061590Srgrimes for (i = 1; i <= ps.tos; ++i) 2071590Srgrimes printf("(%d %d)", ps.p_stack[i], ps.il[i]); 2081590Srgrimes printf("\n"); 2091590Srgrimes#endif 2101590Srgrimes 2111590Srgrimes return; 2121590Srgrimes} 2131590Srgrimes 2141590Srgrimes/* 2151590Srgrimes * NAME: reduce 2168874Srgrimes * 2171590Srgrimes * FUNCTION: Implements the reduce part of the parsing algorithm 2188874Srgrimes * 2191590Srgrimes * ALGORITHM: The following reductions are done. Reductions are repeated 2201590Srgrimes * until no more are possible. 2218874Srgrimes * 2221590Srgrimes * Old TOS New TOS 2231590Srgrimes * <stmt> <stmt> <stmtl> 2241590Srgrimes * <stmtl> <stmt> <stmtl> 2251590Srgrimes * do <stmt> "dostmt" 2261590Srgrimes * if <stmt> "ifstmt" 2271590Srgrimes * switch <stmt> <stmt> 2281590Srgrimes * decl <stmt> <stmt> 2291590Srgrimes * "ifelse" <stmt> <stmt> 2301590Srgrimes * for <stmt> <stmt> 2311590Srgrimes * while <stmt> <stmt> 2321590Srgrimes * "dostmt" while <stmt> 2338874Srgrimes * 2341590Srgrimes * On each reduction, ps.i_l_follow (the indentation for the following line) 2351590Srgrimes * is set to the indentation level associated with the old TOS. 2368874Srgrimes * 2371590Srgrimes * PARAMETERS: None 2388874Srgrimes * 2391590Srgrimes * RETURNS: Nothing 2408874Srgrimes * 2411590Srgrimes * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = 2428874Srgrimes * 2431590Srgrimes * CALLS: None 2448874Srgrimes * 2451590Srgrimes * CALLED BY: parse 2468874Srgrimes * 2471590Srgrimes * HISTORY: initial coding November 1976 D A Willcox of CAC 2488874Srgrimes * 2491590Srgrimes */ 2501590Srgrimes/*----------------------------------------------*\ 2511590Srgrimes| REDUCTION PHASE | 2521590Srgrimes\*----------------------------------------------*/ 25385632Sschweikhstatic void 25485632Sschweikhreduce(void) 2551590Srgrimes{ 25698771Sjmallett int i; 2571590Srgrimes 2581590Srgrimes for (;;) { /* keep looping until there is nothing left to 2591590Srgrimes * reduce */ 2601590Srgrimes 2611590Srgrimes switch (ps.p_stack[ps.tos]) { 2621590Srgrimes 2631590Srgrimes case stmt: 2641590Srgrimes switch (ps.p_stack[ps.tos - 1]) { 2651590Srgrimes 2661590Srgrimes case stmt: 2671590Srgrimes case stmtl: 2681590Srgrimes /* stmtl stmt or stmt stmt */ 2691590Srgrimes ps.p_stack[--ps.tos] = stmtl; 2701590Srgrimes break; 2711590Srgrimes 2721590Srgrimes case dolit: /* <do> <stmt> */ 2731590Srgrimes ps.p_stack[--ps.tos] = dohead; 2741590Srgrimes ps.i_l_follow = ps.il[ps.tos]; 2751590Srgrimes break; 2761590Srgrimes 2771590Srgrimes case ifstmt: 2781590Srgrimes /* <if> <stmt> */ 2791590Srgrimes ps.p_stack[--ps.tos] = ifhead; 2801590Srgrimes for (i = ps.tos - 1; 2811590Srgrimes ( 2821590Srgrimes ps.p_stack[i] != stmt 2831590Srgrimes && 2841590Srgrimes ps.p_stack[i] != stmtl 2851590Srgrimes && 2861590Srgrimes ps.p_stack[i] != lbrace 2871590Srgrimes ); 2881590Srgrimes --i); 2891590Srgrimes ps.i_l_follow = ps.il[i]; 2901590Srgrimes /* 2911590Srgrimes * for the time being, we will assume that there is no else on 2921590Srgrimes * this if, and set the indentation level accordingly. If an 2931590Srgrimes * else is scanned, it will be fixed up later 2941590Srgrimes */ 2951590Srgrimes break; 2961590Srgrimes 2971590Srgrimes case swstmt: 2981590Srgrimes /* <switch> <stmt> */ 2991590Srgrimes case_ind = ps.cstk[ps.tos - 1]; 3001590Srgrimes 3011590Srgrimes case decl: /* finish of a declaration */ 3021590Srgrimes case elsehead: 3031590Srgrimes /* <<if> <stmt> else> <stmt> */ 3041590Srgrimes case forstmt: 3051590Srgrimes /* <for> <stmt> */ 3061590Srgrimes case whilestmt: 3071590Srgrimes /* <while> <stmt> */ 3081590Srgrimes ps.p_stack[--ps.tos] = stmt; 3091590Srgrimes ps.i_l_follow = ps.il[ps.tos]; 3101590Srgrimes break; 3111590Srgrimes 3121590Srgrimes default: /* <anything else> <stmt> */ 3131590Srgrimes return; 3141590Srgrimes 3151590Srgrimes } /* end of section for <stmt> on top of stack */ 3161590Srgrimes break; 3171590Srgrimes 3181590Srgrimes case whilestmt: /* while (...) on top */ 3191590Srgrimes if (ps.p_stack[ps.tos - 1] == dohead) { 3201590Srgrimes /* it is termination of a do while */ 32147361Srnordier ps.tos -= 2; 3221590Srgrimes break; 3231590Srgrimes } 3241590Srgrimes else 3251590Srgrimes return; 3261590Srgrimes 3271590Srgrimes default: /* anything else on top */ 3281590Srgrimes return; 3291590Srgrimes 3301590Srgrimes } 3311590Srgrimes } 3321590Srgrimes} 333