1/*
2 * *****************************************************************************
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
6 * Copyright (c) 2018-2021 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 lexer.
33 *
34 */
35
36#ifndef BC_LEX_H
37#define BC_LEX_H
38
39#include <stdbool.h>
40#include <stddef.h>
41
42#include <status.h>
43#include <vector.h>
44#include <lang.h>
45
46#define bc_lex_err(l, e) (bc_vm_handleError((e), (l)->line))
47#define bc_lex_verr(l, e, ...) (bc_vm_handleError((e), (l)->line, __VA_ARGS__))
48
49#if BC_ENABLED
50
51#if DC_ENABLED
52#define BC_LEX_NEG_CHAR (BC_IS_BC ? '-' : '_')
53#define BC_LEX_LAST_NUM_CHAR (BC_IS_BC ? 'Z' : 'F')
54#else // DC_ENABLED
55#define BC_LEX_NEG_CHAR ('-')
56#define BC_LEX_LAST_NUM_CHAR ('Z')
57#endif // DC_ENABLED
58
59#else // BC_ENABLED
60
61#define BC_LEX_NEG_CHAR ('_')
62#define BC_LEX_LAST_NUM_CHAR ('F')
63
64#endif // BC_ENABLED
65
66#define BC_LEX_NUM_CHAR(c, pt, int_only)                          \
67	(isdigit(c) || ((c) >= 'A' && (c) <= BC_LEX_LAST_NUM_CHAR) || \
68	 ((c) == '.' && !(pt) && !(int_only)))
69
70// BC_LEX_NEG is not used in lexing; it is only for parsing.
71typedef enum BcLexType {
72
73	BC_LEX_EOF,
74	BC_LEX_INVALID,
75
76#if BC_ENABLED
77	BC_LEX_OP_INC,
78	BC_LEX_OP_DEC,
79#endif // BC_ENABLED
80
81	BC_LEX_NEG,
82	BC_LEX_OP_BOOL_NOT,
83#if BC_ENABLE_EXTRA_MATH
84	BC_LEX_OP_TRUNC,
85#endif // BC_ENABLE_EXTRA_MATH
86
87	BC_LEX_OP_POWER,
88	BC_LEX_OP_MULTIPLY,
89	BC_LEX_OP_DIVIDE,
90	BC_LEX_OP_MODULUS,
91	BC_LEX_OP_PLUS,
92	BC_LEX_OP_MINUS,
93
94#if BC_ENABLE_EXTRA_MATH
95	BC_LEX_OP_PLACES,
96
97	BC_LEX_OP_LSHIFT,
98	BC_LEX_OP_RSHIFT,
99#endif // BC_ENABLE_EXTRA_MATH
100
101	BC_LEX_OP_REL_EQ,
102	BC_LEX_OP_REL_LE,
103	BC_LEX_OP_REL_GE,
104	BC_LEX_OP_REL_NE,
105	BC_LEX_OP_REL_LT,
106	BC_LEX_OP_REL_GT,
107
108	BC_LEX_OP_BOOL_OR,
109	BC_LEX_OP_BOOL_AND,
110
111#if BC_ENABLED
112	BC_LEX_OP_ASSIGN_POWER,
113	BC_LEX_OP_ASSIGN_MULTIPLY,
114	BC_LEX_OP_ASSIGN_DIVIDE,
115	BC_LEX_OP_ASSIGN_MODULUS,
116	BC_LEX_OP_ASSIGN_PLUS,
117	BC_LEX_OP_ASSIGN_MINUS,
118#if BC_ENABLE_EXTRA_MATH
119	BC_LEX_OP_ASSIGN_PLACES,
120	BC_LEX_OP_ASSIGN_LSHIFT,
121	BC_LEX_OP_ASSIGN_RSHIFT,
122#endif // BC_ENABLE_EXTRA_MATH
123#endif // BC_ENABLED
124	BC_LEX_OP_ASSIGN,
125
126	BC_LEX_NLINE,
127	BC_LEX_WHITESPACE,
128
129	BC_LEX_LPAREN,
130	BC_LEX_RPAREN,
131
132	BC_LEX_LBRACKET,
133	BC_LEX_COMMA,
134	BC_LEX_RBRACKET,
135
136	BC_LEX_LBRACE,
137	BC_LEX_SCOLON,
138	BC_LEX_RBRACE,
139
140	BC_LEX_STR,
141	BC_LEX_NAME,
142	BC_LEX_NUMBER,
143
144#if BC_ENABLED
145	BC_LEX_KW_AUTO,
146	BC_LEX_KW_BREAK,
147	BC_LEX_KW_CONTINUE,
148	BC_LEX_KW_DEFINE,
149	BC_LEX_KW_FOR,
150	BC_LEX_KW_IF,
151	BC_LEX_KW_LIMITS,
152	BC_LEX_KW_RETURN,
153	BC_LEX_KW_WHILE,
154	BC_LEX_KW_HALT,
155	BC_LEX_KW_LAST,
156#endif // BC_ENABLED
157	BC_LEX_KW_IBASE,
158	BC_LEX_KW_OBASE,
159	BC_LEX_KW_SCALE,
160#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
161	BC_LEX_KW_SEED,
162#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
163	BC_LEX_KW_LENGTH,
164	BC_LEX_KW_PRINT,
165	BC_LEX_KW_SQRT,
166	BC_LEX_KW_ABS,
167#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
168	BC_LEX_KW_IRAND,
169#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
170	BC_LEX_KW_QUIT,
171	BC_LEX_KW_READ,
172#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
173	BC_LEX_KW_RAND,
174#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
175	BC_LEX_KW_MAXIBASE,
176	BC_LEX_KW_MAXOBASE,
177	BC_LEX_KW_MAXSCALE,
178#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
179	BC_LEX_KW_MAXRAND,
180#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
181	BC_LEX_KW_ELSE,
182
183#if DC_ENABLED
184	BC_LEX_EQ_NO_REG,
185	BC_LEX_OP_MODEXP,
186	BC_LEX_OP_DIVMOD,
187
188	BC_LEX_COLON,
189	BC_LEX_EXECUTE,
190	BC_LEX_PRINT_STACK,
191	BC_LEX_CLEAR_STACK,
192	BC_LEX_STACK_LEVEL,
193	BC_LEX_DUPLICATE,
194	BC_LEX_SWAP,
195	BC_LEX_POP,
196
197	BC_LEX_ASCIIFY,
198	BC_LEX_PRINT_STREAM,
199
200	BC_LEX_STORE_IBASE,
201	BC_LEX_STORE_OBASE,
202	BC_LEX_STORE_SCALE,
203#if BC_ENABLE_EXTRA_MATH
204	BC_LEX_STORE_SEED,
205#endif // BC_ENABLE_EXTRA_MATH
206	BC_LEX_LOAD,
207	BC_LEX_LOAD_POP,
208	BC_LEX_STORE_PUSH,
209	BC_LEX_PRINT_POP,
210	BC_LEX_NQUIT,
211	BC_LEX_SCALE_FACTOR,
212#endif // DC_ENABLED
213
214} BcLexType;
215
216struct BcLex;
217typedef void (*BcLexNext)(struct BcLex*);
218
219typedef struct BcLex {
220
221	const char *buf;
222	size_t i;
223	size_t line;
224	size_t len;
225
226	BcLexType t;
227	BcLexType last;
228	BcVec str;
229
230} BcLex;
231
232void bc_lex_init(BcLex *l);
233void bc_lex_free(BcLex *l);
234void bc_lex_file(BcLex *l, const char *file);
235void bc_lex_text(BcLex *l, const char *text);
236void bc_lex_next(BcLex *l);
237
238void bc_lex_lineComment(BcLex *l);
239void bc_lex_comment(BcLex *l);
240void bc_lex_whitespace(BcLex *l);
241void bc_lex_number(BcLex *l, char start);
242void bc_lex_name(BcLex *l);
243void bc_lex_commonTokens(BcLex *l, char c);
244
245void bc_lex_invalidChar(BcLex *l, char c);
246
247#endif // BC_LEX_H
248