1 /* 2 * Copyright (c) 1985 Sun Microsystems, Inc. 3 * Copyright (c) 1980 The Regents of the University of California. 4 * Copyright (c) 1976 Board of Trustees of the University of Illinois. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #ifndef lint 37 /*static char sccsid[] = "from: @(#)parse.c 5.12 (Berkeley) 2/26/91";*/ 38 static char rcsid[] = "$Id: parse.c,v 1.2 1993/08/01 18:14:30 mycroft Exp $"; 39 #endif /* not lint */ 40 41 #include <stdio.h> 42 #include "indent_globs.h" 43 #include "indent_codes.h" 44 45 parse(tk) 46 int tk; /* the code for the construct scanned */ 47 { 48 int i; 49 50 #ifdef debug 51 printf("%2d - %s\n", tk, token); 52 #endif 53 54 while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { 55 /* true if we have an if without an else */ 56 ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt 57 * reduction */ 58 reduce(); /* see if this allows any reduction */ 59 } 60 61 62 switch (tk) { /* go on and figure out what to do with the 63 * input */ 64 65 case decl: /* scanned a declaration word */ 66 ps.search_brace = btype_2; 67 /* indicate that following brace should be on same line */ 68 if (ps.p_stack[ps.tos] != decl) { /* only put one declaration 69 * onto stack */ 70 break_comma = true; /* while in declaration, newline should be 71 * forced after comma */ 72 ps.p_stack[++ps.tos] = decl; 73 ps.il[ps.tos] = ps.i_l_follow; 74 75 if (ps.ljust_decl) {/* only do if we want left justified 76 * declarations */ 77 ps.ind_level = 0; 78 for (i = ps.tos - 1; i > 0; --i) 79 if (ps.p_stack[i] == decl) 80 ++ps.ind_level; /* indentation is number of 81 * declaration levels deep we are */ 82 ps.i_l_follow = ps.ind_level; 83 } 84 } 85 break; 86 87 case ifstmt: /* scanned if (...) */ 88 if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ 89 ps.i_l_follow = ps.il[ps.tos]; 90 case dolit: /* 'do' */ 91 case forstmt: /* for (...) */ 92 ps.p_stack[++ps.tos] = tk; 93 ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 94 ++ps.i_l_follow; /* subsequent statements should be indented 1 */ 95 ps.search_brace = btype_2; 96 break; 97 98 case lbrace: /* scanned { */ 99 break_comma = false; /* don't break comma in an initial list */ 100 if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl 101 || ps.p_stack[ps.tos] == stmtl) 102 ++ps.i_l_follow; /* it is a random, isolated stmt group or a 103 * declaration */ 104 else { 105 if (s_code == e_code) { 106 /* 107 * only do this if there is nothing on the line 108 */ 109 --ps.ind_level; 110 /* 111 * it is a group as part of a while, for, etc. 112 */ 113 if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) 114 --ps.ind_level; 115 /* 116 * for a switch, brace should be two levels out from the code 117 */ 118 } 119 } 120 121 ps.p_stack[++ps.tos] = lbrace; 122 ps.il[ps.tos] = ps.ind_level; 123 ps.p_stack[++ps.tos] = stmt; 124 /* allow null stmt between braces */ 125 ps.il[ps.tos] = ps.i_l_follow; 126 break; 127 128 case whilestmt: /* scanned while (...) */ 129 if (ps.p_stack[ps.tos] == dohead) { 130 /* it is matched with do stmt */ 131 ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; 132 ps.p_stack[++ps.tos] = whilestmt; 133 ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 134 } 135 else { /* it is a while loop */ 136 ps.p_stack[++ps.tos] = whilestmt; 137 ps.il[ps.tos] = ps.i_l_follow; 138 ++ps.i_l_follow; 139 ps.search_brace = btype_2; 140 } 141 142 break; 143 144 case elselit: /* scanned an else */ 145 146 if (ps.p_stack[ps.tos] != ifhead) 147 diag(1, "Unmatched 'else'"); 148 else { 149 ps.ind_level = ps.il[ps.tos]; /* indentation for else should 150 * be same as for if */ 151 ps.i_l_follow = ps.ind_level + 1; /* everything following should 152 * be in 1 level */ 153 ps.p_stack[ps.tos] = elsehead; 154 /* remember if with else */ 155 ps.search_brace = btype_2 | ps.else_if; 156 } 157 break; 158 159 case rbrace: /* scanned a } */ 160 /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ 161 if (ps.p_stack[ps.tos - 1] == lbrace) { 162 ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; 163 ps.p_stack[ps.tos] = stmt; 164 } 165 else 166 diag(1, "Stmt nesting error."); 167 break; 168 169 case swstmt: /* had switch (...) */ 170 ps.p_stack[++ps.tos] = swstmt; 171 ps.cstk[ps.tos] = case_ind; 172 /* save current case indent level */ 173 ps.il[ps.tos] = ps.i_l_follow; 174 case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one 175 * level down from 176 * switch */ 177 ps.i_l_follow += ps.case_indent + 1; /* statements should be two 178 * levels in */ 179 ps.search_brace = btype_2; 180 break; 181 182 case semicolon: /* this indicates a simple stmt */ 183 break_comma = false; /* turn off flag to break after commas in a 184 * declaration */ 185 ps.p_stack[++ps.tos] = stmt; 186 ps.il[ps.tos] = ps.ind_level; 187 break; 188 189 default: /* this is an error */ 190 diag(1, "Unknown code to parser"); 191 return; 192 193 194 } /* end of switch */ 195 196 reduce(); /* see if any reduction can be done */ 197 198 #ifdef debug 199 for (i = 1; i <= ps.tos; ++i) 200 printf("(%d %d)", ps.p_stack[i], ps.il[i]); 201 printf("\n"); 202 #endif 203 204 return; 205 } 206 207 /* 208 * NAME: reduce 209 * 210 * FUNCTION: Implements the reduce part of the parsing algorithm 211 * 212 * ALGORITHM: The following reductions are done. Reductions are repeated 213 * until no more are possible. 214 * 215 * Old TOS New TOS 216 * <stmt> <stmt> <stmtl> 217 * <stmtl> <stmt> <stmtl> 218 * do <stmt> "dostmt" 219 * if <stmt> "ifstmt" 220 * switch <stmt> <stmt> 221 * decl <stmt> <stmt> 222 * "ifelse" <stmt> <stmt> 223 * for <stmt> <stmt> 224 * while <stmt> <stmt> 225 * "dostmt" while <stmt> 226 * 227 * On each reduction, ps.i_l_follow (the indentation for the following line) 228 * is set to the indentation level associated with the old TOS. 229 * 230 * PARAMETERS: None 231 * 232 * RETURNS: Nothing 233 * 234 * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = 235 * 236 * CALLS: None 237 * 238 * CALLED BY: parse 239 * 240 * HISTORY: initial coding November 1976 D A Willcox of CAC 241 * 242 */ 243 /*----------------------------------------------*\ 244 | REDUCTION PHASE | 245 \*----------------------------------------------*/ 246 reduce() 247 { 248 249 register int i; 250 251 for (;;) { /* keep looping until there is nothing left to 252 * reduce */ 253 254 switch (ps.p_stack[ps.tos]) { 255 256 case stmt: 257 switch (ps.p_stack[ps.tos - 1]) { 258 259 case stmt: 260 case stmtl: 261 /* stmtl stmt or stmt stmt */ 262 ps.p_stack[--ps.tos] = stmtl; 263 break; 264 265 case dolit: /* <do> <stmt> */ 266 ps.p_stack[--ps.tos] = dohead; 267 ps.i_l_follow = ps.il[ps.tos]; 268 break; 269 270 case ifstmt: 271 /* <if> <stmt> */ 272 ps.p_stack[--ps.tos] = ifhead; 273 for (i = ps.tos - 1; 274 ( 275 ps.p_stack[i] != stmt 276 && 277 ps.p_stack[i] != stmtl 278 && 279 ps.p_stack[i] != lbrace 280 ); 281 --i); 282 ps.i_l_follow = ps.il[i]; 283 /* 284 * for the time being, we will assume that there is no else on 285 * this if, and set the indentation level accordingly. If an 286 * else is scanned, it will be fixed up later 287 */ 288 break; 289 290 case swstmt: 291 /* <switch> <stmt> */ 292 case_ind = ps.cstk[ps.tos - 1]; 293 294 case decl: /* finish of a declaration */ 295 case elsehead: 296 /* <<if> <stmt> else> <stmt> */ 297 case forstmt: 298 /* <for> <stmt> */ 299 case whilestmt: 300 /* <while> <stmt> */ 301 ps.p_stack[--ps.tos] = stmt; 302 ps.i_l_follow = ps.il[ps.tos]; 303 break; 304 305 default: /* <anything else> <stmt> */ 306 return; 307 308 } /* end of section for <stmt> on top of stack */ 309 break; 310 311 case whilestmt: /* while (...) on top */ 312 if (ps.p_stack[ps.tos - 1] == dohead) { 313 /* it is termination of a do while */ 314 ps.p_stack[--ps.tos] = stmt; 315 break; 316 } 317 else 318 return; 319 320 default: /* anything else on top */ 321 return; 322 323 } 324 } 325 } 326