Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/bc/include/parse.h
39507 views
1
/*
2
* *****************************************************************************
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*
6
* Copyright (c) 2018-2025 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.
136
struct BcParse;
137
struct BcProgram;
138
139
/**
140
* A function pointer to call when more parsing is needed.
141
* @param p The parser.
142
*/
143
typedef 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
*/
151
typedef void (*BcParseExpr)(struct BcParse* p, uint8_t flags);
152
153
/// The parser struct.
154
typedef 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
*/
214
void
215
bc_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
*/
222
void
223
bc_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
*/
230
void
231
bc_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
*/
237
void
238
bc_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
*/
244
void
245
bc_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
*/
252
void
253
bc_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
*/
262
void
263
bc_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
*/
271
void
272
bc_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.
277
extern const char bc_parse_zero[2];
278
extern const char bc_parse_one[2];
279
280
#endif // BC_PARSE_H
281
282