1 1.85 rillig /* $NetBSD: parse.c,v 1.85 2025/01/07 03:55:00 rillig Exp $ */ 2 1.3 tls 3 1.9 kamil /*- 4 1.9 kamil * SPDX-License-Identifier: BSD-4-Clause 5 1.9 kamil * 6 1.9 kamil * Copyright (c) 1985 Sun Microsystems, Inc. 7 1.4 mrg * Copyright (c) 1980, 1993 8 1.4 mrg * The Regents of the University of California. All rights reserved. 9 1.1 cgd * All rights reserved. 10 1.1 cgd * 11 1.1 cgd * Redistribution and use in source and binary forms, with or without 12 1.1 cgd * modification, are permitted provided that the following conditions 13 1.1 cgd * are met: 14 1.1 cgd * 1. Redistributions of source code must retain the above copyright 15 1.1 cgd * notice, this list of conditions and the following disclaimer. 16 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 cgd * notice, this list of conditions and the following disclaimer in the 18 1.1 cgd * documentation and/or other materials provided with the distribution. 19 1.1 cgd * 3. All advertising materials mentioning features or use of this software 20 1.1 cgd * must display the following acknowledgement: 21 1.1 cgd * This product includes software developed by the University of 22 1.1 cgd * California, Berkeley and its contributors. 23 1.1 cgd * 4. Neither the name of the University nor the names of its contributors 24 1.1 cgd * may be used to endorse or promote products derived from this software 25 1.1 cgd * without specific prior written permission. 26 1.1 cgd * 27 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 1.1 cgd * SUCH DAMAGE. 38 1.1 cgd */ 39 1.1 cgd 40 1.5 lukem #include <sys/cdefs.h> 41 1.85 rillig __RCSID("$NetBSD: parse.c,v 1.85 2025/01/07 03:55:00 rillig Exp $"); 42 1.1 cgd 43 1.76 rillig #include <stdlib.h> 44 1.12 rillig 45 1.9 kamil #include "indent.h" 46 1.9 kamil 47 1.82 rillig /* Replace the top 2 symbols with the given symbol. */ 48 1.82 rillig static void 49 1.85 rillig ps_psyms_replace2(parser_symbol psym) 50 1.82 rillig { 51 1.82 rillig ps.psyms.len--; 52 1.82 rillig ps.psyms.sym[ps.psyms.len - 1] = psym; 53 1.85 rillig ps.ind_level_follow = ps.psyms.ind_level[ps.psyms.len - 1]; 54 1.68 rillig } 55 1.1 cgd 56 1.45 rillig static int 57 1.79 rillig left_justify_decl_level(void) 58 1.45 rillig { 59 1.60 rillig int level = 0; 60 1.74 rillig for (size_t i = ps.psyms.len - 2; i > 0; i--) 61 1.69 rillig if (ps.psyms.sym[i] == psym_decl) 62 1.60 rillig level++; 63 1.60 rillig return level; 64 1.45 rillig } 65 1.45 rillig 66 1.76 rillig void 67 1.85 rillig ps_psyms_push(parser_symbol psym, int ind_level) 68 1.64 rillig { 69 1.76 rillig if (ps.psyms.len == ps.psyms.cap) { 70 1.76 rillig ps.psyms.cap += 16; 71 1.76 rillig ps.psyms.sym = nonnull(realloc(ps.psyms.sym, 72 1.77 rillig sizeof(ps.psyms.sym[0]) * ps.psyms.cap)); 73 1.76 rillig ps.psyms.ind_level = nonnull(realloc(ps.psyms.ind_level, 74 1.77 rillig sizeof(ps.psyms.ind_level[0]) * ps.psyms.cap)); 75 1.76 rillig } 76 1.76 rillig ps.psyms.len++; 77 1.76 rillig ps.psyms.sym[ps.psyms.len - 1] = psym; 78 1.85 rillig ps.psyms.ind_level[ps.psyms.len - 1] = ind_level; 79 1.64 rillig } 80 1.64 rillig 81 1.68 rillig /* 82 1.68 rillig * Repeatedly try to reduce the top two symbols on the parse stack to a single 83 1.68 rillig * symbol, until no more reductions are possible. 84 1.68 rillig */ 85 1.68 rillig static void 86 1.77 rillig psyms_reduce(void) 87 1.68 rillig { 88 1.68 rillig again: 89 1.85 rillig if (ps.psyms.len >= 2 && ps.psyms.sym[ps.psyms.len - 1] == psym_stmt) { 90 1.85 rillig switch (ps.psyms.sym[ps.psyms.len - 2]) { 91 1.85 rillig case psym_decl: 92 1.85 rillig case psym_stmt: 93 1.85 rillig case psym_for_exprs: 94 1.85 rillig case psym_if_expr_stmt_else: 95 1.85 rillig case psym_switch_expr: 96 1.85 rillig case psym_while_expr: 97 1.85 rillig ps_psyms_replace2(psym_stmt); 98 1.85 rillig goto again; 99 1.85 rillig case psym_if_expr: 100 1.85 rillig ps_psyms_replace2(psym_if_expr_stmt); 101 1.85 rillig goto again; 102 1.85 rillig case psym_do: 103 1.85 rillig ps_psyms_replace2(psym_do_stmt); 104 1.85 rillig goto again; 105 1.85 rillig default: 106 1.85 rillig return; 107 1.85 rillig } 108 1.85 rillig } 109 1.79 rillig if (ps.psyms.sym[ps.psyms.len - 1] == psym_while_expr && 110 1.79 rillig ps.psyms.sym[ps.psyms.len - 2] == psym_do_stmt) { 111 1.79 rillig ps.psyms.len -= 2; 112 1.68 rillig goto again; 113 1.68 rillig } 114 1.68 rillig } 115 1.68 rillig 116 1.65 rillig static bool 117 1.65 rillig is_lbrace(parser_symbol psym) 118 1.65 rillig { 119 1.65 rillig return psym == psym_lbrace_block 120 1.65 rillig || psym == psym_lbrace_struct 121 1.65 rillig || psym == psym_lbrace_union 122 1.65 rillig || psym == psym_lbrace_enum; 123 1.65 rillig } 124 1.65 rillig 125 1.31 rillig /* 126 1.71 rillig * Shift the token onto the parser stack, then try to reduce it by combining it with 127 1.31 rillig * previous tokens. 128 1.31 rillig */ 129 1.5 lukem void 130 1.39 rillig parse(parser_symbol psym) 131 1.1 cgd { 132 1.62 rillig debug_blank_line(); 133 1.81 rillig debug_println("parse: %s", psym_name[psym]); 134 1.1 cgd 135 1.60 rillig if (psym != psym_else) { 136 1.79 rillig while (ps.psyms.sym[ps.psyms.len - 1] == psym_if_expr_stmt) { 137 1.79 rillig ps.psyms.sym[ps.psyms.len - 1] = psym_stmt; 138 1.84 rillig psyms_reduce(); 139 1.83 rillig ps.ind_level = ps.ind_level_follow 140 1.84 rillig = ps.psyms.ind_level[ps.psyms.len - 1]; 141 1.60 rillig } 142 1.34 rillig } 143 1.1 cgd 144 1.60 rillig switch (psym) { 145 1.1 cgd 146 1.71 rillig case psym_lbrace_block: 147 1.71 rillig case psym_lbrace_struct: 148 1.71 rillig case psym_lbrace_union: 149 1.71 rillig case psym_lbrace_enum: 150 1.71 rillig ps.break_after_comma = false; 151 1.79 rillig if (ps.psyms.sym[ps.psyms.len - 1] == psym_decl 152 1.79 rillig || ps.psyms.sym[ps.psyms.len - 1] == psym_stmt) 153 1.78 rillig ps.ind_level_follow++; 154 1.71 rillig else if (code.len == 0) { 155 1.71 rillig /* It is part of a while, for, etc. */ 156 1.78 rillig ps.ind_level--; 157 1.71 rillig 158 1.71 rillig /* for a switch, brace should be two levels out from 159 1.71 rillig * the code */ 160 1.79 rillig if (ps.psyms.sym[ps.psyms.len - 1] == psym_switch_expr 161 1.71 rillig && opt.case_indent >= 1.0F) 162 1.78 rillig ps.ind_level--; 163 1.71 rillig } 164 1.71 rillig 165 1.85 rillig ps_psyms_push(psym, ps.ind_level); 166 1.85 rillig ps_psyms_push(psym_stmt, ps.ind_level_follow); 167 1.71 rillig break; 168 1.71 rillig 169 1.71 rillig case psym_rbrace: 170 1.77 rillig /* stack should have <lbrace> <stmt> or <lbrace> <decl> */ 171 1.79 rillig if (!(ps.psyms.len >= 2 172 1.79 rillig && is_lbrace(ps.psyms.sym[ps.psyms.len - 2]))) { 173 1.71 rillig diag(1, "Statement nesting error"); 174 1.71 rillig break; 175 1.71 rillig } 176 1.85 rillig ps_psyms_replace2(psym_stmt); 177 1.85 rillig ps.ind_level = ps.ind_level_follow; 178 1.71 rillig break; 179 1.71 rillig 180 1.60 rillig case psym_decl: 181 1.79 rillig if (ps.psyms.sym[ps.psyms.len - 1] == psym_decl) 182 1.60 rillig break; /* only put one declaration onto stack */ 183 1.60 rillig 184 1.63 rillig ps.break_after_comma = true; 185 1.85 rillig ps_psyms_push(psym_decl, ps.ind_level_follow); 186 1.60 rillig 187 1.79 rillig if (opt.left_justify_decl) { 188 1.79 rillig ps.ind_level = left_justify_decl_level(); 189 1.79 rillig ps.ind_level_follow = ps.ind_level; 190 1.79 rillig } 191 1.60 rillig break; 192 1.60 rillig 193 1.71 rillig case psym_stmt: 194 1.71 rillig ps.break_after_comma = false; 195 1.85 rillig ps_psyms_push(psym_stmt, ps.ind_level); 196 1.71 rillig break; 197 1.71 rillig 198 1.60 rillig case psym_if_expr: 199 1.79 rillig if (ps.psyms.sym[ps.psyms.len - 1] == psym_if_expr_stmt_else 200 1.79 rillig && opt.else_if_in_same_line) { 201 1.74 rillig ps.ind_level_follow = 202 1.79 rillig ps.psyms.ind_level[ps.psyms.len - 1]; 203 1.79 rillig ps.psyms.len--; 204 1.79 rillig } 205 1.60 rillig /* FALLTHROUGH */ 206 1.60 rillig case psym_do: 207 1.60 rillig case psym_for_exprs: 208 1.79 rillig ps.ind_level = ps.ind_level_follow; 209 1.79 rillig ps.ind_level_follow = ps.ind_level + 1; 210 1.85 rillig ps_psyms_push(psym, ps.ind_level); 211 1.60 rillig break; 212 1.60 rillig 213 1.60 rillig case psym_else: 214 1.79 rillig if (ps.psyms.sym[ps.psyms.len - 1] != psym_if_expr_stmt) { 215 1.60 rillig diag(1, "Unmatched 'else'"); 216 1.64 rillig break; 217 1.60 rillig } 218 1.79 rillig ps.ind_level = ps.psyms.ind_level[ps.psyms.len - 1]; 219 1.64 rillig ps.ind_level_follow = ps.ind_level + 1; 220 1.79 rillig ps.psyms.sym[ps.psyms.len - 1] = psym_if_expr_stmt_else; 221 1.60 rillig break; 222 1.60 rillig 223 1.60 rillig case psym_switch_expr: 224 1.85 rillig ps_psyms_push(psym_switch_expr, ps.ind_level_follow); 225 1.60 rillig ps.ind_level_follow += (int)opt.case_indent + 1; 226 1.60 rillig break; 227 1.60 rillig 228 1.71 rillig case psym_while_expr: 229 1.79 rillig if (ps.psyms.sym[ps.psyms.len - 1] == psym_do_stmt) { 230 1.79 rillig ps.ind_level = ps.psyms.ind_level[ps.psyms.len - 1]; 231 1.79 rillig ps.ind_level_follow = ps.ind_level; 232 1.85 rillig ps_psyms_push(psym_while_expr, ps.ind_level); 233 1.71 rillig } else { 234 1.85 rillig ps_psyms_push(psym_while_expr, ps.ind_level_follow); 235 1.78 rillig ps.ind_level_follow++; 236 1.71 rillig } 237 1.60 rillig break; 238 1.60 rillig 239 1.60 rillig default: 240 1.60 rillig diag(1, "Unknown code to parser"); 241 1.60 rillig return; 242 1.17 rillig } 243 1.5 lukem 244 1.80 rillig #if debug 245 1.80 rillig static struct buffer before, after; 246 1.81 rillig buf_clear(&before); 247 1.81 rillig ps_psyms_to_string(&before, &ps); 248 1.80 rillig #endif 249 1.77 rillig psyms_reduce(); 250 1.80 rillig #if debug 251 1.81 rillig buf_clear(&after); 252 1.81 rillig ps_psyms_to_string(&after, &ps); 253 1.81 rillig if (strcmp(before.s, after.s) != 0) { 254 1.81 rillig debug_println("psyms before: %s", before.s); 255 1.81 rillig debug_println("psyms after: %s", after.s); 256 1.81 rillig } else 257 1.81 rillig debug_println("psyms: %s", after.s); 258 1.80 rillig #endif 259 1.1 cgd } 260