1/*
2 * *****************************************************************************
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
6 * Copyright (c) 2018-2023 Gavin D. Howard and contributors.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright notice, this
12 *   list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright notice,
15 *   this list of conditions and the following disclaimer in the documentation
16 *   and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
30 * *****************************************************************************
31 *
32 * Definitions for bc's parser.
33 *
34 */
35
36#ifndef BC_PARSE_H
37#define BC_PARSE_H
38
39#include <limits.h>
40#include <stdbool.h>
41#include <stdint.h>
42
43#include <status.h>
44#include <vector.h>
45#include <lex.h>
46#include <lang.h>
47
48// The following are flags that can be passed to @a BcParseExpr functions. They
49// define the requirements that the parsed expression must meet to not have an
50// error thrown.
51
52/// A flag that requires that the expression is valid for conditionals in for
53/// loops, while loops, and if statements. This is because POSIX requires that
54/// certain operators are *only* used in those cases. It's whacked, but that's
55/// how it is.
56#define BC_PARSE_REL (UINTMAX_C(1) << 0)
57
58/// A flag that requires that the expression is valid for a print statement.
59#define BC_PARSE_PRINT (UINTMAX_C(1) << 1)
60
61/// A flag that requires that the expression does *not* have any function call.
62#define BC_PARSE_NOCALL (UINTMAX_C(1) << 2)
63
64/// A flag that requires that the expression does *not* have a read()
65/// expression.
66#define BC_PARSE_NOREAD (UINTMAX_C(1) << 3)
67
68/// A flag that *allows* (rather than requires) that an array appear in the
69/// expression. This is mostly used as parameters in bc.
70#define BC_PARSE_ARRAY (UINTMAX_C(1) << 4)
71
72/// A flag that requires that the expression is not empty and returns a value.
73#define BC_PARSE_NEEDVAL (UINTMAX_C(1) << 5)
74
75/**
76 * Returns true if the parser has been initialized.
77 * @param p    The parser.
78 * @param prg  The program.
79 * @return     True if @a p has been initialized, false otherwise.
80 */
81#define BC_PARSE_IS_INITED(p, prg) ((p)->prog == (prg))
82
83/**
84 * Returns true if the current parser state allows parsing, false otherwise.
85 * @param p  The parser.
86 * @return   True if parsing can proceed, false otherwise.
87 */
88#define BC_PARSE_CAN_PARSE(p) ((p).l.t != BC_LEX_EOF)
89
90/**
91 * Pushes the instruction @a i onto the bytecode vector for the current
92 * function.
93 * @param p  The parser.
94 * @param i  The instruction to push onto the bytecode vector.
95 */
96#define bc_parse_push(p, i) (bc_vec_pushByte(&(p)->func->code, (uchar) (i)))
97
98/**
99 * Pushes an index onto the bytecode vector. For more information, see
100 * @a bc_vec_pushIndex() in src/vector.c and @a bc_program_index() in
101 * src/program.c.
102 * @param p    The parser.
103 * @param idx  The index to push onto the bytecode vector.
104 */
105#define bc_parse_pushIndex(p, idx) (bc_vec_pushIndex(&(p)->func->code, (idx)))
106
107/**
108 * A convenience macro for throwing errors in parse code. This takes care of
109 * plumbing like passing in the current line the lexer is on.
110 * @param p  The parser.
111 * @param e  The error.
112 */
113#if BC_DEBUG
114#define bc_parse_err(p, e) \
115	(bc_vm_handleError((e), __FILE__, __LINE__, (p)->l.line))
116#else // BC_DEBUG
117#define bc_parse_err(p, e) (bc_vm_handleError((e), (p)->l.line))
118#endif // BC_DEBUG
119
120/**
121 * A convenience macro for throwing errors in parse code. This takes care of
122 * plumbing like passing in the current line the lexer is on.
123 * @param p    The parser.
124 * @param e    The error.
125 * @param ...  The varags that are needed.
126 */
127#if BC_DEBUG
128#define bc_parse_verr(p, e, ...) \
129	(bc_vm_handleError((e), __FILE__, __LINE__, (p)->l.line, __VA_ARGS__))
130#else // BC_DEBUG
131#define bc_parse_verr(p, e, ...) \
132	(bc_vm_handleError((e), (p)->l.line, __VA_ARGS__))
133#endif // BC_DEBUG
134
135// Forward declarations.
136struct BcParse;
137struct BcProgram;
138
139/**
140 * A function pointer to call when more parsing is needed.
141 * @param p  The parser.
142 */
143typedef void (*BcParseParse)(struct BcParse* p);
144
145/**
146 * A function pointer to call when an expression needs to be parsed. This can
147 * happen for read() expressions or dc strings.
148 * @param p      The parser.
149 * @param flags  The flags for what is allowed or required. (See flags above.)
150 */
151typedef void (*BcParseExpr)(struct BcParse* p, uint8_t flags);
152
153/// The parser struct.
154typedef struct BcParse
155{
156	/// The lexer.
157	BcLex l;
158
159#if BC_ENABLED
160	/// The stack of flags for bc. (See comments in include/bc.h.) This stack is
161	/// *required* to have one item at all times. Not maintaining that invariant
162	/// will cause problems.
163	BcVec flags;
164
165	/// The stack of exits. These are indices into the bytecode vector where
166	/// blocks for loops and if statements end. Basically, these are the places
167	/// to jump to when skipping code.
168	BcVec exits;
169
170	/// The stack of conditionals. Unlike exits, which are indices to jump
171	/// *forward* to, this is a vector of indices to jump *backward* to, usually
172	/// to the conditional of a loop, hence the name.
173	BcVec conds;
174
175	/// A stack of operators. When parsing expressions, the bc parser uses the
176	/// Shunting-Yard algorithm, which requires a stack of operators. This can
177	/// hold the stack for multiple expressions at once because the expressions
178	/// stack as well. For more information, see the Expression Parsing section
179	/// of the Development manual (manuals/development.md).
180	BcVec ops;
181
182	/// A buffer to temporarily store a string in. This is because the lexer
183	/// might generate a string as part of its work, and the parser needs that
184	/// string, but it also needs the lexer to continue lexing, which might
185	/// overwrite the string stored in the lexer. This buffer is for copying
186	/// that string from the lexer to keep it safe.
187	BcVec buf;
188#endif // BC_ENABLED
189
190	/// A reference to the program to grab the current function when necessary.
191	struct BcProgram* prog;
192
193	/// A reference to the current function. The function is what holds the
194	/// bytecode vector that the parser is filling.
195	BcFunc* func;
196
197	/// The index of the function.
198	size_t fidx;
199
200#if BC_ENABLED
201	/// True if the bc parser just entered a function and an auto statement
202	/// would be valid.
203	bool auto_part;
204#endif // BC_ENABLED
205
206} BcParse;
207
208/**
209 * Initializes a parser.
210 * @param p     The parser to initialize.
211 * @param prog  A referenc to the program.
212 * @param func  The index of the current function.
213 */
214void
215bc_parse_init(BcParse* p, struct BcProgram* prog, size_t func);
216
217/**
218 * Frees a parser. This is not guarded by #if BC_DEBUG because a separate
219 * parser is created at runtime to parse read() expressions and dc strings.
220 * @param p  The parser to free.
221 */
222void
223bc_parse_free(BcParse* p);
224
225/**
226 * Resets the parser. Resetting means erasing all state to the point that the
227 * parser would think it was just initialized.
228 * @param p  The parser to reset.
229 */
230void
231bc_parse_reset(BcParse* p);
232
233/**
234 * Adds a string. See @a BcProgram in include/program.h for more details.
235 * @param p  The parser that parsed the string.
236 */
237void
238bc_parse_addString(BcParse* p);
239
240/**
241 * Adds a number. See @a BcProgram in include/program.h for more details.
242 * @param p  The parser that parsed the number.
243 */
244void
245bc_parse_number(BcParse* p);
246
247/**
248 * Update the current function in the parser.
249 * @param p     The parser.
250 * @param fidx  The index of the new function.
251 */
252void
253bc_parse_updateFunc(BcParse* p, size_t fidx);
254
255/**
256 * Adds a new variable or array. See @a BcProgram in include/program.h for more
257 * details.
258 * @param p     The parser that parsed the variable or array name.
259 * @param name  The name of the variable or array to add.
260 * @param var   True if the name is for a variable, false if it's for an array.
261 */
262void
263bc_parse_pushName(const BcParse* p, char* name, bool var);
264
265/**
266 * Sets the text that the parser will parse.
267 * @param p     The parser.
268 * @param text  The text to lex.
269 * @param mode  The mode to parse in.
270 */
271void
272bc_parse_text(BcParse* p, const char* text, BcMode mode);
273
274// References to const 0 and 1 strings for special cases. bc and dc have
275// specific instructions for 0 and 1 because they pop up so often and (in the
276// case of 1), increment/decrement operators.
277extern const char bc_parse_zero[2];
278extern const char bc_parse_one[2];
279
280#endif // BC_PARSE_H
281