2
#include <stdlib.h> /* for exit */
3
#include <string.h> /* for strlen */
4
#include <stdio.h> /* for fprintf etc */
7
#define BASE_PACKAGE "net.sf.snowball"
8
#define BASE_CLASS "SnowballProgram"
12
static void generate(struct generator * g, struct node * p);
13
static void w(struct generator * g, char * s);
14
static void writef(struct generator * g, char * s, struct node * p);
21
static int new_label(struct generator * g)
23
return g->next_label++;
26
static struct str * vars_newname(struct generator * g)
31
str_append_string(output, "v_");
32
str_append_int(output, g->var_number);
37
static void output_str(FILE * outfile, struct str * str)
39
char * s = b_to_s(str_data(str));
40
fprintf(outfile, "%s", s);
44
/* Write routines for simple entities */
46
static void write_char(struct generator * g, int ch)
48
str_append_ch(g->outbuf, ch);
51
static void write_newline(struct generator * g)
53
str_append_string(g->outbuf, "\n");
56
static void write_string(struct generator * g, char * s)
58
str_append_string(g->outbuf, s);
61
static void write_b(struct generator * g, symbol * b)
63
str_append_b(g->outbuf, b);
66
static void write_str(struct generator * g, struct str * str)
68
str_append(g->outbuf, str);
71
static void write_int(struct generator * g, int i)
73
str_append_int(g->outbuf, i);
77
/* Write routines for items from the syntax tree */
79
static void write_varname(struct generator * g, struct name * p)
81
int ch = "SBIrxg"[p->type];
82
if (p->type != t_external)
87
str_append_b(g->outbuf, p->b);
90
static void write_varref(struct generator * g, struct name * p)
92
/* In java, references look just the same */
96
static void write_hexdigit(struct generator * g, int n)
98
write_char(g, n < 10 ? n + '0' : n - 10 + 'A');
101
static void write_hex(struct generator * g, int ch)
103
write_string(g, "\\u");
105
for (i = 12; i >= 0; i -= 4) write_hexdigit(g, ch >> i & 0xf);
109
static void write_literal_string(struct generator * g, symbol * p)
112
write_string(g, "\"");
113
for (i = 0; i < SIZE(p); i++) {
115
if (32 <= ch && ch <= 127) {
116
if (ch == '\"' || ch == '\\') write_string(g, "\\");
122
write_string(g, "\"");
125
static void write_margin(struct generator * g)
128
for (i = 0; i < g->margin; i++) write_string(g, " ");
131
/* Write a variable declaration. */
132
static void write_declare(struct generator * g,
136
struct str * temp = g->outbuf;
137
g->outbuf = g->declarations;
138
write_string(g, " ");
139
writef(g, declaration, p);
140
write_string(g, ";");
145
static void write_comment(struct generator * g, struct node * p)
148
write_string(g, "// ");
149
write_string(g, (char *) name_of_token(p->type));
151
write_string(g, " ");
152
str_append_b(g->outbuf, p->name->b);
154
write_string(g, ", line ");
155
write_int(g, p->line_number);
159
static void write_block_start(struct generator * g)
164
static void write_block_end(struct generator * g) /* block end */
169
static void write_savecursor(struct generator * g, struct node * p,
170
struct str * savevar)
172
g->B[0] = str_data(savevar);
174
if (p->mode != m_forward) g->S[1] = "limit - ";
175
write_declare(g, "int ~B0", p);
176
writef(g, "~M~B0 = ~S1cursor;~N" , p);
179
static void restore_string(struct node * p, struct str * out, struct str * savevar)
182
str_append_string(out, "cursor = ");
183
if (p->mode != m_forward) str_append_string(out, "limit - ");
184
str_append(out, savevar);
185
str_append_string(out, ";");
188
static void write_restorecursor(struct generator * g, struct node * p,
189
struct str * savevar)
191
struct str * temp = str_new();
193
restore_string(p, temp, savevar);
199
static void write_inc_cursor(struct generator * g, struct node * p)
202
write_string(g, p->mode == m_forward ? "cursor++;" : "cursor--;");
206
static void wsetlab_begin(struct generator * g, int n)
213
static void wsetlab_end(struct generator * g)
215
w(g, "~-~M} while (false);~N");
218
static void wgotol(struct generator * g, int n)
221
write_string(g, "break lab");
223
write_string(g, ";");
227
static void write_failure(struct generator * g)
229
if (str_len(g->failure_str) != 0) {
231
write_str(g, g->failure_str);
235
switch (g->failure_label)
238
write_string(g, "return false;");
241
write_string(g, "break lab");
242
write_int(g, g->failure_label);
243
write_string(g, ";");
246
g->unreachable = true;
249
static void write_failure_if(struct generator * g, char * s, struct node * p)
251
writef(g, "~Mif (", p);
254
write_block_start(g);
257
g->unreachable = false;
260
/* if at limit fail */
261
static void write_check_limit(struct generator * g, struct node * p)
263
if (p->mode == m_forward) {
264
write_failure_if(g, "cursor >= limit", p);
266
write_failure_if(g, "cursor <= limit_backward", p);
270
/* Formatted write. */
271
static void writef(struct generator * g, char * input, struct node * p)
274
int l = strlen(input);
280
default: write_char(g, input[i - 1]); continue;
281
case 'C': write_comment(g, p); continue;
282
case 'f': write_block_start(g);
284
g->unreachable = false;
287
case 'M': write_margin(g); continue;
288
case 'N': write_newline(g); continue;
289
case '{': write_block_start(g); continue;
290
case '}': write_block_end(g); continue;
291
case 'S': write_string(g, g->S[input[i++] - '0']); continue;
292
case 'B': write_b(g, g->B[input[i++] - '0']); continue;
293
case 'I': write_int(g, g->I[input[i++] - '0']); continue;
294
case 'V': write_varref(g, g->V[input[i++] - '0']); continue;
295
case 'W': write_varname(g, g->V[input[i++] - '0']); continue;
296
case 'L': write_literal_string(g, g->L[input[i++] - '0']); continue;
297
case '+': g->margin++; continue;
298
case '-': g->margin--; continue;
299
case 'n': write_string(g, g->options->name); continue;
307
static void w(struct generator * g, char * s) {
311
static void generate_AE(struct generator * g, struct node * p)
315
write_varref(g, p->name); break;
317
write_int(g, p->number); break;
319
write_string(g, "MAXINT"); break;
321
write_string(g, "MININT"); break;
323
write_string(g, "-"); generate_AE(g, p->right); break;
325
s = " * "; goto label0;
327
s = " + "; goto label0;
329
s = " - "; goto label0;
333
write_string(g, "("); generate_AE(g, p->left);
334
write_string(g, s); generate_AE(g, p->right); write_string(g, ")"); break;
337
w(g, "(~V0.length())"); break;
339
w(g, "cursor"); break;
341
w(g, p->mode == m_forward ? "limit" : "limit_backward"); break;
343
w(g, "(current.length())"); break;
347
/* K_needed() tests to see if we really need to keep c. Not true when the
348
the command does not touch the cursor. This and repeat_score() could be
349
elaborated almost indefinitely.
352
static int K_needed(struct generator * g, struct node * p)
362
case c_multiplyassign:
378
if (K_needed(g, p->name->definition)) return true;
382
if (K_needed(g, p->left)) return true;
385
default: return true;
392
static int repeat_score(struct generator * g, struct node * p)
403
case c_multiplyassign:
411
case c_sliceto: /* case c_not: must not be included here! */
416
score += repeat_score(g, p->name->definition);
420
score += repeat_score(g, p->left);
424
case c_literalstring:
441
/* tests if an expression requires cursor reinstatement in a repeat */
443
static int repeat_restore(struct generator * g, struct node * p)
445
return repeat_score(g, p) >= 2;
448
static void generate_bra(struct generator * g, struct node * p)
458
static void generate_and(struct generator * g, struct node * p)
460
struct str * savevar = vars_newname(g);
461
int keep_c = K_needed(g, p->left);
465
if (keep_c) write_savecursor(g, p, savevar);
470
if (g->unreachable) break;
471
if (keep_c && p->right != 0) write_restorecursor(g, p, savevar);
477
static void generate_or(struct generator * g, struct node * p)
479
struct str * savevar = vars_newname(g);
480
int keep_c = K_needed(g, p->left);
482
int a0 = g->failure_label;
483
struct str * a1 = str_copy(g->failure_str);
485
int out_lab = new_label(g);
487
wsetlab_begin(g, out_lab);
489
if (keep_c) write_savecursor(g, p, savevar);
492
str_clear(g->failure_str);
495
/* p should never be 0 after an or: there should be at least two
497
fprintf(stderr, "Error: \"or\" node without children nodes.");
500
while (p->right != 0) {
501
g->failure_label = new_label(g);
502
wsetlab_begin(g, g->failure_label);
504
if (!g->unreachable) wgotol(g, out_lab);
506
g->unreachable = false;
507
if (keep_c) write_restorecursor(g, p, savevar);
511
g->failure_label = a0;
512
str_delete(g->failure_str);
520
static void generate_backwards(struct generator * g, struct node * p)
523
writef(g,"~Mlimit_backward = cursor; cursor = limit;~N", p);
524
generate(g, p->left);
525
w(g, "~Mcursor = limit_backward;");
529
static void generate_not(struct generator * g, struct node * p)
531
struct str * savevar = vars_newname(g);
532
int keep_c = K_needed(g, p->left);
534
int a0 = g->failure_label;
535
struct str * a1 = str_copy(g->failure_str);
539
write_block_start(g);
540
write_savecursor(g, p, savevar);
543
g->failure_label = new_label(g);
544
str_clear(g->failure_str);
546
wsetlab_begin(g, g->failure_label);
548
generate(g, p->left);
550
g->failure_label = a0;
551
str_delete(g->failure_str);
554
if (!g->unreachable) write_failure(g);
557
g->unreachable = false;
559
if (keep_c) write_restorecursor(g, p, savevar);
560
if (keep_c) write_block_end(g);
565
static void generate_try(struct generator * g, struct node * p)
567
struct str * savevar = vars_newname(g);
568
int keep_c = K_needed(g, p->left);
571
if (keep_c) write_savecursor(g, p, savevar);
573
g->failure_label = new_label(g);
574
if (keep_c) restore_string(p, g->failure_str, savevar);
576
wsetlab_begin(g, g->failure_label);
577
generate(g, p->left);
579
g->unreachable = false;
584
static void generate_set(struct generator * g, struct node * p)
588
writef(g, "~M~V0 = true;~N", p);
591
static void generate_unset(struct generator * g, struct node * p)
595
writef(g, "~M~V0 = false;~N", p);
598
static void generate_fail(struct generator * g, struct node * p)
601
generate(g, p->left);
602
if (!g->unreachable) write_failure(g);
605
/* generate_test() also implements 'reverse' */
607
static void generate_test(struct generator * g, struct node * p)
609
struct str * savevar = vars_newname(g);
610
int keep_c = K_needed(g, p->left);
615
write_savecursor(g, p, savevar);
618
generate(g, p->left);
620
if (!g->unreachable) {
622
write_restorecursor(g, p, savevar);
628
static void generate_do(struct generator * g, struct node * p)
630
struct str * savevar = vars_newname(g);
631
int keep_c = K_needed(g, p->left);
633
if (keep_c) write_savecursor(g, p, savevar);
635
g->failure_label = new_label(g);
636
str_clear(g->failure_str);
638
wsetlab_begin(g, g->failure_label);
639
generate(g, p->left);
641
g->unreachable = false;
643
if (keep_c) write_restorecursor(g, p, savevar);
647
static void generate_GO(struct generator * g, struct node * p, int style)
649
int end_unreachable = false;
650
struct str * savevar = vars_newname(g);
651
int keep_c = style == 1 || repeat_restore(g, p->left);
653
int a0 = g->failure_label;
654
struct str * a1 = str_copy(g->failure_str);
656
int golab = new_label(g);
659
w(g, "~Mgolab~I0: while(true)~N");
662
if (keep_c) write_savecursor(g, p, savevar);
664
g->failure_label = new_label(g);
665
wsetlab_begin(g, g->failure_label);
666
generate(g, p->left);
668
if (g->unreachable) {
669
/* Cannot break out of this loop: therefore the code after the
670
* end of the loop is unreachable.*/
671
end_unreachable = true;
673
/* include for goto; omit for gopast */
674
if (style == 1) write_restorecursor(g, p, savevar);
676
w(g, "~Mbreak golab~I0;~N");
678
g->unreachable = false;
680
if (keep_c) write_restorecursor(g, p, savevar);
682
g->failure_label = a0;
683
str_delete(g->failure_str);
686
write_check_limit(g, p);
687
write_inc_cursor(g, p);
690
g->unreachable = end_unreachable;
693
static void generate_loop(struct generator * g, struct node * p)
695
struct str * loopvar = vars_newname(g);
697
g->B[0] = str_data(loopvar);
698
write_declare(g, "int ~B0", p);
699
w(g, "~Mfor (~B0 = ");
700
generate_AE(g, p->AE);
701
g->B[0] = str_data(loopvar);
702
writef(g, "; ~B0 > 0; ~B0--)~N", p);
705
generate(g, p->left);
709
g->unreachable = false;
712
static void generate_repeat(struct generator * g, struct node * p, struct str * loopvar)
714
struct str * savevar = vars_newname(g);
715
int keep_c = repeat_restore(g, p->left);
716
int replab = new_label(g);
719
writef(g, "~Mreplab~I0: while(true)~N~{", p);
721
if (keep_c) write_savecursor(g, p, savevar);
723
g->failure_label = new_label(g);
724
str_clear(g->failure_str);
725
wsetlab_begin(g, g->failure_label);
726
generate(g, p->left);
728
if (!g->unreachable) {
730
g->B[0] = str_data(loopvar);
735
w(g, "~Mcontinue replab~I0;~N");
739
g->unreachable = false;
741
if (keep_c) write_restorecursor(g, p, savevar);
744
w(g, "~Mbreak replab~I0;~N~}");
748
static void generate_atleast(struct generator * g, struct node * p)
750
struct str * loopvar = vars_newname(g);
753
g->B[0] = str_data(loopvar);
754
w(g, "~Mint ~B0 = ");
755
generate_AE(g, p->AE);
758
int a0 = g->failure_label;
759
struct str * a1 = str_copy(g->failure_str);
761
generate_repeat(g, p, loopvar);
763
g->failure_label = a0;
764
str_delete(g->failure_str);
767
g->B[0] = str_data(loopvar);
768
write_failure_if(g, "~B0 > 0", p);
773
static void generate_setmark(struct generator * g, struct node * p)
777
writef(g, "~M~V0 = cursor;~N", p);
780
static void generate_tomark(struct generator * g, struct node * p)
783
g->S[0] = p->mode == m_forward ? ">" : "<";
785
w(g, "~Mif (cursor ~S0 "); generate_AE(g, p->AE); w(g, ")~N");
786
write_block_start(g);
789
g->unreachable = false;
790
w(g, "~Mcursor = "); generate_AE(g, p->AE); writef(g, ";~N", p);
793
static void generate_atmark(struct generator * g, struct node * p)
796
w(g, "~Mif (cursor != "); generate_AE(g, p->AE); writef(g, ")~N", p);
797
write_block_start(g);
800
g->unreachable = false;
804
static void generate_hop(struct generator * g, struct node * p)
807
g->S[0] = p->mode == m_forward ? "+" : "-";
809
w(g, "~{~Mint c = cursor ~S0 ");
810
generate_AE(g, p->AE);
813
g->S[0] = p->mode == m_forward ? "0" : "limit_backward";
815
write_failure_if(g, "~S0 > c || c > limit", p);
816
writef(g, "~Mcursor = c;~N", p);
820
static void generate_delete(struct generator * g, struct node * p)
823
writef(g, "~Mslice_del();~N", p);
827
static void generate_next(struct generator * g, struct node * p)
830
write_check_limit(g, p);
831
write_inc_cursor(g, p);
834
static void generate_tolimit(struct generator * g, struct node * p)
837
g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
838
writef(g, "~Mcursor = ~S0;~N", p);
841
static void generate_atlimit(struct generator * g, struct node * p)
844
g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
845
g->S[1] = p->mode == m_forward ? "<" : ">";
846
write_failure_if(g, "cursor ~S1 ~S0", p);
849
static void generate_leftslice(struct generator * g, struct node * p)
852
g->S[0] = p->mode == m_forward ? "bra" : "ket";
853
writef(g, "~M~S0 = cursor;~N", p);
856
static void generate_rightslice(struct generator * g, struct node * p)
859
g->S[0] = p->mode == m_forward ? "ket" : "bra";
860
writef(g, "~M~S0 = cursor;~N", p);
863
static void generate_assignto(struct generator * g, struct node * p)
867
writef(g, "~M~V0 = assign_to(~V0);~N", p);
870
static void generate_sliceto(struct generator * g, struct node * p)
874
writef(g, "~M~V0 = slice_to(~V0);~N", p);
877
static void generate_address(struct generator * g, struct node * p)
879
symbol * b = p->literalstring;
881
write_literal_string(g, b);
883
write_varref(g, p->name);
887
static void generate_insert(struct generator * g, struct node * p, int style)
889
int keep_c = style == c_attach;
891
if (p->mode == m_backward) keep_c = !keep_c;
892
if (keep_c) w(g, "~{~Mint c = cursor;~N");
893
writef(g, "~Minsert(cursor, cursor, ", p);
894
generate_address(g, p);
895
writef(g, ");~N", p);
896
if (keep_c) w(g, "~Mcursor = c;~N~}");
899
static void generate_assignfrom(struct generator * g, struct node * p)
901
int keep_c = p->mode == m_forward; /* like 'attach' */
904
if (keep_c) writef(g, "~{~Mint c = cursor;~N", p);
905
if (p->mode == m_forward) {
906
writef(g, "~Minsert(cursor, limit, ", p);
908
writef(g, "~Minsert(limit_backward, cursor, ", p);
910
generate_address(g, p);
911
writef(g, ");~N", p);
912
if (keep_c) w(g, "~Mcursor = c;~N~}");
916
static void generate_slicefrom(struct generator * g, struct node * p)
919
w(g, "~Mslice_from(");
920
generate_address(g, p);
921
writef(g, ");~N", p);
924
static void generate_setlimit(struct generator * g, struct node * p)
926
struct str * savevar = vars_newname(g);
927
struct str * varname = vars_newname(g);
929
write_savecursor(g, p, savevar);
930
generate(g, p->left);
932
if (!g->unreachable) {
933
g->B[0] = str_data(varname);
934
write_declare(g, "int ~B0", p);
935
if (p->mode == m_forward) {
936
w(g, "~M~B0 = limit - cursor;~N");
937
w(g, "~Mlimit = cursor;~N");
939
w(g, "~M~B0 = limit_backward;~N");
940
w(g, "~Mlimit_backward = cursor;~N");
942
write_restorecursor(g, p, savevar);
944
if (p->mode == m_forward) {
945
str_assign(g->failure_str, "limit += ");
946
str_append(g->failure_str, varname);
947
str_append_ch(g->failure_str, ';');
949
str_assign(g->failure_str, "limit_backward = ");
950
str_append(g->failure_str, varname);
951
str_append_ch(g->failure_str, ';');
955
if (!g->unreachable) {
957
write_str(g, g->failure_str);
965
/* dollar sets snowball up to operate on a string variable as if it were the
967
static void generate_dollar(struct generator * g, struct node * p)
969
struct str * savevar = vars_newname(g);
973
str_assign(g->failure_str, "copy_from(");
974
str_append(g->failure_str, savevar);
975
str_append_string(g->failure_str, ");");
976
g->B[0] = str_data(savevar);
977
writef(g, "~{~M~n ~B0 = this;~N"
980
"~Mlimit = (current.length());~N", p);
981
generate(g, p->left);
982
if (!g->unreachable) {
984
write_str(g, g->failure_str);
991
static void generate_integer_assign(struct generator * g, struct node * p, char * s)
995
w(g, "~M~V0 ~S0 "); generate_AE(g, p->AE); w(g, ";~N");
998
static void generate_integer_test(struct generator * g, struct node * p, char * s)
1002
w(g, "~Mif (!(~V0 ~S0 "); generate_AE(g, p->AE); w(g, "))~N");
1003
write_block_start(g);
1006
g->unreachable = false;
1009
static void generate_call(struct generator * g, struct node * p)
1011
write_comment(g, p);
1013
write_failure_if(g, "!~V0()", p);
1016
static void generate_grouping(struct generator * g, struct node * p, int complement)
1018
struct grouping * q = p->name->grouping;
1019
g->S[0] = p->mode == m_forward ? "" : "_b";
1020
g->S[1] = complement ? "out" : "in";
1022
g->I[0] = q->smallest_ch;
1023
g->I[1] = q->largest_ch;
1025
write_failure_if(g, "!(~S1_range~S0(~I0, ~I1))", p);
1027
write_failure_if(g, "!(~S1_grouping~S0(~V0, ~I0, ~I1))", p);
1030
static void generate_namedstring(struct generator * g, struct node * p)
1032
write_comment(g, p);
1033
g->S[0] = p->mode == m_forward ? "" : "_b";
1035
write_failure_if(g, "!(eq_v~S0(~V0))", p);
1038
static void generate_literalstring(struct generator * g, struct node * p)
1040
symbol * b = p->literalstring;
1041
write_comment(g, p);
1042
g->S[0] = p->mode == m_forward ? "" : "_b";
1045
write_failure_if(g, "!(eq_s~S0(~I0, ~L0))", p);
1048
static void generate_define(struct generator * g, struct node * p)
1050
struct name * q = p->name;
1052
struct str * saved_output = g->outbuf;
1053
struct str * saved_declarations = g->declarations;
1055
g->S[0] = q->type == t_routine ? "private" : "public";
1057
w(g, "~+~+~N~M~S0 boolean ~V0() {~+~N");
1059
g->outbuf = str_new();
1060
g->declarations = str_new();
1065
if (p->amongvar_needed) write_declare(g, "int among_var", p);
1066
str_clear(g->failure_str);
1067
g->failure_label = x_return;
1068
g->unreachable = false;
1069
generate(g, p->left);
1070
if (!g->unreachable) w(g, "~Mreturn true;~N");
1073
str_append(saved_output, g->declarations);
1074
str_append(saved_output, g->outbuf);
1075
str_delete(g->declarations);
1076
str_delete(g->outbuf);
1077
g->declarations = saved_declarations;
1078
g->outbuf = saved_output;
1081
static void generate_substring(struct generator * g, struct node * p)
1083
struct among * x = p->among;
1085
write_comment(g, p);
1087
g->S[0] = p->mode == m_forward ? "" : "_b";
1088
g->I[0] = x->number;
1089
g->I[1] = x->literalstring_count;
1091
if (x->command_count == 0 && x->starter == 0) {
1092
write_failure_if(g, "find_among~S0(a_~I0, ~I1) == 0", p);
1094
writef(g, "~Mamong_var = find_among~S0(a_~I0, ~I1);~N", p);
1095
write_failure_if(g, "among_var == 0", p);
1099
static void generate_among(struct generator * g, struct node * p)
1101
struct among * x = p->among;
1102
int case_number = 1;
1104
if (x->substring == 0) generate_substring(g, p);
1105
if (x->command_count == 0 && x->starter == 0) return;
1107
if (x->starter != 0) generate(g, x->starter);
1110
if (p != 0 && p->type != c_literalstring) p = p->right;
1111
w(g, "~Mswitch(among_var) {~N~+");
1112
w(g, "~Mcase 0:~N~+");
1114
g->unreachable = false;
1118
if (p->type == c_bra && p->left != 0) {
1119
g->I[0] = case_number++;
1120
w(g, "~Mcase ~I0:~N~+");
1122
if (!g->unreachable) w(g, "~Mbreak;~N");
1124
g->unreachable = false;
1131
static void generate_booltest(struct generator * g, struct node * p)
1133
write_comment(g, p);
1135
write_failure_if(g, "!(~V0)", p);
1138
static void generate_false(struct generator * g, struct node * p)
1140
write_comment(g, p);
1144
static void generate_debug(struct generator * g, struct node * p)
1146
write_comment(g, p);
1147
g->I[0] = g->debug_count++;
1148
g->I[1] = p->line_number;
1149
writef(g, "~Mdebug(~I0, ~I1);~N", p);
1152
static void generate(struct generator * g, struct node * p)
1157
if (g->unreachable) return;
1159
a0 = g->failure_label;
1160
a1 = str_copy(g->failure_str);
1164
case c_define: generate_define(g, p); break;
1165
case c_bra: generate_bra(g, p); break;
1166
case c_and: generate_and(g, p); break;
1167
case c_or: generate_or(g, p); break;
1168
case c_backwards: generate_backwards(g, p); break;
1169
case c_not: generate_not(g, p); break;
1170
case c_set: generate_set(g, p); break;
1171
case c_unset: generate_unset(g, p); break;
1172
case c_try: generate_try(g, p); break;
1173
case c_fail: generate_fail(g, p); break;
1175
case c_test: generate_test(g, p); break;
1176
case c_do: generate_do(g, p); break;
1177
case c_goto: generate_GO(g, p, 1); break;
1178
case c_gopast: generate_GO(g, p, 0); break;
1179
case c_repeat: generate_repeat(g, p, 0); break;
1180
case c_loop: generate_loop(g, p); break;
1181
case c_atleast: generate_atleast(g, p); break;
1182
case c_setmark: generate_setmark(g, p); break;
1183
case c_tomark: generate_tomark(g, p); break;
1184
case c_atmark: generate_atmark(g, p); break;
1185
case c_hop: generate_hop(g, p); break;
1186
case c_delete: generate_delete(g, p); break;
1187
case c_next: generate_next(g, p); break;
1188
case c_tolimit: generate_tolimit(g, p); break;
1189
case c_atlimit: generate_atlimit(g, p); break;
1190
case c_leftslice: generate_leftslice(g, p); break;
1191
case c_rightslice: generate_rightslice(g, p); break;
1192
case c_assignto: generate_assignto(g, p); break;
1193
case c_sliceto: generate_sliceto(g, p); break;
1194
case c_assign: generate_assignfrom(g, p); break;
1196
case c_attach: generate_insert(g, p, p->type); break;
1197
case c_slicefrom: generate_slicefrom(g, p); break;
1198
case c_setlimit: generate_setlimit(g, p); break;
1199
case c_dollar: generate_dollar(g, p); break;
1200
case c_mathassign: generate_integer_assign(g, p, "="); break;
1201
case c_plusassign: generate_integer_assign(g, p, "+="); break;
1202
case c_minusassign: generate_integer_assign(g, p, "-="); break;
1203
case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
1204
case c_divideassign: generate_integer_assign(g, p, "/="); break;
1205
case c_eq: generate_integer_test(g, p, "=="); break;
1206
case c_ne: generate_integer_test(g, p, "!="); break;
1207
case c_gr: generate_integer_test(g, p, ">"); break;
1208
case c_ge: generate_integer_test(g, p, ">="); break;
1209
case c_ls: generate_integer_test(g, p, "<"); break;
1210
case c_le: generate_integer_test(g, p, "<="); break;
1211
case c_call: generate_call(g, p); break;
1212
case c_grouping: generate_grouping(g, p, false); break;
1213
case c_non: generate_grouping(g, p, true); break;
1214
case c_name: generate_namedstring(g, p); break;
1215
case c_literalstring: generate_literalstring(g, p); break;
1216
case c_among: generate_among(g, p); break;
1217
case c_substring: generate_substring(g, p); break;
1218
case c_booltest: generate_booltest(g, p); break;
1219
case c_false: generate_false(g, p); break;
1221
case c_debug: generate_debug(g, p); break;
1222
default: fprintf(stderr, "%d encountered\n", p->type);
1226
g->failure_label = a0;
1227
str_delete(g->failure_str);
1228
g->failure_str = a1;
1231
static void generate_start_comment(struct generator * g)
1233
w(g, "// This file was generated automatically by the Snowball to Java compiler~N");
1237
static void generate_class_begin(struct generator * g)
1239
w(g, "package " BASE_PACKAGE ".ext;~N"
1240
"import " BASE_PACKAGE "." BASE_CLASS ";~N"
1241
"import " BASE_PACKAGE ".Among;~N"
1244
" * Generated class implementing code defined by a snowball script.~N"
1246
"public class ~n extends " BASE_CLASS " {~N"
1250
static void generate_class_end(struct generator * g)
1256
static void generate_among_table(struct generator * g, struct among * x)
1258
struct amongvec * v = x->b;
1260
g->I[0] = x->number;
1261
g->I[1] = x->literalstring_count;
1263
w(g, "~+~+~Mprivate Among a_~I0[] = {~N~+");
1266
for (i = 0; i < x->literalstring_count; i++)
1270
g->I[2] = v->result;
1272
g->S[0] = i < x->literalstring_count - 1 ? "," : "";
1274
w(g, "~Mnew Among ( ~L0, ~I1, ~I2, \"");
1275
if (v->function != 0) {
1276
write_varname(g, v->function);
1278
w(g, "\", this)~S0~N");
1282
w(g, "~-~M};~-~-~N~N");
1285
static void generate_amongs(struct generator * g)
1287
struct among * x = g->analyser->amongs;
1289
generate_among_table(g, x);
1294
static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
1296
static int bit_is_set(symbol * b, int i) { return b[i/8] & 1 << i%8; }
1298
static void generate_grouping_table(struct generator * g, struct grouping * q)
1300
int range = q->largest_ch - q->smallest_ch + 1;
1301
int size = (range + 7)/ 8; /* assume 8 bits per symbol */
1303
symbol * map = create_b(size);
1305
for (i = 0; i < size; i++) map[i] = 0;
1307
/* Using unicode would require revision here */
1309
for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1312
for (i = 0; i < range; i++) unless (bit_is_set(map, i)) q->no_gaps = false;
1315
{ g->V[0] = q->name;
1317
w(g, "~+~+~Mprivate static final char ~V0[] = {");
1318
for (i = 0; i < size; i++)
1319
{ write_int(g, map[i]);
1320
if (i < size - 1) w(g, ", ");
1322
w(g, " };~N~-~-~N");
1327
static void generate_groupings(struct generator * g)
1328
{ struct grouping * q = g->analyser->groupings;
1330
{ generate_grouping_table(g, q);
1335
static void generate_members(struct generator * g)
1337
struct name * q = g->analyser->names;
1342
w(g, " private StringBuffer ~W0 = new StringBuffer();~N");
1345
w(g, " private int ~W0;~N");
1348
w(g, " private boolean ~W0;~N");
1356
static void generate_copyfrom(struct generator * g)
1359
w(g, "~+~+~Mprivate void copy_from(~n other) {~+~N");
1360
for (q = g->analyser->names; q != 0; q = q->next) {
1366
w(g, "~M~W0 = other.~W0;~N");
1370
w(g, "~Msuper.copy_from(other);~N");
1371
w(g, "~-~M}~-~-~N");
1374
static void generate_methods(struct generator * g)
1376
struct node * p = g->analyser->program;
1379
g->unreachable = false;
1384
extern void generate_program_java(struct generator * g)
1386
g->outbuf = str_new();
1387
g->failure_str = str_new();
1389
generate_start_comment(g);
1390
generate_class_begin(g);
1393
generate_groupings(g);
1395
generate_members(g);
1396
generate_copyfrom(g);
1397
generate_methods(g);
1399
generate_class_end(g);
1401
output_str(g->options->output_java, g->outbuf);
1402
str_delete(g->failure_str);
1403
str_delete(g->outbuf);
1406
extern struct generator * create_generator_java(struct analyser * a, struct options * o)
1413
g->unreachable = false;
1417
extern void close_generator_java(struct generator * g)