Line data Source code
1 : /*- 2 : * Copyright (c) 1985 Sun Microsystems, Inc. 3 : * Copyright (c) 1980, 1993 4 : * The Regents of the University of California. All rights reserved. 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. 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 : #if 0 33 : #ifndef lint 34 : static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93"; 35 : #endif /* not lint */ 36 : #endif 37 : 38 : #include "c.h" 39 : 40 : #include <err.h> 41 : #include <stdio.h> 42 : #include "indent_globs.h" 43 : #include "indent_codes.h" 44 : #include "indent.h" 45 : 46 : static void reduce(void); 47 : 48 : void 49 606 : parse(int tk) /* tk: the code for the construct scanned */ 50 : { 51 : int i; 52 : 53 : #ifdef debug 54 : printf("%2d - %s\n", tk, token); 55 : #endif 56 : 57 616 : while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { 58 : /* true if we have an if without an else */ 59 10 : ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt 60 : * reduction */ 61 10 : reduce(); /* see if this allows any reduction */ 62 : } 63 : 64 : 65 606 : switch (tk) { /* go on and figure out what to do with the 66 : * input */ 67 : 68 174 : case decl: /* scanned a declaration word */ 69 174 : ps.search_brace = btype_2; 70 : /* indicate that following brace should be on same line */ 71 174 : if (ps.p_stack[ps.tos] != decl) { /* only put one declaration 72 : * onto stack */ 73 154 : break_comma = true; /* while in declaration, newline should be 74 : * forced after comma */ 75 154 : ps.p_stack[++ps.tos] = decl; 76 154 : ps.il[ps.tos] = ps.i_l_follow; 77 : 78 154 : if (ps.ljust_decl) {/* only do if we want left justified 79 : * declarations */ 80 0 : ps.ind_level = 0; 81 0 : for (i = ps.tos - 1; i > 0; --i) 82 0 : if (ps.p_stack[i] == decl) 83 0 : ++ps.ind_level; /* indentation is number of 84 : * declaration levels deep we are */ 85 0 : ps.i_l_follow = ps.ind_level; 86 : } 87 : } 88 174 : break; 89 : 90 20 : case ifstmt: /* scanned if (...) */ 91 20 : if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ 92 : /* 93 : * Note that the stack pointer here is decremented, effectively 94 : * reducing "else if" to "if". This saves a lot of stack space 95 : * in case of a long "if-else-if ... else-if" sequence. 96 : */ 97 2 : ps.i_l_follow = ps.il[ps.tos--]; 98 : /* the rest is the same as for dolit and forstmt */ 99 : /* FALLTHROUGH */ 100 : case dolit: /* 'do' */ 101 : case forstmt: /* for (...) */ 102 20 : ps.p_stack[++ps.tos] = tk; 103 20 : ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 104 20 : ++ps.i_l_follow; /* subsequent statements should be indented 1 */ 105 20 : ps.search_brace = btype_2; 106 20 : break; 107 : 108 82 : case lbrace: /* scanned { */ 109 82 : break_comma = false; /* don't break comma in an initial list */ 110 82 : if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl 111 62 : || ps.p_stack[ps.tos] == stmtl) 112 68 : ++ps.i_l_follow; /* it is a random, isolated stmt group or a 113 : * declaration */ 114 : else { 115 14 : if (s_code == e_code) { 116 : /* 117 : * only do this if there is nothing on the line 118 : */ 119 8 : --ps.ind_level; 120 : /* 121 : * it is a group as part of a while, for, etc. 122 : */ 123 8 : if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) 124 0 : --ps.ind_level; 125 : /* 126 : * for a switch, brace should be two levels out from the code 127 : */ 128 : } 129 : } 130 : 131 82 : ps.p_stack[++ps.tos] = lbrace; 132 82 : ps.il[ps.tos] = ps.ind_level; 133 82 : ps.p_stack[++ps.tos] = stmt; 134 : /* allow null stmt between braces */ 135 82 : ps.il[ps.tos] = ps.i_l_follow; 136 82 : break; 137 : 138 0 : case whilestmt: /* scanned while (...) */ 139 0 : if (ps.p_stack[ps.tos] == dohead) { 140 : /* it is matched with do stmt */ 141 0 : ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; 142 0 : ps.p_stack[++ps.tos] = whilestmt; 143 0 : ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; 144 : } 145 : else { /* it is a while loop */ 146 0 : ps.p_stack[++ps.tos] = whilestmt; 147 0 : ps.il[ps.tos] = ps.i_l_follow; 148 0 : ++ps.i_l_follow; 149 0 : ps.search_brace = btype_2; 150 : } 151 : 152 0 : break; 153 : 154 10 : case elselit: /* scanned an else */ 155 : 156 10 : if (ps.p_stack[ps.tos] != ifhead) 157 0 : diag2(1, "Unmatched 'else'"); 158 : else { 159 10 : ps.ind_level = ps.il[ps.tos]; /* indentation for else should 160 : * be same as for if */ 161 10 : ps.i_l_follow = ps.ind_level + 1; /* everything following should 162 : * be in 1 level */ 163 10 : ps.p_stack[ps.tos] = elsehead; 164 : /* remember if with else */ 165 10 : ps.search_brace = btype_2 | ps.else_if; 166 : } 167 10 : break; 168 : 169 82 : case rbrace: /* scanned a } */ 170 : /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ 171 82 : if (ps.tos > 0 && ps.p_stack[ps.tos - 1] == lbrace) { 172 82 : ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; 173 82 : ps.p_stack[ps.tos] = stmt; 174 : } 175 : else 176 0 : diag2(1, "Statement nesting error"); 177 82 : break; 178 : 179 2 : case swstmt: /* had switch (...) */ 180 2 : ps.p_stack[++ps.tos] = swstmt; 181 2 : ps.cstk[ps.tos] = case_ind; 182 : /* save current case indent level */ 183 2 : ps.il[ps.tos] = ps.i_l_follow; 184 2 : case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one 185 : * level down from 186 : * switch */ 187 2 : ps.i_l_follow += ps.case_indent + 1; /* statements should be two 188 : * levels in */ 189 2 : ps.search_brace = btype_2; 190 2 : break; 191 : 192 236 : case semicolon: /* this indicates a simple stmt */ 193 236 : break_comma = false; /* turn off flag to break after commas in a 194 : * declaration */ 195 236 : ps.p_stack[++ps.tos] = stmt; 196 236 : ps.il[ps.tos] = ps.ind_level; 197 236 : break; 198 : 199 0 : default: /* this is an error */ 200 0 : diag2(1, "Unknown code to parser"); 201 0 : return; 202 : 203 : 204 : } /* end of switch */ 205 : 206 606 : if (ps.tos >= nitems(ps.p_stack) - 1) 207 0 : errx(1, "Parser stack overflow"); 208 : 209 606 : reduce(); /* see if any reduction can be done */ 210 : 211 : #ifdef debug 212 : for (i = 1; i <= ps.tos; ++i) 213 : printf("(%d %d)", ps.p_stack[i], ps.il[i]); 214 : printf("\n"); 215 : #endif 216 : 217 606 : return; 218 : } 219 : 220 : /* 221 : * NAME: reduce 222 : * 223 : * FUNCTION: Implements the reduce part of the parsing algorithm 224 : * 225 : * ALGORITHM: The following reductions are done. Reductions are repeated 226 : * until no more are possible. 227 : * 228 : * Old TOS New TOS 229 : * <stmt> <stmt> <stmtl> 230 : * <stmtl> <stmt> <stmtl> 231 : * do <stmt> "dostmt" 232 : * if <stmt> "ifstmt" 233 : * switch <stmt> <stmt> 234 : * decl <stmt> <stmt> 235 : * "ifelse" <stmt> <stmt> 236 : * for <stmt> <stmt> 237 : * while <stmt> <stmt> 238 : * "dostmt" while <stmt> 239 : * 240 : * On each reduction, ps.i_l_follow (the indentation for the following line) 241 : * is set to the indentation level associated with the old TOS. 242 : * 243 : * PARAMETERS: None 244 : * 245 : * RETURNS: Nothing 246 : * 247 : * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = 248 : * 249 : * CALLS: None 250 : * 251 : * CALLED BY: parse 252 : * 253 : * HISTORY: initial coding November 1976 D A Willcox of CAC 254 : * 255 : */ 256 : /*----------------------------------------------*\ 257 : | REDUCTION PHASE | 258 : \*----------------------------------------------*/ 259 : static void 260 1108 : reduce(void) 261 : { 262 : int i; 263 : 264 : for (;;) { /* keep looping until there is nothing left to 265 : * reduce */ 266 : 267 1108 : switch (ps.p_stack[ps.tos]) { 268 : 269 574 : case stmt: 270 574 : switch (ps.p_stack[ps.tos - 1]) { 271 : 272 308 : case stmt: 273 : case stmtl: 274 : /* stmtl stmt or stmt stmt */ 275 308 : ps.p_stack[--ps.tos] = stmtl; 276 308 : break; 277 : 278 0 : case dolit: /* <do> <stmt> */ 279 0 : ps.p_stack[--ps.tos] = dohead; 280 0 : ps.i_l_follow = ps.il[ps.tos]; 281 0 : break; 282 : 283 20 : case ifstmt: 284 : /* <if> <stmt> */ 285 20 : ps.p_stack[--ps.tos] = ifhead; 286 20 : for (i = ps.tos - 1; 287 : ( 288 20 : ps.p_stack[i] != stmt 289 16 : && 290 16 : ps.p_stack[i] != stmtl 291 0 : && 292 0 : ps.p_stack[i] != lbrace 293 : ); 294 0 : --i); 295 20 : ps.i_l_follow = ps.il[i]; 296 : /* 297 : * for the time being, we will assume that there is no else on 298 : * this if, and set the indentation level accordingly. If an 299 : * else is scanned, it will be fixed up later 300 : */ 301 20 : break; 302 : 303 2 : case swstmt: 304 : /* <switch> <stmt> */ 305 2 : case_ind = ps.cstk[ps.tos - 1]; 306 : /* FALLTHROUGH */ 307 164 : case decl: /* finish of a declaration */ 308 : case elsehead: 309 : /* <<if> <stmt> else> <stmt> */ 310 : case forstmt: 311 : /* <for> <stmt> */ 312 : case whilestmt: 313 : /* <while> <stmt> */ 314 164 : ps.p_stack[--ps.tos] = stmt; 315 164 : ps.i_l_follow = ps.il[ps.tos]; 316 164 : break; 317 : 318 82 : default: /* <anything else> <stmt> */ 319 82 : return; 320 : 321 : } /* end of section for <stmt> on top of stack */ 322 492 : break; 323 : 324 0 : case whilestmt: /* while (...) on top */ 325 0 : if (ps.p_stack[ps.tos - 1] == dohead) { 326 : /* it is termination of a do while */ 327 0 : ps.tos -= 2; 328 0 : break; 329 : } 330 : else 331 0 : return; 332 : 333 534 : default: /* anything else on top */ 334 534 : return; 335 : 336 : } 337 : } 338 : }