~snowball-yiddish-dev/snowball-yiddish/trunk

« back to all changes in this revision

Viewing changes to website/p/generator.c

  • Committer: martinporter
  • Date: 2001-10-19 11:36:36 UTC
  • Revision ID: svn-v4:633ccae0-01f4-0310-8c99-d3591da6f01f:trunk:60
initialĀ upload

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include <stdio.h> /* for fprintf etc */
 
3
#include "header.h"
 
4
 
 
5
/* recursive use: */
 
6
 
 
7
static void generate(struct generator * g, struct node * p);
 
8
 
 
9
enum special_labels {
 
10
 
 
11
    x_return = -1
 
12
 
 
13
};
 
14
 
 
15
static int new_label(struct generator * g)
 
16
{   return g->next_label++;
 
17
}
 
18
 
 
19
static void wch(struct generator * g, int ch)  { fprintf(g->output, "%c", ch); } /* character */
 
20
static void wnl(struct generator * g)           { fprintf(g->output, "\n"); } /* newline */
 
21
static void ws(struct generator * g, char * s) { fprintf(g->output, "%s", s); } /* string */
 
22
static void wi(struct generator * g, int i)    { fprintf(g->output, "%d", i); } /* integer */
 
23
static void wi3(struct generator * g, int i) { fprintf(g->output, "%3d", i); } /* integer (width 3) */
 
24
 
 
25
static void wvn(struct generator * g, struct name * p)  /* variable name */
 
26
{
 
27
    int ch = "SBIrxg"[p->type];
 
28
    switch (p->type)
 
29
    {   case t_string:
 
30
        case t_boolean:
 
31
        case t_integer:
 
32
            wch(g, ch); wch(g, '['); wi(g, p->count); wch(g, ']'); return;
 
33
        case t_external:
 
34
            ws(g, g->options->externals_prefix); break;
 
35
        default:
 
36
            wch(g, ch); wch(g, '_');
 
37
    }
 
38
    report_b(g->output, p->b);
 
39
}
 
40
 
 
41
static void wv(struct generator * g, struct name * p)  /* reference to variable */
 
42
{   if (p->type < t_routine) ws(g, "z->");
 
43
    wvn(g, p);
 
44
}
 
45
 
 
46
static void whexch(struct generator * g, int n)
 
47
{   wch(g, n < 10 ? n + '0' : n - 10 + 'A');
 
48
}
 
49
 
 
50
static void whex(struct generator * g, int ch)
 
51
{   ws(g, "\\x");
 
52
    whexch(g, ch >> 4);
 
53
    whexch(g, ch & 0XF);
 
54
    ws(g, "\" \"");
 
55
}
 
56
 
 
57
static void wlit(struct generator * g, byte * p)  /* write literal string */
 
58
{   ws(g, "\"");
 
59
    {   int i;
 
60
        for (i = 0; i < SIZE(p); i++)
 
61
        {   int ch = p[i];
 
62
            if (32 <= ch && ch <= 127) switch (ch)
 
63
            {   case '\"': case '\\': ws(g, "\\");
 
64
                default: wch(g, ch);
 
65
            }  else whex(g, ch);
 
66
        }
 
67
    }
 
68
    ws(g, "\"");
 
69
}
 
70
 
 
71
static void wm(struct generator * g)       /* margin */
 
72
{   int i;
 
73
    for (i = 0; i < g->margin; i++) ws(g, "    ");
 
74
}
 
75
 
 
76
static void wc(struct generator * g, struct node * p) /* comment */
 
77
{
 
78
    ws(g, " /* ");
 
79
    ws(g, (char *) name_of_token(p->type));
 
80
    unless (p->name == 0) { ws(g, " "); report_b(g->output, p->name->b); }
 
81
    ws(g, ", line "); wi(g, p->line_number); ws(g, " */");
 
82
    wnl(g);
 
83
}
 
84
 
 
85
static void wms(struct generator * g, char * s)
 
86
{   wm(g); ws(g, s);   } /* margin + string */
 
87
 
 
88
static void wbs(struct generator * g) /* block start */
 
89
{   wms(g, "{   ");
 
90
    g->margin++;
 
91
}
 
92
 
 
93
static void wbe(struct generator * g)    /* block end */
 
94
{   g->margin--;
 
95
    wms(g, "}"); wnl(g);
 
96
}
 
97
 
 
98
static void wk(struct generator * g, struct node * p)     /* keep c */
 
99
{   ws(g, p->mode == m_forward ? "int c = z->c;" :
 
100
                                 "int m = z->l - z->c;");
 
101
}
 
102
 
 
103
char * restore_string(struct generator * g, struct node * p)
 
104
{   return p->mode == m_forward ? "z->c = c;" :
 
105
                                  "z->c = z->l - m;";
 
106
}
 
107
 
 
108
static void wr(struct generator * g, struct node * p)     /* restore c */
 
109
{   ws(g, restore_string(g, p));
 
110
}
 
111
 
 
112
static void winc(struct generator * g, struct node * p)     /* increment c */
 
113
{   ws(g, p->mode == m_forward ? "z->c++;" :
 
114
                                 "z->c--;");
 
115
}
 
116
 
 
117
static void wsetl(struct generator * g, int n)
 
118
{   g->margin--;
 
119
    wms(g, "lab"); wi(g, n); ws(g, ":"); wnl(g);
 
120
    g->margin++;
 
121
}
 
122
 
 
123
static void wgotol(struct generator * g, int n)
 
124
{   wms(g, "goto lab"); wi(g, n); ws(g, ";"); wnl(g);
 
125
}
 
126
 
 
127
static void wf(struct generator * g)          /* fail */
 
128
{   if (g->failure_string != 0) { ws(g, "{ "); ws(g, g->failure_string); ws(g, " "); }
 
129
    switch (g->failure_label)
 
130
    {
 
131
        case x_return:
 
132
           ws(g, "return 0;"); break;
 
133
        default:
 
134
           ws(g, "goto lab"); wi(g, g->failure_label); ws(g, ";");
 
135
    }
 
136
    if (g->failure_string != 0) ws(g, " }");
 
137
}
 
138
 
 
139
static void wlim(struct generator * g, struct node * p)     /* if at limit fail */
 
140
{
 
141
    ws(g, p->mode == m_forward ? "if (z->c >= z->l) " :
 
142
                                 "if (z->c <= z->lb) ");
 
143
    wf(g);
 
144
}
 
145
 
 
146
static void wp(struct generator * g, char * s, struct node * p) /* formatted write */
 
147
{   int i = 0;
 
148
    int l = strlen(s);
 
149
    until (i >= l)
 
150
    {   int ch = s[i++];
 
151
        if (ch != '~') wch(g, ch); else
 
152
        switch(s[i++])
 
153
        {   default:  wch(g, s[i - 1]); continue;
 
154
            case 'C': wc(g, p); continue;
 
155
            case 'k': wk(g, p); continue;
 
156
            case 'K': /* keep for c_test */
 
157
                ws(g, p->mode == m_forward ? "int c_test = z->c;" :
 
158
                                             "int m_test = z->l - z->c;");
 
159
                continue;
 
160
            case 'r': wr(g, p); continue;
 
161
            case 'R': /* restore for c_test */
 
162
                ws(g, p->mode == m_forward ? "z->c = c_test;" :
 
163
                                             "z->c = z->l - m_test;");
 
164
                continue;
 
165
            case 'i': winc(g, p); continue;
 
166
            case 'l': wlim(g, p); continue;
 
167
            case 'f': wf(g); continue;
 
168
            case 'M': wm(g); continue;
 
169
            case 'N': wnl(g); continue;
 
170
            case '{': wbs(g); continue;
 
171
            case '}': wbe(g); continue;
 
172
            case 'S': ws(g, g->S[s[i++] - '0']); continue;
 
173
            case 'I': wi(g, g->I[s[i++] - '0']); continue;
 
174
            case 'J': wi3(g, g->I[s[i++] - '0']); continue;
 
175
            case 'V': wv(g, g->V[s[i++] - '0']); continue;
 
176
            case 'W': wvn(g, g->V[s[i++] - '0']); continue;
 
177
            case 'L': wlit(g, g->L[s[i++] - '0']); continue;
 
178
            case '+': g->margin++; continue;
 
179
            case '-': g->margin--; continue;
 
180
            case '$': /* insert_s, insert_v etc */
 
181
                wch(g, p->literalstring == 0 ? 'v' : 's');
 
182
                continue;
 
183
            case 'p': ws(g, g->options->externals_prefix); continue;
 
184
        }
 
185
    }
 
186
}
 
187
 
 
188
static void w(struct generator * g, char * s) { wp(g, s, 0); }
 
189
 
 
190
static void generate_AE(struct generator * g, struct node * p)
 
191
{   char * s;
 
192
    switch (p->type)
 
193
    {   case c_name:
 
194
            wv(g, p->name); break;
 
195
        case c_number:
 
196
            wi(g, p->number); break;
 
197
        case c_maxint:
 
198
            ws(g, "MAXINT"); break;
 
199
        case c_minint:
 
200
            ws(g, "MININT"); break;
 
201
        case c_neg:
 
202
            ws(g, "-"); generate_AE(g, p->left); break;
 
203
        case c_multiply:
 
204
            s = " * "; goto label0;
 
205
        case c_plus:
 
206
            s = " + "; goto label0;
 
207
        case c_minus:
 
208
            s = " - "; goto label0;
 
209
        case c_divide:
 
210
            s = " / ";
 
211
        label0:
 
212
            ws(g, "("); generate_AE(g, p->left);
 
213
            ws(g, s); generate_AE(g, p->right); ws(g, ")"); break;
 
214
        case c_sizeof:
 
215
            g->V[0] = p->name;
 
216
            w(g, "SIZE(~V0)"); break;
 
217
        case c_cursor:
 
218
            w(g, "z->c"); break;
 
219
        case c_limit:
 
220
            w(g, p->mode == m_forward ? "z->l" : "z->lb"); break;
 
221
        case c_size:
 
222
            w(g, "SIZE(z->p)"); break;
 
223
    }
 
224
}
 
225
 
 
226
/* K_needed() tests to see if we really need to keep c. Not true when the
 
227
   the command does not touch the cursor. This and repeat_score() could be
 
228
   elaborated almost indefinitely.
 
229
*/
 
230
 
 
231
static int K_needed(struct generator * g, struct node * p)
 
232
{   until (p == 0)
 
233
    {   switch (p->type)
 
234
        {   case c_dollar:
 
235
            case c_leftslice:
 
236
            case c_rightslice:
 
237
            case c_mathassign:
 
238
            case c_plusassign:
 
239
            case c_minusassign:
 
240
            case c_multiplyassign:
 
241
            case c_divideassign:
 
242
            case c_eq:
 
243
            case c_ne:
 
244
            case c_gr:
 
245
            case c_ge:
 
246
            case c_ls:
 
247
            case c_le:
 
248
            case c_sliceto:
 
249
            case c_true:
 
250
            case c_false:
 
251
            case c_debug:
 
252
                break;
 
253
 
 
254
            case c_call:
 
255
                if (K_needed(g, p->name->definition)) return true;
 
256
                break;
 
257
 
 
258
            case c_bra:
 
259
                if (K_needed(g, p->left)) return true;
 
260
                break;
 
261
 
 
262
            default: return true;
 
263
        }
 
264
        p = p->right;
 
265
    }
 
266
    return false;
 
267
}
 
268
 
 
269
static int repeat_score(struct generator * g, struct node * p)
 
270
{   int score = 0;
 
271
    until (p == 0)
 
272
    {
 
273
        switch (p->type)
 
274
        {   case c_dollar:
 
275
            case c_leftslice:
 
276
            case c_rightslice:
 
277
            case c_mathassign:
 
278
            case c_plusassign:
 
279
            case c_minusassign:
 
280
            case c_multiplyassign:
 
281
            case c_divideassign:
 
282
            case c_eq:
 
283
            case c_ne:
 
284
            case c_gr:
 
285
            case c_ge:
 
286
            case c_ls:
 
287
            case c_le:
 
288
            case c_sliceto:   /* case c_not: must not be included here! */
 
289
            case c_debug:
 
290
                break;
 
291
 
 
292
            case c_call:
 
293
                score += repeat_score(g, p->name->definition);
 
294
                break;
 
295
 
 
296
            case c_bra:
 
297
                score += repeat_score(g, p->left);
 
298
                break;
 
299
 
 
300
            case c_name:
 
301
            case c_literalstring:
 
302
            case c_next:
 
303
            case c_grouping:
 
304
            case c_non:
 
305
            case c_hop:
 
306
                score = score + 1; break;
 
307
 
 
308
            default: score = 2; break;
 
309
        }
 
310
        p = p->right;
 
311
    }
 
312
    return score;
 
313
}
 
314
 
 
315
/* tests if an expression requires cursor reinstatement in a repeat */
 
316
 
 
317
static int repeat_restore(struct generator * g, struct node * p)
 
318
{   return repeat_score(g, p) >= 2;
 
319
}
 
320
 
 
321
static void generate_bra(struct generator * g, struct node * p)
 
322
{   p = p->left;
 
323
    until (p == 0) { generate(g, p); p = p->right; }
 
324
}
 
325
 
 
326
static void generate_and(struct generator * g, struct node * p)
 
327
{   int keep_c = K_needed(g, p->left);
 
328
    if (keep_c) wp(g, "~{~k~C", p);
 
329
           else wp(g, "~M~C", p);
 
330
    p = p->left;
 
331
    until (p == 0)
 
332
    {   generate(g, p);
 
333
        if (keep_c && p->right != 0) wp(g, "~M~r~N", p);
 
334
        p = p->right;
 
335
    }
 
336
    if (keep_c) w(g, "~}");
 
337
}
 
338
 
 
339
static void generate_or(struct generator * g, struct node * p)
 
340
{   int keep_c = K_needed(g, p->left);
 
341
 
 
342
    int a0 = g->failure_label;
 
343
    char * a1 = g->failure_string;
 
344
 
 
345
    int out_lab = new_label(g);
 
346
 
 
347
    if (keep_c) wp(g, "~{~k~C", p);
 
348
           else wp(g, "~M~C", p);
 
349
    p = p->left;
 
350
    g->failure_string = 0;
 
351
    until (p == 0)
 
352
    {   if (p->right != 0)
 
353
        {
 
354
            g->failure_label = new_label(g);
 
355
            generate(g, p);
 
356
            wgotol(g, out_lab);
 
357
            wsetl(g, g->failure_label);
 
358
            if (keep_c) wp(g, "~M~r~N", p);
 
359
        } else
 
360
        {
 
361
            g->failure_label = a0;
 
362
            g->failure_string = a1;
 
363
 
 
364
            generate(g, p);
 
365
            if (keep_c) w(g, "~}");
 
366
            wsetl(g, out_lab);
 
367
        }
 
368
        p = p->right;
 
369
    }
 
370
}
 
371
 
 
372
/*-static void generate_backwards(struct generator * g, struct node * p)
 
373
-{   char * a1 = g->failure_string;
 
374
-
 
375
-    wp(g, "~{int m_backw = LOF(z->p, z->chead) - z->l;~C~N"
 
376
-             "~Mz->lb = z->c; z->c = z->l;~N", p);
 
377
-
 
378
-    g->failure_string = "z->l = LOF(z->p, z->chead) - m_backw;";
 
379
-    generate(g, p->left);
 
380
-
 
381
-    w(g,    "~Mz->c = z->lb; z->l = LOF(z->p, z->chead) - m_backw;~N"
 
382
-         "~}");
 
383
-
 
384
-    g->failure_string = a1;
 
385
-}
 
386
-*/
 
387
 
 
388
static void generate_backwards(struct generator * g, struct node * p)
 
389
{
 
390
    wp(g,"~Mz->lb = z->c; z->c = z->l;~C~N", p);
 
391
    generate(g, p->left);
 
392
    w(g, "~Mz->c = z->lb;");
 
393
}
 
394
 
 
395
 
 
396
static void generate_not(struct generator * g, struct node * p)
 
397
{   int keep_c = K_needed(g, p->left);
 
398
 
 
399
    int a0 = g->failure_label;
 
400
    char * a1 = g->failure_string;
 
401
 
 
402
    if (keep_c) wp(g, "~{~k~C", p);
 
403
           else wp(g, "~M~C", p);
 
404
 
 
405
    g->failure_label = new_label(g);
 
406
    g->failure_string = 0;
 
407
    generate(g, p->left);
 
408
 
 
409
    {   int l = g->failure_label;
 
410
 
 
411
        g->failure_label = a0;
 
412
        g->failure_string = a1;
 
413
 
 
414
        w(g, "~M~f~N");
 
415
        wsetl(g, l);
 
416
    }
 
417
    if (keep_c) wp(g, "~M~r~N"
 
418
                   "~}", p);
 
419
}
 
420
 
 
421
 
 
422
static void generate_try(struct generator * g, struct node * p)
 
423
{   int keep_c = K_needed(g, p->left);
 
424
 
 
425
    if (keep_c) wp(g, "~{~k~C", p);
 
426
           else wp(g, "~M~C", p);
 
427
 
 
428
    g->failure_label = new_label(g);
 
429
    g->failure_string = keep_c ? restore_string(g, p) : 0;
 
430
    generate(g, p->left);
 
431
 
 
432
    wsetl(g, g->failure_label);
 
433
 
 
434
    if (keep_c) w(g, "~}");
 
435
}
 
436
 
 
437
static void generate_set(struct generator * g, struct node * p)
 
438
{   g->V[0] = p->name; wp(g, "~M~V0 = 1;~C", p);
 
439
}
 
440
 
 
441
static void generate_unset(struct generator * g, struct node * p)
 
442
{   g->V[0] = p->name; wp(g, "~M~V0 = 0;~C", p);
 
443
}
 
444
 
 
445
static void generate_fail(struct generator * g, struct node * p)
 
446
{   generate(g, p->left);
 
447
    wp(g, "~M~f~C", p);
 
448
}
 
449
 
 
450
/* generate_test() also implements 'reverse' */
 
451
 
 
452
static void generate_test(struct generator * g, struct node * p)
 
453
{   int keep_c = K_needed(g, p->left);
 
454
    if (keep_c) wp(g, "~{~K~C", p);
 
455
           else wp(g, "~M~C", p);
 
456
 
 
457
    generate(g, p->left);
 
458
 
 
459
    if (keep_c) wp(g, "~M~R~N"
 
460
                   "~}", p);
 
461
}
 
462
 
 
463
static void generate_do(struct generator * g, struct node * p)
 
464
{   int keep_c = K_needed(g, p->left);
 
465
    if (keep_c) wp(g, "~{~k~C", p);
 
466
           else wp(g, "~M~C", p);
 
467
 
 
468
    g->failure_label = new_label(g);
 
469
    g->failure_string = 0;
 
470
    generate(g, p->left);
 
471
 
 
472
    wsetl(g, g->failure_label);
 
473
    if (keep_c) wp(g, "~M~r~N"
 
474
                   "~}", p);
 
475
}
 
476
 
 
477
static void generate_GO(struct generator * g, struct node * p, int style)
 
478
{   int keep_c = style == 1 || repeat_restore(g, p->left);
 
479
 
 
480
    int a0 = g->failure_label;
 
481
    char * a1 = g->failure_string;
 
482
 
 
483
    w(g, "~Mwhile(1) {"); wp(g, "~C~+", p);
 
484
 
 
485
    if (keep_c) wp(g, "~M~k~N", p);
 
486
 
 
487
    g->failure_label = new_label(g);
 
488
    generate(g, p->left);
 
489
 
 
490
    if (style == 1) wp(g, "~M~r~N", p);  /* include for goto; omit for gopast */
 
491
    w(g, "~Mbreak;~N");
 
492
    wsetl(g, g->failure_label);
 
493
    if (keep_c) wp(g, "~M~r~N", p);
 
494
 
 
495
    g->failure_label = a0;
 
496
    g->failure_string = a1;
 
497
 
 
498
    wp(g, "~M~l~N"
 
499
          "~M~i~N"
 
500
       "~}", p);
 
501
}
 
502
 
 
503
static void generate_loop(struct generator * g, struct node * p)
 
504
{   w(g, "~{int i; for (i = "); generate_AE(g, p->AE); wp(g, "; i > 0; i--)~C"
 
505
            "~{", p);
 
506
 
 
507
    generate(g, p->left);
 
508
 
 
509
    w(g,    "~}"
 
510
         "~}");
 
511
}
 
512
 
 
513
static void generate_repeat(struct generator * g, struct node * p, int atleast_case)
 
514
{   int keep_c = repeat_restore(g, p->left);
 
515
    wp(g, "~Mwhile(1) {~C~+", p);
 
516
 
 
517
    if (keep_c) wp(g, "~M~k~N", p);
 
518
 
 
519
    g->failure_label = new_label(g);
 
520
    g->failure_string = 0;
 
521
    generate(g, p->left);
 
522
 
 
523
    if (atleast_case) w(g, "~Mi--;~N");
 
524
 
 
525
    w(g, "~Mcontinue;~N");
 
526
    wsetl(g, g->failure_label);
 
527
 
 
528
    if (keep_c) wp(g, "~M~r~N", p);
 
529
 
 
530
    w(g, "~Mbreak;~N"
 
531
      "~}");
 
532
}
 
533
 
 
534
static void generate_atleast(struct generator * g, struct node * p)
 
535
{   w(g, "~{int i = "); generate_AE(g, p->AE); w(g, ";~N");
 
536
    {
 
537
        int a0 = g->failure_label;
 
538
        char * a1 = g->failure_string;
 
539
 
 
540
        generate_repeat(g, p, true);
 
541
 
 
542
        g->failure_label = a0;
 
543
        g->failure_string = a1;
 
544
    }
 
545
    w(g, "~Mif (i > 0) ~f~N"
 
546
      "~}");
 
547
}
 
548
 
 
549
static void generate_setmark(struct generator * g, struct node * p)
 
550
{   g->V[0] = p->name;
 
551
    wp(g, "~M~V0 = z->c;~C", p);
 
552
}
 
553
 
 
554
static void generate_tomark(struct generator * g, struct node * p)
 
555
{   g->S[0] = p->mode == m_forward ? ">" : "<";
 
556
 
 
557
    w(g, "~Mif (z->c ~S0 "); generate_AE(g, p->AE); w(g, ") ~f~N");
 
558
    w(g, "~Mz->c = "); generate_AE(g, p->AE); wp(g, ";~C", p);
 
559
}
 
560
 
 
561
static void generate_atmark(struct generator * g, struct node * p)
 
562
{
 
563
    w(g, "~Mif (z->c != "); generate_AE(g, p->AE); wp(g, ") ~f~C", p);
 
564
}
 
565
 
 
566
 
 
567
static void generate_hop(struct generator * g, struct node * p)
 
568
{   g->S[0] = p->mode == m_forward ? "+" : "-";
 
569
 
 
570
    w(g, "~{int c = z->c ~S0 "); generate_AE(g, p->AE); w(g, ";~N");
 
571
 
 
572
    g->S[0] = p->mode == m_forward ? "0" : "z->lb";
 
573
 
 
574
    wp(g, "~Mif (~S0 > c || c > z->l) ~f~N"
 
575
          "~Mz->c = c;~C"
 
576
          "~}", p);
 
577
}
 
578
 
 
579
static void generate_delete(struct generator * g, struct node * p)
 
580
{   wp(g, "~Mslice_del(z);~C", p);
 
581
}
 
582
 
 
583
 
 
584
static void generate_next(struct generator * g, struct node * p)
 
585
{   wp(g, "~M~l~N"
 
586
          "~M~i~C", p);
 
587
}
 
588
 
 
589
static void generate_tolimit(struct generator * g, struct node * p)
 
590
{   g->S[0] = p->mode == m_forward ? "" : "b";
 
591
    wp(g, "~Mz->c = z->l~S0;~C", p);
 
592
}
 
593
 
 
594
static void generate_atlimit(struct generator * g, struct node * p)
 
595
{   g->S[0] = p->mode == m_forward ? "" : "b";
 
596
    g->S[1] = p->mode == m_forward ? "<" : ">";
 
597
    wp(g, "~Mif (z->c ~S1 z->l~S0) ~f~C", p);
 
598
}
 
599
 
 
600
static void generate_leftslice(struct generator * g, struct node * p)
 
601
{   g->S[0] = p->mode == m_forward ? "bra" : "ket";
 
602
    wp(g, "~Mz->~S0 = z->c;~C", p);
 
603
}
 
604
 
 
605
static void generate_rightslice(struct generator * g, struct node * p)
 
606
{   g->S[0] = p->mode == m_forward ? "ket" : "bra";
 
607
    wp(g, "~Mz->~S0 = z->c;~C", p);
 
608
}
 
609
 
 
610
static void generate_assignto(struct generator * g, struct node * p)
 
611
{   g->V[0] = p->name;
 
612
    wp(g, "~M~V0 = assign_to(z, ~V0);~C", p);
 
613
}
 
614
 
 
615
static void generate_sliceto(struct generator * g, struct node * p)
 
616
{   g->V[0] = p->name;
 
617
    wp(g, "~M~V0 = slice_to(z, ~V0);~C", p);
 
618
}
 
619
 
 
620
static void generate_data_address(struct generator * g, struct node * p)
 
621
{
 
622
    byte * b = p->literalstring;
 
623
    if (b != 0)
 
624
    {   wi(g, SIZE(b)); w(g, ", ");
 
625
        wlit(g, b);
 
626
    } else
 
627
        wv(g, p->name);
 
628
}
 
629
 
 
630
static void generate_insert(struct generator * g, struct node * p, int style)
 
631
{
 
632
    int keep_c = style == c_attach;
 
633
    if (p->mode == m_backward) keep_c = !keep_c;
 
634
    if (keep_c) w(g, "~{int c = z->c;~N");
 
635
    wp(g, "~Minsert_~$(z, z->c, z->c, ", p);
 
636
    generate_data_address(g, p);
 
637
    wp(g, ");~C", p);
 
638
    if (keep_c) w(g, "~Mz->c = c;~N~}");
 
639
}
 
640
 
 
641
static void generate_assignfrom(struct generator * g, struct node * p)
 
642
{
 
643
    int keep_c = p->mode == m_forward; /* like 'attach' */
 
644
    if (keep_c) wp(g, "~{int c = z->c;~N"
 
645
                   "~Minsert_~$(z, z->c, z->l, ", p);
 
646
                else wp(g, "~Minsert_~$(z, z->lb, z->c, ", p);
 
647
    generate_data_address(g, p);
 
648
    wp(g, ");~C", p);
 
649
    if (keep_c) w(g, "~Mz->c = c;~N~}");
 
650
}
 
651
 
 
652
 
 
653
static void generate_slicefrom(struct generator * g, struct node * p)
 
654
{
 
655
    w(g, "~Mslice_from_s(z, ");
 
656
    generate_data_address(g, p);
 
657
    wp(g, ");~C", p);
 
658
}
 
659
 
 
660
static void generate_setlimit(struct generator * g, struct node * p)
 
661
{   wp(g, "~{~k~C"
 
662
              "~Mint m3;~N", p);
 
663
    generate(g, p->left);
 
664
    if (p->mode == m_forward) w(g, "~Mm3 = z->l - z->c; z->l = z->c;~N");
 
665
                         else w(g, "~Mm3 = z->lb; z->lb = z->c;~N");
 
666
    wp(g, "~M~r~N", p);
 
667
    {
 
668
        g->failure_string = p->mode == m_forward ? "z->l += m3;" :
 
669
                                                   "z->lb = m3;";
 
670
        generate(g, p->aux);
 
671
        wms(g, g->failure_string);
 
672
        w(g, "~N"
 
673
          "~}");
 
674
    }
 
675
}
 
676
 
 
677
static void generate_dollar(struct generator * g, struct node * p)
 
678
{
 
679
    g->V[0] = p->name;
 
680
    g->failure_string = "* z = env;";
 
681
    wp(g, "~{struct SN_env env = * z;~C"
 
682
             "~Mz->p = ~V0;~N"
 
683
             "~Mz->c = 0;~N"
 
684
             "~Mz->l = SIZE(z->p);~N", p);
 
685
    generate(g, p->left);
 
686
    wms(g, g->failure_string);
 
687
    w(g, "~N"
 
688
      "~}");
 
689
}
 
690
 
 
691
static void generate_integer_assign(struct generator * g, struct node * p, char * s)
 
692
{
 
693
    g->V[0] = p->name;
 
694
    g->S[0] = s;
 
695
    w(g, "~M~V0 ~S0 "); generate_AE(g, p->AE); w(g, ";~N");
 
696
}
 
697
 
 
698
static void generate_integer_test(struct generator * g, struct node * p, char * s)
 
699
{
 
700
    g->V[0] = p->name;
 
701
    g->S[0] = s;
 
702
    w(g, "~Mif (!(~V0 ~S0 "); generate_AE(g, p->AE); w(g, ")) ~f~N");
 
703
}
 
704
 
 
705
static void generate_call(struct generator * g, struct node * p)
 
706
{
 
707
    g->V[0] = p->name;
 
708
    wp(g, "~Mif (!~V0(z)) ~f~C", p);
 
709
}
 
710
 
 
711
static void generate_grouping(struct generator * g, struct node * p, int complement)
 
712
{
 
713
    struct grouping * q = p->name->grouping;
 
714
    g->S[0] = p->mode == m_forward ? "" : "_b";
 
715
    g->S[1] = complement ? "out" : "in";
 
716
    g->V[0] = p->name;
 
717
    g->I[0] = q->smallest_ch;
 
718
    g->I[1] = q->largest_ch;
 
719
    if (q->no_gaps)
 
720
        w(g, "~Mif (!(~S1_range~S0(z, ~I0, ~I1))) ~f~N");
 
721
    else
 
722
        w(g, "~Mif (!(~S1_grouping~S0(z, ~V0, ~I0, ~I1))) ~f~N");
 
723
}
 
724
 
 
725
static void generate_namedstring(struct generator * g, struct node * p)
 
726
{
 
727
    g->S[0] = p->mode == m_forward ? "" : "_b";
 
728
    g->V[0] = p->name;
 
729
    wp(g, "~Mif (!(eq_v~S0(z, ~V0))) ~f~C", p);
 
730
}
 
731
 
 
732
static void generate_literalstring(struct generator * g, struct node * p)
 
733
{   byte * b = p->literalstring;
 
734
    g->S[0] = p->mode == m_forward ? "" : "_b";
 
735
    g->I[0] = SIZE(b);
 
736
    g->L[0] = b;
 
737
 
 
738
    w(g, "~Mif (!(eq_s~S0(z, ~I0, ~L0))) ~f~N");
 
739
}
 
740
 
 
741
static void generate_define(struct generator * g, struct node * p)
 
742
{   struct name * q = p->name;
 
743
    g->next_label = 0;
 
744
 
 
745
    g->S[0] = q->type == t_routine ? "static" : "extern";
 
746
    g->V[0] = q;
 
747
 
 
748
    w(g, "~N~S0 int ~V0(struct SN_env * z) {~N~+");
 
749
    g->failure_string = 0;
 
750
    g->failure_label = x_return;
 
751
    generate(g, p->left);
 
752
    w(g, "~Mreturn 1;~N~}");
 
753
}
 
754
 
 
755
static void generate_substring(struct generator * g, struct node * p)
 
756
{
 
757
    struct among * x = p->among;
 
758
 
 
759
    g->S[0] = p->mode == m_forward ? "" : "_b";
 
760
    g->I[0] = x->number;
 
761
    g->I[1] = x->literalstring_count;
 
762
 
 
763
    if (x->command_count == 0 && x->starter == 0)
 
764
        wp(g, "~Mif (!(find_among~S0(z, a_~I0, ~I1))) ~f~C", p);
 
765
    else
 
766
        wp(g, "~Mz->a = find_among~S0(z, a_~I0, ~I1);~C", p);
 
767
}
 
768
 
 
769
static void generate_among(struct generator * g, struct node * p)
 
770
{
 
771
    struct among * x = p->among;
 
772
    int case_number = 1;
 
773
 
 
774
    if (x->substring == 0) generate_substring(g, p);
 
775
    if (x->command_count == 0 && x->starter == 0) return;
 
776
 
 
777
    unless (x->starter == 0) generate(g, x->starter);
 
778
 
 
779
    p = p->left;
 
780
    if (p != 0 && p->type != c_literalstring) p = p->right;
 
781
    w(g, "~Mswitch(z->a) {~N~+"
 
782
             "~Mcase 0: ~f~N");
 
783
 
 
784
    until (p == 0)
 
785
    {    if (p->type == c_bra && p->left != 0)
 
786
         {   g->I[0] = case_number++;
 
787
             w(g, "~Mcase ~I0:~N~+"); generate(g, p); w(g, "~Mbreak;~N~-");
 
788
         }
 
789
         p = p->right;
 
790
    }
 
791
    w(g, "~}");
 
792
}
 
793
 
 
794
static void generate_booltest(struct generator * g, struct node * p)
 
795
{
 
796
    g->V[0] = p->name;
 
797
    wp(g, "~Mif (!(~V0)) ~f~C", p);
 
798
}
 
799
 
 
800
static void generate_false(struct generator * g, struct node * p)
 
801
{
 
802
    wp(g, "~M~f~C", p);
 
803
}
 
804
 
 
805
static void generate_debug(struct generator * g, struct node * p)
 
806
{
 
807
    g->I[0] = g->debug_count++;
 
808
    g->I[1] = p->line_number;
 
809
    wp(g, "~Mdebug(z, ~I0, ~I1);~C", p);
 
810
 
 
811
}
 
812
 
 
813
static void generate(struct generator * g, struct node * p)
 
814
{
 
815
    int a0 = g->failure_label;
 
816
    char * a1 = g->failure_string;
 
817
 
 
818
    switch (p->type)
 
819
    {
 
820
        case c_define:        generate_define(g, p); break;
 
821
        case c_bra:           generate_bra(g, p); break;
 
822
        case c_and:           generate_and(g, p); break;
 
823
        case c_or:            generate_or(g, p); break;
 
824
        case c_backwards:     generate_backwards(g, p); break;
 
825
        case c_not:           generate_not(g, p); break;
 
826
        case c_set:           generate_set(g, p); break;
 
827
        case c_unset:         generate_unset(g, p); break;
 
828
        case c_try:           generate_try(g, p); break;
 
829
        case c_fail:          generate_fail(g, p); break;
 
830
        case c_reverse:
 
831
        case c_test:          generate_test(g, p); break;
 
832
        case c_do:            generate_do(g, p); break;
 
833
        case c_goto:          generate_GO(g, p, 1); break;
 
834
        case c_gopast:        generate_GO(g, p, 0); break;
 
835
        case c_repeat:        generate_repeat(g, p, false); break;
 
836
        case c_loop:          generate_loop(g, p); break;
 
837
        case c_atleast:       generate_atleast(g, p); break;
 
838
        case c_setmark:       generate_setmark(g, p); break;
 
839
        case c_tomark:        generate_tomark(g, p); break;
 
840
        case c_atmark:        generate_atmark(g, p); break;
 
841
        case c_hop:           generate_hop(g, p); break;
 
842
        case c_delete:        generate_delete(g, p); break;
 
843
        case c_next:          generate_next(g, p); break;
 
844
        case c_tolimit:       generate_tolimit(g, p); break;
 
845
        case c_atlimit:       generate_atlimit(g, p); break;
 
846
        case c_leftslice:     generate_leftslice(g, p); break;
 
847
        case c_rightslice:    generate_rightslice(g, p); break;
 
848
        case c_assignto:      generate_assignto(g, p); break;
 
849
        case c_sliceto:       generate_sliceto(g, p); break;
 
850
        case c_assign:        generate_assignfrom(g, p); break;
 
851
        case c_insert:
 
852
        case c_attach:        generate_insert(g, p, p->type); break;
 
853
        case c_slicefrom:     generate_slicefrom(g, p); break;
 
854
        case c_setlimit:      generate_setlimit(g, p); break;
 
855
        case c_dollar:        generate_dollar(g, p); break;
 
856
        case c_mathassign:    generate_integer_assign(g, p, "="); break;
 
857
        case c_plusassign:    generate_integer_assign(g, p, "+="); break;
 
858
        case c_minusassign:   generate_integer_assign(g, p, "-="); break;
 
859
        case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
 
860
        case c_divideassign:  generate_integer_assign(g, p, "/="); break;
 
861
        case c_eq:            generate_integer_test(g, p, "=="); break;
 
862
        case c_ne:            generate_integer_test(g, p, "!="); break;
 
863
        case c_gr:            generate_integer_test(g, p, ">"); break;
 
864
        case c_ge:            generate_integer_test(g, p, ">="); break;
 
865
        case c_ls:            generate_integer_test(g, p, "<"); break;
 
866
        case c_le:            generate_integer_test(g, p, "<="); break;
 
867
        case c_call:          generate_call(g, p); break;
 
868
        case c_grouping:      generate_grouping(g, p, false); break;
 
869
        case c_non:           generate_grouping(g, p, true); break;
 
870
        case c_name:          generate_namedstring(g, p); break;
 
871
        case c_literalstring: generate_literalstring(g, p); break;
 
872
        case c_among:         generate_among(g, p); break;
 
873
        case c_substring:     generate_substring(g, p); break;
 
874
        case c_booltest:      generate_booltest(g, p); break;
 
875
        case c_false:         generate_false(g, p); break;
 
876
        case c_true:          break;
 
877
        case c_debug:         generate_debug(g, p); break;
 
878
        default: fprintf(stderr, "%d encountered\n", p->type);
 
879
                 exit(1);
 
880
    }
 
881
 
 
882
    g->failure_label = a0;
 
883
    g->failure_string = a1;
 
884
 
 
885
}
 
886
 
 
887
static void generate_head(struct generator * g)
 
888
{
 
889
    w(g, "~N#include \"header.h\"~N~N");
 
890
}
 
891
 
 
892
static void generate_routine_headers(struct generator * g)
 
893
{   struct name * q = g->analyser->names;
 
894
    until (q == 0)
 
895
    {   g->V[0] = q;
 
896
        switch (q->type)
 
897
        {   case t_routine:  g->S[0] = "static"; goto label0;
 
898
            case t_external: g->S[0] = "extern";
 
899
            label0:
 
900
                w(g, "~S0 int ~W0(struct SN_env * z);~N");
 
901
        }
 
902
        q = q->next;
 
903
    }
 
904
    w(g, "~N");
 
905
}
 
906
 
 
907
static void generate_among_table(struct generator * g, struct among * x)
 
908
{
 
909
    struct amongvec * v = x->b;
 
910
 
 
911
    g->I[0] = x->number;
 
912
    g->I[1] = x->literalstring_count;
 
913
 
 
914
    w(g, "~Mstatic struct among a_~I0[~I1] =~N{~N");
 
915
 
 
916
    {   int i;
 
917
        for (i = 0; i < x->literalstring_count; i++)
 
918
 
 
919
        {   g->I[0] = i;
 
920
            g->I[1] = v->size;
 
921
            g->I[2] = v->i;
 
922
            g->I[3] = v->result;
 
923
            g->L[0] = v->b;
 
924
            g->S[0] = i < x->literalstring_count - 1 ? "," : "";
 
925
 
 
926
            w(g, "/*~J0 */ { ~I1, (byte *)~L0, ~I2, ~I3}~S0~N");
 
927
            v++;
 
928
        }
 
929
    }
 
930
    w(g, "};~N~N");
 
931
}
 
932
 
 
933
static void generate_amongs(struct generator * g)
 
934
{   struct among * x = g->analyser->amongs;
 
935
    until (x == 0)
 
936
    {   generate_among_table(g, x);
 
937
        x = x->next;
 
938
    }
 
939
}
 
940
 
 
941
static void set_bit(byte * b, int i) { b[i/8] |= 1 << i%8; }
 
942
 
 
943
static int bit_is_set(byte * b, int i) { return b[i/8] & 1 << i%8; }
 
944
 
 
945
static void generate_grouping_table(struct generator * g, struct grouping * q)
 
946
{
 
947
    int range = q->largest_ch - q->smallest_ch + 1;
 
948
    int size = (range + 7)/ 8;  /* assume 8 bits per byte */
 
949
    byte * b = q->b;
 
950
    byte * map = create_b(size);
 
951
    int i;
 
952
    for (i = 0; i < size; i++) map[i] = 0;
 
953
 
 
954
    /* Using unicode would require revision here */
 
955
 
 
956
    for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
 
957
 
 
958
    q->no_gaps = true;
 
959
    for (i = 0; i < range; i++) unless (bit_is_set(map, i)) q->no_gaps = false;
 
960
 
 
961
    unless (q->no_gaps)
 
962
    {   g->V[0] = q->name;
 
963
 
 
964
        w(g, "~N"
 
965
             "static byte ~V0[] = { ");
 
966
        for (i = 0; i < size; i++)
 
967
        {    wi(g, map[i]);
 
968
             if (i < size - 1) w(g, ", ");
 
969
        }
 
970
        w(g, " };~N");
 
971
    }
 
972
    lose_b(map);
 
973
}
 
974
 
 
975
static void generate_groupings(struct generator * g)
 
976
{   struct grouping * q = g->analyser->groupings;
 
977
    until (q == 0)
 
978
    {   generate_grouping_table(g, q);
 
979
        q = q->next;
 
980
    }
 
981
}
 
982
 
 
983
static void generate_create(struct generator * g)
 
984
{
 
985
    int * p = g->analyser->name_count;
 
986
    g->I[0] = p[t_string];
 
987
    g->I[1] = p[t_integer];
 
988
    g->I[2] = p[t_boolean];
 
989
    w(g, "~N"
 
990
         "extern struct SN_env * ~pcreate_env(void) { return SN_create_env(~I0, ~I1, ~I2); }"
 
991
         "~N");
 
992
}
 
993
 
 
994
static void generate_close(struct generator * g)
 
995
{
 
996
    w(g, "~Nextern void ~pclose_env(struct SN_env * z) { SN_close_env(z); }~N~N");
 
997
}
 
998
 
 
999
static void generate_header_file(struct generator * g)
 
1000
{
 
1001
    struct name * q = g->analyser->names;
 
1002
    byte * vp = g->options->variables_prefix;
 
1003
    g->S[0] = vp;
 
1004
 
 
1005
    w(g, "~N"
 
1006
         "extern struct SN_env * ~pcreate_env(void);~N"
 
1007
         "extern void close_env(struct SN_env * z);~N~N");
 
1008
 
 
1009
    until (q == 0)
 
1010
    {   g->V[0] = q;
 
1011
        switch (q->type)
 
1012
        {
 
1013
            case t_external:
 
1014
                w(g, "extern int ~W0(struct SN_env * z);~N");
 
1015
                break;
 
1016
            case t_string:  g->S[1] = "S"; goto label0;
 
1017
            case t_integer: g->S[1] = "I"; goto label0;
 
1018
            case t_boolean: g->S[1] = "B";
 
1019
            label0:
 
1020
                if (vp)
 
1021
                {   g->I[0] = q->count;
 
1022
                    w(g, "#define ~S0");
 
1023
                    report_b(g->output, q->b);
 
1024
                    w(g, " (~S1[~I0])~N");
 
1025
                }
 
1026
                break;
 
1027
        }
 
1028
        q = q->next;
 
1029
    }
 
1030
    w(g, "~N");
 
1031
}
 
1032
 
 
1033
extern void generate_program(struct generator * g)
 
1034
{
 
1035
    g->output = g->options->output_c;
 
1036
    generate_head(g);
 
1037
    generate_routine_headers(g);
 
1038
    generate_amongs(g);
 
1039
    generate_groupings(g);
 
1040
 
 
1041
    {   struct node * p = g->analyser->program;
 
1042
        until (p == 0) { generate(g, p); p = p->right; }
 
1043
    }
 
1044
    generate_create(g);
 
1045
    generate_close(g);
 
1046
 
 
1047
    g->output = g->options->output_h;
 
1048
    generate_header_file(g);
 
1049
}
 
1050
 
 
1051
extern struct generator * create_generator(struct analyser * a, struct options * o)
 
1052
{   NEW(generator, g);
 
1053
    g->analyser = a;
 
1054
    g->options = o;
 
1055
    g->margin = 0;
 
1056
    g->debug_count = 0;
 
1057
    return g;
 
1058
}
 
1059
 
 
1060
extern void close_generator(struct generator * g)
 
1061
{
 
1062
    FREE(g);
 
1063
}
 
1064