comparison anagram/agcore/bpu.cpp @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:13d2b8934445
1 /*
2 * AnaGram, A System for Syntax Directed Programming
3 * Copyright 1993-1999 Parsifal Software. All Rights Reserved.
4 * See the file COPYING for license and usage terms.
5 *
6 * bpu.cpp - Utility routines for bpe3
7 */
8
9 #include <ctype.h>
10 #include <stdarg.h>
11 #include "port.h"
12
13 #include "arrays.h"
14 #include "bpe3.h"
15 #include "bpu.h"
16 #include "cd.h"
17 #include "data.h"
18 #include "dict.h"
19 #include "engdef.h"
20 #include "keyword.h"
21 #include "myalloc.h"
22 #include "q1glbl.h"
23 #include "rule.h"
24 #include "stacks.h"
25 #include "symbol.h"
26 #include "token.h"
27
28 //#define INCLUDE_LOGGING
29 #include "log.h"
30
31
32 void template_string(const char *name, const char *tp, const char tc) {
33 ics();
34 while (*tp) {
35 char c = *tp++;
36 if (c == tc) {
37 ass(name);
38 continue;
39 }
40 acs(c);
41 }
42 tss();
43 }
44
45 AgString subs_template(const char *name, const char *tp, const char tc) {
46 template_string(name, tp, tc);
47 return buildAgString();
48 }
49
50 unsigned find_token_number(const char *name) {
51 return Symbol(name)->token_number;
52 //return map_token_name[identify_string(name,tkn_dict)].token_number;
53 }
54
55 int find_completions(int s, const unsigned **q) {
56 state_number_map *sp = &map_state_number[s];
57 const unsigned *p = lstptr(*sp, chain_completions);
58 int n = sp->n_chain_completions;
59 if (n == 0 && sp->chain_gotos_index == 0) {
60 p = lstptr(*sp, completions);
61 n = sp->n_completions;
62 }
63 *q = p;
64 return n;
65 }
66
67 void select_actions(int k) {
68 int n = tis()/3;
69 int *lb;
70
71 list_space(n+1);
72 lb = list_base;
73 iws();
74 while (n--) {
75 aws(lb[k]);
76 k += 3;
77 }
78 }
79
80 void find_key_tokens(const int *pl, int n, int tw /*, int ct */) {
81 LOGSECTION("find_key_tokens");
82 LOGV(n);
83 for (; n--; pl += tw) {
84 //int tn = *pl;
85 Token token = *pl;
86 LOGV(token);
87 //if (map_token_number[tn].key == 0) continue;
88 //if (token->key == 0) continue;
89 if (token->key.isNull()) {
90 continue;
91 }
92 isws(token);
93 }
94 }
95
96
97 /*
98 * Note that the text of the defined format must not contain a newline.
99 * Failure to abide by this rule will cause the line count to be
100 * incorrect.
101 */
102
103 void define_macro(const char *n, const char *fmt, ...) {
104 va_list ap;
105 fprintf(pe_file, "#define %s ", n);
106 va_start(ap, fmt);
107 vfprintf(pe_file, fmt, ap);
108 va_end(ap);
109 fputc('\n', pe_file);
110 pe_line_count++;
111 }
112
113 void define_macro_default(const char *n, const char *fmt, ...) {
114 va_list ap;
115 char name_only[80];
116 char *ptr;
117
118 strcpy(name_only, n);
119 ptr = strchr(name_only, '(');
120
121 if (ptr != NULL) {
122 *ptr = 0;
123 }
124
125 fprintf(pe_file, "#ifndef %s\n#define %s ", name_only, n);
126 va_start(ap, fmt);
127 vfprintf(pe_file, fmt, ap);
128 va_end(ap);
129 fprintf(pe_file, "\n#endif\n");
130 pe_line_count += 3;
131 }
132
133 unsigned char *key_string(int tn) {
134 LOGSECTION("key_string");
135 Keyword key = map_token_number[tn].key;
136 LOGV(tn) LCV(key) LCV(Keyword::count());
137
138 if (key.isNull()) {
139 return NULL;
140 }
141 LOGV(key->string);
142 return (unsigned char *) key->string.pointer();
143 }
144
145 /*
146 * Function: reducing_token
147 * Arguments:
148 * token number, tn
149 * state number, sn
150 * Returns: 0 if tn is _not_ a reducing token in the given state
151 * Otherwise, returns the number of the rule it reduces.
152 */
153
154 #if 0 /* no longer used */
155 unsigned reducing_token(unsigned tn, unsigned sn) {
156 state_number_map *sp = &map_state_number[sn];
157 const unsigned *p;
158 unsigned n = sp->n_reductions; /* number of reductions in this state */
159
160 if (n) {
161 p = lstptr(*sp, reductions);
162 while (n--) {
163 if (*p++ == tn) {
164 return *p;
165 }
166 p++;
167 }
168 return 0;
169 }
170 if (sp->n_completed_forms != 1) {
171 return 0;
172 }
173 if (shift_token(tn, sn)) {
174 return 0;
175 }
176 return *(lstptr(*sp,completed_forms));
177 }
178 #endif /* 0 - no longer used */
179
180 Rule ruleReducedBy(Token token, unsigned sn) {
181 state_number_map *sp = &map_state_number[sn];
182 const unsigned *p;
183 unsigned n = sp->n_reductions; /* number of reductions in this state */
184
185 if (n) {
186 p = lstptr(*sp, reductions);
187 while (n--) {
188 if (*p++ == (unsigned) token) {
189 return *p;
190 }
191 p++;
192 }
193 return 0;
194 }
195 if (sp->n_completed_forms != 1) {
196 // Exit if more than one completed rule
197 return 0;
198 }
199 if (shift_token(token, sn)) {
200 // Exit if there's a shift
201 return 0;
202 }
203 // Default reduction, return rule #
204 return *(lstptr(*sp, completed_forms));
205 }
206
207 void select_write_fragment(const char *name, const char *modes,
208 const char *suffix) {
209 char fragment[80];
210
211 strcpy(fragment, name);
212 strcat(fragment, modes);
213 strcat(fragment, suffix);
214 write_code_segment(fragment);
215 }
216
217 int shift_token(unsigned tn, unsigned sn) {
218 const unsigned *p;
219 unsigned n;
220
221 n = find_gotos(sn, &p);
222 while (n--) {
223 if (*p == tn) {
224 return 1;
225 }
226 else {
227 p += 2;
228 }
229 }
230
231 n = find_completions(sn, &p);
232 while (n--) {
233 if (*p == tn) {
234 return 1;
235 }
236 else {
237 p += 2;
238 }
239 }
240
241 return 0;
242 }
243
244 void count_pe_line(const char *s, int k) {
245 LOGSECTION("count_pe_line");
246
247 while (k--) {
248 if (s[k] == '\n') {
249 pe_line_count++;
250 }
251 }
252 LOGV(pe_line_count);
253 }
254
255 int wps(const char *s) {
256 LOGSECTION("wps");
257 int k = strlen(s);
258
259 fputs(s, pe_file);
260 count_pe_line(s, k);
261 return k;
262 }
263
264 int wss(void) {
265 count_pe_line(string_base, tis());
266 fputs(string_base, pe_file);
267 return rcs();
268 }
269
270 int wpe(const char *fs, ...) {
271 LOGSECTION("wpe");
272 va_list ap;
273 char buf[2000];
274
275 va_start(ap, fs);
276 vsprintf(buf, fs, ap);
277 va_end(ap);
278 return wps(buf);
279 }
280
281 void write_code_segment(const char *name) {
282 LOGSECTION("write_code_segment");
283 LOGV(name);
284 if (name == NULL) {
285 return;
286 }
287 AgString text = code_segment(name);
288 if (!text.exists()) {
289 return;
290 }
291 char *buf = text.pointer();
292 wps(buf);
293 wps("\n\n");
294 }
295
296 static AgString expand_my_macros(const char *s) {
297 LOGSECTION("expand_my_macros");
298 char *p;
299 int col_no = 0, lb = 0, k;
300
301 LOGV(s);
302 if (my_macros == NULL) {
303 return AgString(s);
304 }
305 ics();
306 while (*s) {
307 char *word;
308 int index;
309
310 while (*s && !isalpha(*s) && *s != '_') {
311 if (*s == '\n') {
312 acs(*s++);
313 col_no = 0;
314 while (*s && *s == ' ') {
315 col_no++, s++;
316 }
317 lb = col_no;
318 continue;
319 }
320 if (lb == col_no) {
321 for (k = lb; k--; ) {
322 acs(' ');
323 }
324 }
325 col_no++;
326 acs(*s++);
327 }
328 if (*s == 0) {
329 break;
330 }
331 ics();
332 while (*s && (isalpha(*s) || *s == '_')) {
333 acs(*s++);
334 }
335 word = build_string();
336 index = identify_string(word, my_macros);
337 if (index == 0) {
338 if (lb == col_no) {
339 for (k = lb; k--; ) {
340 acs(' ');
341 }
342 }
343 col_no += strlen(word);
344 ass(word);
345 DEALLOCATE(word);
346 continue;
347 }
348 DEALLOCATE(word);
349 p = my_macros_subs[index];
350 if (*p == 0 && lb == col_no && (*s == '\n' || strncmp(s,"\\\n",2) == 0)) {
351 if (*s == '\\') {
352 s++;
353 }
354 s++;
355 col_no = 0;
356 while (*s && *s == ' ') {
357 col_no++;
358 s++;
359 }
360 lb = col_no;
361 continue;
362 }
363 if (lb == col_no) for (k = lb; k--;) acs(' ');
364 for (; *p; p++ ) {
365 acs(*p);
366 col_no++;
367 if (*p == '\n') {
368 for (k = lb; k--; ) {
369 acs(' ');
370 }
371 col_no = lb;
372 continue;
373 }
374 }
375 if (*s == '#') {
376 s++;
377 }
378 }
379 LOGV(string_base);
380 return buildAgString();
381 }
382
383
384 AgString code_segment(const char *name) {
385 LOGSECTION("code_segment");
386
387 const char *rawtext = engdef_get(name);
388 LOGV(rawtext);
389
390 AgString mx = expand_my_macros(rawtext);
391 LOGV(mx);
392
393 return mx;
394 }