1 /*
2 * *****************************************************************************
3 *
4 * Copyright (c) 2018-2019 Gavin D. Howard and contributors.
5 *
6 * All rights reserved.
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 * Code common to the parsers.
33 *
34 */
35
36 #include <assert.h>
37 #include <stddef.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include <limits.h>
42
43 #include <status.h>
44 #include <vector.h>
45 #include <lex.h>
46 #include <parse.h>
47 #include <program.h>
48 #include <vm.h>
49
bc_parse_updateFunc(BcParse * p,size_t fidx)50 void bc_parse_updateFunc(BcParse *p, size_t fidx) {
51 p->fidx = fidx;
52 p->func = bc_vec_item(&p->prog->fns, fidx);
53 }
54
bc_parse_pushName(const BcParse * p,char * name,bool var)55 void bc_parse_pushName(const BcParse *p, char *name, bool var) {
56 size_t idx = bc_program_search(p->prog, name, var);
57 bc_parse_pushIndex(p, idx);
58 }
59
bc_parse_addId(BcParse * p,const char * string,uchar inst)60 void bc_parse_addId(BcParse *p, const char *string, uchar inst) {
61
62 BcFunc *f = BC_IS_BC ? p->func : bc_vec_item(&p->prog->fns, BC_PROG_MAIN);
63 BcVec *v = inst == BC_INST_NUM ? &f->consts : &f->strs;
64 size_t idx = v->len;
65
66 if (inst == BC_INST_NUM) {
67
68 if (bc_parse_one[0] == string[0] && bc_parse_one[1] == string[1]) {
69 bc_parse_push(p, BC_INST_ONE);
70 return;
71 }
72 else {
73
74 BcConst c;
75 char *str = bc_vm_strdup(string);
76
77 c.val = str;
78 c.base = BC_NUM_BIGDIG_MAX;
79
80 memset(&c.num, 0, sizeof(BcNum));
81 bc_vec_push(v, &c);
82 }
83 }
84 else {
85 char *str = bc_vm_strdup(string);
86 bc_vec_push(v, &str);
87 }
88
89 bc_parse_updateFunc(p, p->fidx);
90 bc_parse_push(p, inst);
91 bc_parse_pushIndex(p, idx);
92 }
93
bc_parse_number(BcParse * p)94 void bc_parse_number(BcParse *p) {
95
96 #if BC_ENABLE_EXTRA_MATH
97 char *exp = strchr(p->l.str.v, 'e');
98 size_t idx = SIZE_MAX;
99
100 if (exp != NULL) {
101 idx = ((size_t) (exp - p->l.str.v));
102 *exp = 0;
103 }
104 #endif // BC_ENABLE_EXTRA_MATH
105
106 bc_parse_addId(p, p->l.str.v, BC_INST_NUM);
107
108 #if BC_ENABLE_EXTRA_MATH
109 if (exp != NULL) {
110
111 bool neg;
112
113 neg = (*((char*) bc_vec_item(&p->l.str, idx + 1)) == BC_LEX_NEG_CHAR);
114
115 bc_parse_addId(p, bc_vec_item(&p->l.str, idx + 1 + neg), BC_INST_NUM);
116 bc_parse_push(p, BC_INST_LSHIFT + neg);
117 }
118 #endif // BC_ENABLE_EXTRA_MATH
119 }
120
bc_parse_text(BcParse * p,const char * text)121 BcStatus bc_parse_text(BcParse *p, const char *text) {
122 // Make sure the pointer isn't invalidated.
123 p->func = bc_vec_item(&p->prog->fns, p->fidx);
124 return bc_lex_text(&p->l, text);
125 }
126
bc_parse_reset(BcParse * p,BcStatus s)127 BcStatus bc_parse_reset(BcParse *p, BcStatus s) {
128
129 if (p->fidx != BC_PROG_MAIN) {
130 bc_func_reset(p->func);
131 bc_parse_updateFunc(p, BC_PROG_MAIN);
132 }
133
134 p->l.i = p->l.len;
135 p->l.t = BC_LEX_EOF;
136 p->auto_part = false;
137
138 #if BC_ENABLED
139 if (BC_IS_BC) {
140 bc_vec_npop(&p->flags, p->flags.len - 1);
141 bc_vec_npop(&p->exits, p->exits.len);
142 bc_vec_npop(&p->conds, p->conds.len);
143 bc_vec_npop(&p->ops, p->ops.len);
144 }
145 #endif // BC_ENABLED
146
147 return bc_program_reset(p->prog, s);
148 }
149
bc_parse_free(BcParse * p)150 void bc_parse_free(BcParse *p) {
151
152 assert(p != NULL);
153
154 #if BC_ENABLED
155 if (BC_IS_BC) {
156 bc_vec_free(&p->flags);
157 bc_vec_free(&p->exits);
158 bc_vec_free(&p->conds);
159 bc_vec_free(&p->ops);
160 bc_vec_free(&p->buf);
161 }
162 #endif // BC_ENABLED
163
164 bc_lex_free(&p->l);
165 }
166
bc_parse_init(BcParse * p,BcProgram * prog,size_t func)167 void bc_parse_init(BcParse *p, BcProgram *prog, size_t func) {
168
169 #if BC_ENABLED
170 uint16_t flag = 0;
171 #endif // BC_ENABLED
172
173 assert(p != NULL && prog != NULL);
174
175 #if BC_ENABLED
176 if (BC_IS_BC) {
177 bc_vec_init(&p->flags, sizeof(uint16_t), NULL);
178 bc_vec_push(&p->flags, &flag);
179 bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL);
180 bc_vec_init(&p->conds, sizeof(size_t), NULL);
181 bc_vec_init(&p->ops, sizeof(BcLexType), NULL);
182 bc_vec_init(&p->buf, sizeof(char), NULL);
183 }
184 #endif // BC_ENABLED
185
186 bc_lex_init(&p->l);
187
188 p->prog = prog;
189 p->auto_part = false;
190 bc_parse_updateFunc(p, func);
191 }
192