parse.c revision 1.85 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