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