beta-0.89.2
[luatex.git] / source / texk / web2c / web2c / web2c-parser.y
blob773f489db0c03d743ffac5bc232ad240d3a36fef
1 /* web2c-parser.y -- parse some of Pascal, and output C, sort of.
3 This grammar has one shift/reduce conflict, from the
4 if-then[-else] rules, which is unresolvable. */
6 /* The order of some of the tokens here is significant. See the rules
7 for - and + in web2c-lexer.l. */
8 %token array_tok begin_tok case_tok const_tok do_tok downto_tok else_tok
9 end_tok file_tok for_tok function_tok goto_tok if_tok label_tok
10 of_tok procedure_tok program_tok record_tok repeat_tok then_tok
11 to_tok type_tok until_tok var_tok while_tok noreturn_tok
12 others_tok r_num_tok i_num_tok string_literal_tok single_char_tok
13 assign_tok two_dots_tok undef_id_tok var_id_tok
14 proc_id_tok proc_param_tok fun_id_tok fun_param_tok const_id_tok
15 type_id_tok hhb0_tok hhb1_tok field_id_tok define_tok field_tok
16 break_tok
18 %nonassoc '=' not_eq_tok '<' '>' less_eq_tok great_eq_tok
19 %left '+' '-' or_tok
20 %right unary_plus_tok unary_minus_tok
21 %left '*' '/' div_tok mod_tok and_tok
22 %right not_tok
25 #include "web2c.h"
27 #define YYDEBUG 1
29 #define symbol(x) sym_table[x].id
30 #define MAX_ARGS 50
32 static char fn_return_type[50], for_stack[300], control_var[50],
33 relation[3];
34 static char arg_type[MAX_ARGS][30];
35 static int last_type = -1, ids_typed;
36 static int proc_is_noreturn = 0;
37 char my_routine[100]; /* Name of routine being parsed, if any */
38 static char array_bounds[80], array_offset[80];
39 static int uses_mem, uses_eqtb, lower_sym, upper_sym;
40 static FILE *orig_out;
41 boolean doing_statements = false;
42 static boolean var_formals = false;
43 static int param_id_list[MAX_ARGS], ids_paramed=0;
45 extern char conditional[], temp[], *std_header;
46 extern int tex, mf, strict_for;
47 extern FILE *coerce;
48 extern char coerce_name[];
49 extern string program_name;
50 extern boolean debug;
52 static long my_labs (long);
53 static void compute_array_bounds (void);
54 static void fixup_var_list (void);
55 static void do_proc_args (void);
56 static void gen_function_head (void);
57 static boolean doreturn (string);
60 %start PROGRAM
63 PROGRAM:
64 DEFS
65 PROGRAM_HEAD
67 printf ("#define %s\n", uppercasify (program_name));
68 block_level++;
69 printf ("#include \"%s\"\n", std_header);
71 LABEL_DEC_PART CONST_DEC_PART TYPE_DEC_PART
72 VAR_DEC_PART
73 { printf ("\n#include \"%s\"\n", coerce_name); }
74 P_F_DEC_PART
75 BODY
76 { YYACCEPT; }
79 /* The @define statements we use to populate the symbol table. */
80 DEFS:
81 /* empty */
82 | DEFS DEF
84 DEF:
85 define_tok field_tok undef_id_tok ';'
87 ii = add_to_table (last_id);
88 sym_table[ii].typ = field_id_tok;
90 | define_tok function_tok undef_id_tok ';'
92 ii = add_to_table (last_id);
93 sym_table[ii].typ = fun_id_tok;
95 | define_tok const_tok undef_id_tok ';'
97 ii = add_to_table (last_id);
98 sym_table[ii].typ = const_id_tok;
100 | define_tok function_tok undef_id_tok '(' ')' ';'
102 ii = add_to_table (last_id);
103 sym_table[ii].typ = fun_param_tok;
105 | define_tok procedure_tok undef_id_tok ';'
107 ii = add_to_table (last_id);
108 sym_table[ii].typ = proc_id_tok;
110 | define_tok procedure_tok undef_id_tok '(' ')' ';'
112 ii = add_to_table (last_id);
113 sym_table[ii].typ = proc_param_tok;
115 | define_tok type_tok undef_id_tok ';'
117 ii = add_to_table (last_id);
118 sym_table[ii].typ = type_id_tok;
120 | define_tok type_tok undef_id_tok '=' SUBRANGE_TYPE ';'
122 ii = add_to_table (last_id);
123 sym_table[ii].typ = type_id_tok;
124 sym_table[ii].val = lower_bound;
125 sym_table[ii].val_sym = lower_sym;
126 sym_table[ii].upper = upper_bound;
127 sym_table[ii].upper_sym = upper_sym;
129 | define_tok var_tok undef_id_tok ';'
131 ii = add_to_table (last_id);
132 sym_table[ii].typ = var_id_tok;
136 /* program statement. Ignore any files. */
137 PROGRAM_HEAD:
138 program_tok undef_id_tok PROGRAM_FILE_PART ';'
141 PROGRAM_FILE_PART:
142 '(' PROGRAM_FILE_LIST ')'
143 | /* empty */
146 PROGRAM_FILE_LIST:
147 PROGRAM_FILE
148 | PROGRAM_FILE_LIST ',' PROGRAM_FILE
151 PROGRAM_FILE:
152 const_id_tok /* input and output are constants */
153 | undef_id_tok
156 BLOCK:
157 { if (block_level > 0) my_output("{\n ");
158 indent++; block_level++;
160 LABEL_DEC_PART
161 CONST_DEC_PART TYPE_DEC_PART
162 { if (block_level == 2) {
163 if (strcmp(fn_return_type, "void")) {
164 my_output("register");
165 my_output(fn_return_type);
166 my_output("Result;");
168 if (tex) {
169 sprintf(safe_string, "%s_regmem", my_routine);
170 my_output(safe_string);
171 new_line();
175 VAR_DEC_PART
176 { doing_statements = true; }
177 STAT_PART
179 if (block_level == 2) {
180 if (strcmp(fn_return_type,"void")) {
181 my_output("return Result");
182 semicolon();
184 if (tex) {
185 if (uses_mem && uses_eqtb)
186 fprintf(coerce,
187 "#define %s_regmem register memoryword *mem=zmem, *eqtb=zeqtb;\n",
188 my_routine);
189 else if (uses_mem)
190 fprintf(coerce, "#define %s_regmem register memoryword *mem=zmem;\n",
191 my_routine);
192 else if (uses_eqtb)
193 fprintf(coerce, "#define %s_regmem register memoryword *eqtb=zeqtb;\n",
194 my_routine);
195 else
196 fprintf(coerce, "#define %s_regmem\n", my_routine);
198 my_routine[0] = '\0';
200 indent--; block_level--;
201 my_output("}"); new_line();
202 doing_statements = false;
206 LABEL_DEC_PART: /* empty */
207 | label_tok
208 { my_output("/*"); }
209 LABEL_LIST ';'
210 { my_output("*/"); }
213 LABEL_LIST: LABEL
214 | LABEL_LIST ',' LABEL
217 LABEL:
218 i_num_tok { my_output(temp); }
221 CONST_DEC_PART:
222 /* empty */
223 | const_tok CONST_DEC_LIST
224 { new_line(); }
227 CONST_DEC_LIST:
228 CONST_DEC
229 | CONST_DEC_LIST CONST_DEC
232 CONST_DEC:
233 { /* `#define' must be in column 1 for pcc. */
234 unsigned save = indent;
235 new_line ();
236 indent = 0;
237 my_output ("#define");
238 indent = save;
240 undef_id_tok
241 { ii = add_to_table (last_id);
242 sym_table[ii].typ = const_id_tok;
243 my_output (last_id);
245 '=' { my_output ("("); }
246 CONSTANT_EXPRESS { my_output (")"); }
247 ';' { sym_table[ii].val = last_i_num; new_line(); }
250 CONSTANT:
251 i_num_tok
253 sscanf (temp, "%ld", &last_i_num);
254 if (my_labs ((long) last_i_num) > 32767)
255 strcat (temp, "L");
256 my_output (temp);
257 $$ = ex_32;
259 | r_num_tok { my_output(temp); $$ = ex_real; }
260 | STRING { $$ = 0; }
261 | CONSTANT_ID { $$ = ex_32; }
264 CONSTANT_EXPRESS:
265 UNARY_OP CONSTANT_EXPRESS %prec '*'
266 { $$ = $2; }
267 | CONSTANT_EXPRESS '+' { my_output ("+"); }
268 CONSTANT_EXPRESS { $$ = max ($1, $4); }
269 | CONSTANT_EXPRESS '-' { my_output ("-"); }
270 CONSTANT_EXPRESS { $$ = max ($1, $4); }
271 | CONSTANT_EXPRESS '*' { my_output ("*"); }
272 CONSTANT_EXPRESS { $$ = max ($1, $4); }
273 | CONSTANT_EXPRESS div_tok { my_output ("/"); }
274 CONSTANT_EXPRESS { $$ = max ($1, $4); }
275 | CONSTANT_EXPRESS '=' { my_output ("=="); }
276 CONSTANT_EXPRESS { $$ = max ($1, $4); }
277 | CONSTANT_EXPRESS not_eq_tok { my_output ("!="); }
278 CONSTANT_EXPRESS { $$ = max ($1, $4); }
279 | CONSTANT_EXPRESS mod_tok { my_output ("%"); }
280 CONSTANT_EXPRESS { $$ = max ($1, $4); }
281 | CONSTANT_EXPRESS '<' { my_output ("<"); }
282 CONSTANT_EXPRESS { $$ = max ($1, $4); }
283 | CONSTANT_EXPRESS '>' { my_output (">"); }
284 CONSTANT_EXPRESS { $$ = max ($1, $4); }
285 | CONSTANT_EXPRESS less_eq_tok { my_output ("<="); }
286 CONSTANT_EXPRESS { $$ = max ($1, $4); }
287 | CONSTANT_EXPRESS great_eq_tok { my_output (">="); }
288 CONSTANT_EXPRESS { $$ = max ($1, $4); }
289 | CONSTANT_EXPRESS and_tok { my_output ("&&"); }
290 CONSTANT_EXPRESS { $$ = max ($1, $4); }
291 | CONSTANT_EXPRESS or_tok { my_output ("||"); }
292 CONSTANT_EXPRESS { $$ = max ($1, $4); }
293 | CONSTANT_EXPRESS '/' { my_output ("/ ((double)"); }
294 CONSTANT_EXPRESS { $$ = max ($1, $4); my_output (")"); }
295 | CONST_FACTOR { $$ = $1; }
298 CONST_FACTOR:
300 { my_output ("("); }
301 CONSTANT_EXPRESS ')'
302 { my_output (")"); $$ = $1; }
303 | CONSTANT
306 STRING:
307 string_literal_tok
309 char s[132];
310 get_string_literal(s);
311 my_output (s);
313 | single_char_tok
315 char s[5];
316 get_single_char(s);
317 my_output (s);
321 CONSTANT_ID:
322 const_id_tok { my_output (last_id); }
325 TYPE_DEC_PART: /* empty */
326 | type_tok TYPE_DEF_LIST
329 TYPE_DEF_LIST: TYPE_DEF
330 | TYPE_DEF_LIST TYPE_DEF
333 TYPE_DEF:
334 { my_output ("typedef"); }
335 undef_id_tok
337 ii = add_to_table(last_id);
338 sym_table[ii].typ = type_id_tok;
339 strcpy(safe_string, last_id);
340 last_type = ii;
344 array_bounds[0] = 0;
345 array_offset[0] = 0;
347 TYPE ';'
349 if (*array_offset) {
350 yyerror ("Cannot typedef arrays with offsets");
352 my_output (safe_string);
353 my_output (array_bounds);
354 semicolon ();
355 last_type = -1;
359 TYPE:
360 SIMPLE_TYPE
361 | STRUCTURED_TYPE
364 SIMPLE_TYPE:
365 SUBRANGE_TYPE
367 if (last_type >= 0)
369 sym_table[ii].val = lower_bound;
370 sym_table[ii].val_sym = lower_sym;
371 sym_table[ii].upper = upper_bound;
372 sym_table[ii].upper_sym = upper_sym;
373 ii= -1;
376 /* If the bounds on an integral type are known at
377 translation time, select the smallest ANSI C type which
378 can represent it. We avoid using char as such variables
379 are frequently used as array indices. We avoid using
380 schar and unsigned short where possible, since they are
381 treated differently by different compilers
382 (see also config.h). */
383 if (lower_sym == -1 && upper_sym == -1) {
384 if (0 <= lower_bound && upper_bound <= UCHAR_MAX)
385 my_output ("unsigned char");
386 else if (SCHAR_MIN <= lower_bound && upper_bound <= SCHAR_MAX)
387 my_output ("schar");
388 else if (SHRT_MIN <= lower_bound && upper_bound <= SHRT_MAX)
389 my_output ("short");
390 else if (0 <= lower_bound && upper_bound <= USHRT_MAX)
391 my_output ("unsigned short");
392 else
393 my_output ("integer");
394 } else {
395 my_output ("integer");
398 | TYPE_ID
401 SUBRANGE_TYPE:
402 SUBRANGE_CONSTANT two_dots_tok SUBRANGE_CONSTANT
405 POSSIBLE_PLUS:
406 /* empty */
407 | unary_plus_tok
410 SUBRANGE_CONSTANT:
411 POSSIBLE_PLUS i_num_tok
413 lower_bound = upper_bound;
414 lower_sym = upper_sym;
415 sscanf (temp, "%ld", &upper_bound);
416 upper_sym = -1; /* no sym table entry */
418 | const_id_tok
420 lower_bound = upper_bound;
421 lower_sym = upper_sym;
422 upper_bound = sym_table[l_s].val;
423 upper_sym = l_s;
425 | var_id_tok
426 { /* We've changed some constants into dynamic variables.
427 To avoid changing all the subrange decls, just use integer.
428 This does not work for arrays, for which we check later. */
429 lower_bound = upper_bound;
430 lower_sym = upper_sym;
431 upper_bound = 0;
432 upper_sym = 0; /* Translate to integer. */
434 | undef_id_tok
435 { /* Same as var_id_tok, to avoid changing type definitions.
436 Should keep track of the variables we use in this way
437 and make sure they're all eventually defined. */
438 lower_bound = upper_bound;
439 lower_sym = upper_sym;
440 upper_bound = 0;
441 upper_sym = 0;
445 TYPE_ID:
446 type_id_tok
448 if (last_type >= 0) {
449 sym_table[last_type].var_not_needed = sym_table[l_s].var_not_needed;
450 sym_table[last_type].upper = sym_table[l_s].upper;
451 sym_table[last_type].upper_sym = sym_table[l_s].upper_sym;
452 sym_table[last_type].val = sym_table[l_s].val;
453 sym_table[last_type].val_sym = sym_table[l_s].val_sym;
455 my_output (last_id);
459 STRUCTURED_TYPE:
460 ARRAY_TYPE
461 { if (last_type >= 0)
462 sym_table[last_type].var_not_needed = true;
464 | RECORD_TYPE
465 | FILE_TYPE
466 { if (last_type >= 0)
467 sym_table[last_type].var_not_needed = true;
469 | POINTER_TYPE
470 { if (last_type >= 0)
471 sym_table[last_type].var_not_needed = true;
475 POINTER_TYPE:
476 '^' type_id_tok
478 if (last_type >= 0) {
479 sym_table[last_type].var_not_needed = sym_table[l_s].var_not_needed;
480 sym_table[last_type].upper = sym_table[l_s].upper;
481 sym_table[last_type].upper_sym = sym_table[l_s].upper_sym;
482 sym_table[last_type].val = sym_table[l_s].val;
483 sym_table[last_type].val_sym = sym_table[l_s].val_sym;
485 my_output (last_id);
486 my_output ("*");
490 ARRAY_TYPE:
491 array_tok '[' INDEX_TYPE ']' of_tok COMPONENT_TYPE
492 | array_tok '[' INDEX_TYPE ',' INDEX_TYPE ']' of_tok COMPONENT_TYPE
495 INDEX_TYPE:
496 SUBRANGE_TYPE
497 { compute_array_bounds(); }
498 | type_id_tok
500 lower_bound = sym_table[l_s].val;
501 lower_sym = sym_table[l_s].val_sym;
502 upper_bound = sym_table[l_s].upper;
503 upper_sym = sym_table[l_s].upper_sym;
504 compute_array_bounds();
508 COMPONENT_TYPE: TYPE ;
510 RECORD_TYPE:
511 record_tok
512 { my_output ("struct"); my_output ("{"); indent++; }
513 FIELD_LIST end_tok
514 { indent--; my_output ("}"); semicolon(); }
517 FIELD_LIST: RECORD_SECTION
518 | FIELD_LIST ';' RECORD_SECTION
521 RECORD_SECTION:
522 { field_list[0] = 0; }
523 FIELD_ID_LIST ':'
525 /*array_bounds[0] = 0;
526 array_offset[0] = 0;*/
528 TYPE
529 { int i=0, j; char ltemp[80];
530 while(field_list[i++] == '!') {
531 j = 0;
532 while (field_list[i])
533 ltemp[j++] = field_list[i++];
534 i++;
535 if (field_list[i] == '!')
536 ltemp[j++] = ',';
537 ltemp[j] = 0;
538 my_output (ltemp);
540 semicolon();
542 | /* empty */
545 FIELD_ID_LIST: FIELD_ID
546 | FIELD_ID_LIST ',' FIELD_ID
549 FIELD_ID: undef_id_tok
550 { int i=0, j=0;
551 while (field_list[i] == '!')
552 while(field_list[i++]);
553 ii = add_to_table(last_id);
554 sym_table[ii].typ = field_id_tok;
555 field_list[i++] = '!';
556 while (last_id[j])
557 field_list[i++] = last_id[j++];
558 field_list[i++] = 0;
559 field_list[i++] = 0;
561 | field_id_tok
562 { int i=0, j=0;
563 while (field_list[i] == '!')
564 while(field_list[i++]);
565 field_list[i++] = '!';
566 while (last_id[j])
567 field_list[i++] = last_id[j++];
568 field_list[i++] = 0;
569 field_list[i++] = 0;
573 FILE_TYPE:
574 file_tok of_tok
575 { my_output ("text /* of "); }
576 TYPE
577 { my_output ("*/"); }
580 VAR_DEC_PART:
581 /* empty */
582 | var_tok VAR_DEC_LIST
585 VAR_DEC_LIST:
586 VAR_DEC
587 | VAR_DEC_LIST VAR_DEC
590 VAR_DEC:
592 var_list[0] = 0;
593 array_bounds[0] = 0;
594 array_offset[0] = 0;
595 var_formals = false;
596 ids_paramed = 0;
598 VAR_ID_DEC_LIST ':'
600 array_bounds[0] = 0;
601 array_offset[0] = 0;
603 TYPE ';'
604 { fixup_var_list(); }
607 VAR_ID_DEC_LIST: VAR_ID
608 | VAR_ID_DEC_LIST ',' VAR_ID
611 VAR_ID: undef_id_tok
612 { int i=0, j=0;
613 ii = add_to_table(last_id);
614 sym_table[ii].typ = var_id_tok;
615 sym_table[ii].var_formal = var_formals;
616 param_id_list[ids_paramed++] = ii;
617 while (var_list[i] == '!')
618 while(var_list[i++]);
619 var_list[i++] = '!';
620 while (last_id[j])
621 var_list[i++] = last_id[j++];
622 var_list[i++] = 0;
623 var_list[i++] = 0;
625 | var_id_tok
626 { int i=0, j=0;
627 ii = add_to_table(last_id);
628 sym_table[ii].typ = var_id_tok;
629 sym_table[ii].var_formal = var_formals;
630 param_id_list[ids_paramed++] = ii;
631 while (var_list[i] == '!')
632 while (var_list[i++]);
633 var_list[i++] = '!';
634 while (last_id[j])
635 var_list[i++] = last_id[j++];
636 var_list[i++] = 0;
637 var_list[i++] = 0;
639 | field_id_tok
640 { int i=0, j=0;
641 ii = add_to_table(last_id);
642 sym_table[ii].typ = var_id_tok;
643 sym_table[ii].var_formal = var_formals;
644 param_id_list[ids_paramed++] = ii;
645 while (var_list[i] == '!')
646 while(var_list[i++]);
647 var_list[i++] = '!';
648 while (last_id[j])
649 var_list[i++] = last_id[j++];
650 var_list[i++] = 0;
651 var_list[i++] = 0;
655 BODY:
656 /* empty */
657 | begin_tok
658 { my_output ("void mainbody( void ) {");
659 indent++;
660 new_line ();
662 STAT_LIST end_tok '.'
663 { indent--;
664 my_output ("}");
665 new_line ();
669 P_F_DEC_PART:
670 P_F_DEC
671 | P_F_DEC_PART P_F_DEC
674 P_F_DEC: PROCEDURE_DEC ';'
675 { new_line(); remove_locals(); }
676 | FUNCTION_DEC ';'
677 { new_line(); remove_locals(); }
680 PROCEDURE_DEC:
681 PROCEDURE_HEAD BLOCK ;
683 PROCEDURE_TOK:
684 procedure_tok
685 | noreturn_tok
686 { proc_is_noreturn = 1; }
687 procedure_tok
690 PROCEDURE_HEAD:
691 PROCEDURE_TOK undef_id_tok
692 { ii = add_to_table(last_id);
693 if (debug)
694 fprintf(stderr, "%3d Procedure %s\n", pf_count++, last_id);
695 sym_table[ii].typ = proc_id_tok;
696 strcpy(my_routine, last_id);
697 uses_eqtb = uses_mem = false;
698 my_output ("void");
699 new_line ();
700 orig_out = out;
701 out = 0;
703 PARAM ';'
704 { strcpy(fn_return_type, "void");
705 do_proc_args();
706 gen_function_head(); }
707 | procedure_tok DECLARED_PROC
708 { ii = l_s;
709 if (debug)
710 fprintf(stderr, "%3d Procedure %s\n", pf_count++, last_id);
711 strcpy(my_routine, last_id);
712 my_output ("void");
713 new_line ();
715 PARAM ';'
716 { strcpy(fn_return_type, "void");
717 do_proc_args();
718 gen_function_head();
722 PARAM:
723 /* empty */
725 strcpy (z_id, last_id);
726 mark ();
727 ids_paramed = 0;
729 | '('
730 { sprintf (z_id, "z%s", last_id);
731 ids_paramed = 0;
732 if (sym_table[ii].typ == proc_id_tok)
733 sym_table[ii].typ = proc_param_tok;
734 else if (sym_table[ii].typ == fun_id_tok)
735 sym_table[ii].typ = fun_param_tok;
736 mark();
738 FORM_PAR_SEC_L ')'
741 FORM_PAR_SEC_L: FORM_PAR_SEC
742 | FORM_PAR_SEC_L ';' FORM_PAR_SEC
745 FORM_PAR_SEC1:
746 { ids_typed = ids_paramed; }
747 VAR_ID_DEC_LIST ':' type_id_tok
748 { int i, need_var;
749 i = search_table(last_id);
750 need_var = !sym_table[i].var_not_needed;
751 for (i=ids_typed; i<ids_paramed; i++)
753 strcpy(arg_type[i], last_id);
754 if (need_var && sym_table[param_id_list[i]].var_formal)
755 strcat(arg_type[i], " *");
756 else
757 sym_table[param_id_list[i]].var_formal = false;
762 FORM_PAR_SEC: {var_formals = 0; } FORM_PAR_SEC1
763 | var_tok {var_formals = 1; } FORM_PAR_SEC1
766 DECLARED_PROC:
767 proc_id_tok
768 | proc_param_tok
771 FUNCTION_DEC: FUNCTION_HEAD BLOCK ;
773 FUNCTION_HEAD:
774 function_tok undef_id_tok
776 orig_out = out;
777 out = 0;
778 ii = add_to_table(last_id);
779 if (debug)
780 fprintf(stderr, "%3d Function %s\n", pf_count++, last_id);
781 sym_table[ii].typ = fun_id_tok;
782 strcpy (my_routine, last_id);
783 uses_eqtb = uses_mem = false;
785 PARAM ':'
787 normal();
788 array_bounds[0] = 0;
789 array_offset[0] = 0;
791 RESULT_TYPE
793 get_result_type(fn_return_type);
794 do_proc_args();
795 gen_function_head();
798 | function_tok DECLARED_FUN
800 orig_out = out;
801 out = 0;
802 ii = l_s;
803 if (debug)
804 fprintf(stderr, "%3d Function %s\n", pf_count++, last_id);
805 strcpy(my_routine, last_id);
806 uses_eqtb = uses_mem = false;
808 PARAM ':'
809 { normal();
810 array_bounds[0] = 0;
811 array_offset[0] = 0;
813 RESULT_TYPE
814 { get_result_type(fn_return_type);
815 do_proc_args();
816 gen_function_head();
821 DECLARED_FUN: fun_id_tok
822 | fun_param_tok
825 RESULT_TYPE: TYPE
828 STAT_PART: begin_tok STAT_LIST end_tok
831 COMPOUND_STAT: begin_tok
832 { my_output ("{"); indent++; new_line(); }
833 STAT_LIST end_tok
834 { indent--; my_output ("}"); new_line(); }
837 STAT_LIST: STATEMENT
838 | STAT_LIST ';' STATEMENT
841 STATEMENT: UNLAB_STAT
842 | S_LABEL ':'
843 UNLAB_STAT
846 S_LABEL: i_num_tok
847 {if (!doreturn(temp)) {
848 sprintf(safe_string, "lab%s:", temp);
849 my_output (safe_string);
854 UNLAB_STAT: SIMPLE_STAT
855 { semicolon(); }
856 | STRUCT_STAT
857 { semicolon(); }
860 SIMPLE_STAT: ASSIGN_STAT
861 | PROC_STAT
862 | GO_TO_STAT
863 | EMPTY_STAT
864 | break_tok
865 { my_output ("break"); }
868 ASSIGN_STAT: VARIABLE assign_tok
869 { my_output ("="); }
870 EXPRESS
871 | FUNC_ID_AS assign_tok
872 { my_output ("Result ="); }
873 EXPRESS
876 VARIABLE: var_id_tok
877 { if (strcmp(last_id, "mem") == 0)
878 uses_mem = 1;
879 else if (strcmp(last_id, "eqtb") == 0)
880 uses_eqtb = 1;
881 if (sym_table[l_s].var_formal)
882 putchar('*');
883 my_output (last_id);
884 $$ = ex_32;
886 VAR_DESIG_LIST
887 | var_id_tok
888 { if (sym_table[l_s].var_formal)
889 putchar('*');
890 my_output (last_id); $$ = ex_32; }
893 FUNC_ID_AS: fun_id_tok
894 { $$ = ex_32; }
895 | fun_param_tok
896 { $$ = ex_32; }
899 VAR_DESIG_LIST: VAR_DESIG
900 | VAR_DESIG_LIST VAR_DESIG
903 VAR_DESIG: '['
904 { my_output ("["); }
905 EXPRESS VAR_DESIG1
906 { my_output ("]"); }
907 | '.' field_id_tok
908 {if (tex || mf) {
909 if (strcmp(last_id, "int")==0)
910 my_output (".cint");
911 else if (strcmp(last_id, "lh")==0)
912 my_output (".v.LH");
913 else if (strcmp(last_id, "rh")==0)
914 my_output (".v.RH");
915 else {
916 sprintf(safe_string, ".%s", last_id);
917 my_output (safe_string);
920 else {
921 sprintf(safe_string, ".%s", last_id);
922 my_output (safe_string);
925 | '.' hhb0_tok
926 { my_output (".hh.b0"); }
927 | '.' hhb1_tok
928 { my_output (".hh.b1"); }
931 VAR_DESIG1: ']'
932 | ','
933 { my_output ("]["); }
934 EXPRESS ']'
937 EXPRESS: UNARY_OP EXPRESS %prec '*'
938 { $$ = $2; }
939 | EXPRESS '+' { my_output ("+"); } EXPRESS
940 { $$ = max ($1, $4); }
941 | EXPRESS '-' { my_output ("-"); } EXPRESS
942 { $$ = max ($1, $4); }
943 | EXPRESS '*' { my_output ("*"); } EXPRESS
944 { $$ = max ($1, $4); }
945 | EXPRESS div_tok { my_output ("/"); } EXPRESS
946 { $$ = max ($1, $4); }
947 | EXPRESS '=' { my_output ("=="); } EXPRESS
948 { $$ = max ($1, $4); }
949 | EXPRESS not_eq_tok { my_output ("!="); } EXPRESS
950 { $$ = max ($1, $4); }
951 | EXPRESS mod_tok { my_output ("%"); } EXPRESS
952 { $$ = max ($1, $4); }
953 | EXPRESS '<' { my_output ("<"); } EXPRESS
954 { $$ = max ($1, $4); }
955 | EXPRESS '>' { my_output (">"); } EXPRESS
956 { $$ = max ($1, $4); }
957 | EXPRESS less_eq_tok { my_output ("<="); } EXPRESS
958 { $$ = max ($1, $4); }
959 | EXPRESS great_eq_tok { my_output (">="); } EXPRESS
960 { $$ = max ($1, $4); }
961 | EXPRESS and_tok { my_output ("&&"); } EXPRESS
962 { $$ = max ($1, $4); }
963 | EXPRESS or_tok { my_output ("||"); } EXPRESS
964 { $$ = max ($1, $4); }
965 | EXPRESS '/'
966 { my_output ("/ ((double)"); }
967 EXPRESS
968 { $$ = max ($1, $4); my_output (")"); }
969 | FACTOR
970 { $$ = $1; }
973 UNARY_OP:
974 unary_plus_tok
975 | unary_minus_tok
976 { my_output ("- (integer)"); }
977 | not_tok
978 { my_output ("!"); }
981 FACTOR:
983 { my_output ("("); }
984 EXPRESS ')'
985 { my_output (")"); $$ = $1; }
986 | VARIABLE
987 | CONSTANT
988 | fun_id_tok
989 { my_output (last_id); my_output ("()"); }
990 | fun_param_tok
991 { my_output (last_id); }
992 PARAM_LIST
995 PARAM_LIST:
996 '(' { my_output ("("); }
997 ACTUAL_PARAM_L ')' { my_output (")"); }
1000 ACTUAL_PARAM_L:
1001 ACTUAL_PARAM
1002 | ACTUAL_PARAM_L ',' { my_output (","); }
1003 ACTUAL_PARAM
1006 ACTUAL_PARAM:
1007 EXPRESS WIDTH_FIELD
1008 | type_id_tok /* So we can pass type names to C macros. */
1009 { my_output (last_id); }
1012 WIDTH_FIELD:
1013 ':' i_num_tok
1014 | /* empty */
1017 PROC_STAT: proc_id_tok
1018 { my_output (last_id); my_output ("()"); }
1019 | undef_id_tok
1020 { my_output (last_id);
1021 ii = add_to_table(last_id);
1022 sym_table[ii].typ = proc_id_tok;
1023 my_output ("()");
1025 | proc_param_tok
1026 { my_output (last_id); }
1027 PARAM_LIST
1030 GO_TO_STAT: goto_tok i_num_tok
1031 {if (doreturn(temp)) {
1032 if (strcmp(fn_return_type,"void"))
1033 my_output ("return Result");
1034 else
1035 my_output ("return");
1036 } else {
1037 sprintf(safe_string, "goto lab%s",
1038 temp);
1039 my_output (safe_string);
1044 EMPTY_STAT: /* empty */
1047 STRUCT_STAT: COMPOUND_STAT
1048 | CONDIT_STAT
1049 | REPETIT_STAT
1052 CONDIT_STAT: IF_STATEMENT
1053 | CASE_STATEMENT
1056 IF_STATEMENT: if_tok
1057 { my_output ("if"); my_output ("("); }
1058 IF_THEN_ELSE_STAT
1061 IF_THEN_ELSE_STAT: EXPRESS
1062 { my_output (")"); }
1063 THEN_ELSE_STAT
1066 THEN_ELSE_STAT: then_tok
1067 { new_line (); }
1068 STATEMENT ELSE_STAT
1069 | then_tok if_tok
1070 { my_output ("{"); indent++; new_line();
1071 my_output ("if"); my_output ("("); }
1072 IF_THEN_ELSE_STAT
1073 { indent--; my_output ("}"); new_line(); }
1074 ELSE_STAT
1077 ELSE_STAT: /* empty */
1078 | else_tok
1079 { my_output ("else"); }
1080 STATEMENT
1083 CASE_STATEMENT: case_tok
1084 { my_output ("switch"); my_output ("("); }
1085 EXPRESS of_tok
1086 { my_output (")"); new_line();
1087 my_output ("{"); indent++;
1089 CASE_EL_LIST END_CASE
1090 { indent--; my_output ("}"); new_line(); }
1093 CASE_EL_LIST: CASE_ELEMENT
1094 | CASE_EL_LIST ';' CASE_ELEMENT
1097 CASE_ELEMENT: CASE_LAB_LIST ':' UNLAB_STAT
1098 { my_output ("break"); semicolon(); }
1101 CASE_LAB_LIST: CASE_LAB
1102 | CASE_LAB_LIST ',' CASE_LAB
1105 CASE_LAB: i_num_tok
1106 { my_output ("case");
1107 my_output (temp);
1108 my_output (":"); new_line();
1110 | others_tok
1111 { my_output ("default:"); new_line(); }
1114 END_CASE: end_tok
1115 | ';' end_tok
1118 REPETIT_STAT: WHILE_STATEMENT
1119 | REP_STATEMENT
1120 | FOR_STATEMENT
1123 WHILE_STATEMENT: while_tok
1124 { my_output ("while");
1125 my_output ("(");
1127 EXPRESS
1128 { my_output (")"); }
1129 do_tok STATEMENT
1132 REP_STATEMENT: repeat_tok
1133 { my_output ("do"); my_output ("{"); indent++; }
1134 STAT_LIST until_tok
1135 { indent--; my_output ("}");
1136 my_output ("while"); my_output ("( ! (");
1138 EXPRESS
1139 { my_output (") )"); }
1142 FOR_STATEMENT: for_tok
1144 my_output ("{");
1145 my_output ("register");
1146 my_output ("integer");
1147 if (strict_for)
1148 my_output ("for_begin,");
1149 my_output ("for_end;");
1151 CONTROL_VAR assign_tok
1152 { if (strict_for)
1153 my_output ("for_begin");
1154 else
1155 my_output (control_var);
1156 my_output ("="); }
1157 FOR_LIST do_tok
1158 { my_output ("; if (");
1159 if (strict_for) my_output ("for_begin");
1160 else my_output (control_var);
1161 my_output (relation);
1162 my_output ("for_end)");
1163 if (strict_for) {
1164 my_output ("{");
1165 my_output (control_var);
1166 my_output ("=");
1167 my_output ("for_begin");
1168 semicolon();
1170 my_output ("do");
1171 indent++;
1172 new_line();
1174 STATEMENT
1176 char *top = strrchr (for_stack, '#');
1177 indent--;
1178 new_line();
1179 my_output ("while");
1180 my_output ("(");
1181 my_output (top+1);
1182 my_output (")");
1183 my_output (";");
1184 my_output ("}");
1185 if (strict_for)
1186 my_output ("}");
1187 *top=0;
1188 new_line();
1192 CONTROL_VAR: var_id_tok
1193 { strcpy(control_var, last_id); }
1196 FOR_LIST: EXPRESS
1197 { my_output (";"); }
1198 to_tok
1200 strcpy(relation, "<=");
1201 my_output ("for_end");
1202 my_output ("="); }
1203 EXPRESS
1205 sprintf(for_stack + strlen(for_stack),
1206 "#%s++ < for_end", control_var);
1208 | EXPRESS
1209 { my_output (";"); }
1210 downto_tok
1212 strcpy(relation, ">=");
1213 my_output ("for_end");
1214 my_output ("="); }
1215 EXPRESS
1217 sprintf(for_stack + strlen(for_stack),
1218 "#%s-- > for_end", control_var);
1223 static void
1224 compute_array_bounds (void)
1226 long lb;
1227 char tmp[200];
1229 if (lower_sym == 0 || upper_sym == 0) {
1230 yyerror ("Cannot handle variable subrange in array decl");
1232 else if (lower_sym == -1) { /* lower is a constant */
1233 lb = lower_bound - 1;
1234 if (lb==0) lb = -1; /* Treat lower_bound==1 as if lower_bound==0 */
1235 if (upper_sym == -1) /* both constants */
1236 sprintf(tmp, "[%ld]", upper_bound - lb);
1237 else { /* upper a symbol, lower constant */
1238 if (lb < 0)
1239 sprintf(tmp, "[%s + %ld]",
1240 symbol(upper_sym), (-lb));
1241 else
1242 sprintf(tmp, "[%s - %ld]",
1243 symbol(upper_sym), lb);
1245 if (lower_bound < 0 || lower_bound > 1) {
1246 if (*array_bounds) {
1247 yyerror ("Cannot handle offset in second dimension");
1249 if (lower_bound < 0) {
1250 sprintf(array_offset, "+%ld", -lower_bound);
1251 } else {
1252 sprintf(array_offset, "-%ld", lower_bound);
1255 strcat(array_bounds, tmp);
1256 } else { /* lower is a symbol */
1257 if (upper_sym != -1) /* both are symbols */
1258 sprintf(tmp, "[%s - %s + 1]", symbol(upper_sym),
1259 symbol(lower_sym));
1260 else { /* upper constant, lower symbol */
1261 sprintf(tmp, "[%ld - %s]", upper_bound + 1,
1262 symbol(lower_sym));
1264 if (*array_bounds) {
1265 yyerror ("Cannot handle symbolic offset in second dimension");
1267 sprintf(array_offset, "- (int)(%s)", symbol(lower_sym));
1268 strcat(array_bounds, tmp);
1273 /* Kludge around negative lower array bounds. */
1275 static void
1276 fixup_var_list (void)
1278 int i, j;
1279 char output_string[100], real_symbol[100];
1281 for (i = 0; var_list[i++] == '!'; )
1283 for (j = 0; (real_symbol[j++] = var_list[i++]); )
1285 if (*array_offset)
1287 fprintf (out, "\n#define %s (%s %s)\n ",
1288 real_symbol, next_temp, array_offset);
1289 strcpy (real_symbol, next_temp);
1290 /* Add the temp to the symbol table, so that change files can
1291 use it later on if necessary. */
1292 j = add_to_table (next_temp);
1293 sym_table[j].typ = var_id_tok;
1294 find_next_temp ();
1296 sprintf (output_string, "%s%s%c", real_symbol, array_bounds,
1297 var_list[i] == '!' ? ',' : ' ');
1298 my_output (output_string);
1300 semicolon ();
1304 /* If we're not processing TeX, we return false. Otherwise,
1305 return true if the label is "10" and we're not in one of four TeX
1306 routines where the line labeled "10" isn't the end of the routine.
1307 Otherwise, return 0. */
1309 static boolean
1310 doreturn (string label)
1312 return
1314 && STREQ (label, "10")
1315 && !STREQ (my_routine, "macrocall")
1316 && !STREQ (my_routine, "hpack")
1317 && !STREQ (my_routine, "vpackage")
1318 && !STREQ (my_routine, "trybreak");
1322 /* Return the absolute value of a long. */
1323 static long
1324 my_labs (long x)
1326 if (x < 0L) return(-x);
1327 return(x);
1331 /* Output current function declaration to coerce file. */
1333 static void
1334 do_proc_args (void)
1336 /* If we want ANSI code and one of the parameters is a var
1337 parameter, then use the #define to add the &. We do this by
1338 adding a 'z' at the front of the name. gen_function_head will do
1339 the real work. */
1340 int i;
1341 int var = 0;
1342 for (i = 0; i < ids_paramed; ++i)
1343 var += sym_table[param_id_list[i]].var_formal;
1344 if (var) {
1345 for (i = strlen (z_id); i >= 0; --i)
1346 z_id[i+1] = z_id[i];
1347 z_id[0] = 'z';
1350 if (proc_is_noreturn) {
1351 fprintf (coerce, "WEB2C_NORETURN ");
1352 proc_is_noreturn = 0;
1354 /* We can't use our P?H macros here, since there might be an arbitrary
1355 number of function arguments. */
1356 fprintf (coerce, "%s %s (", fn_return_type, z_id);
1357 if (ids_paramed == 0) fprintf (coerce, "void");
1358 for (i = 0; i < ids_paramed; i++) {
1359 if (i > 0)
1360 putc (',', coerce);
1361 fprintf (coerce, "%s %s", arg_type[i], symbol (param_id_list[i]));
1363 fprintf (coerce, ");\n");
1366 static void
1367 gen_function_head (void)
1369 int i;
1371 if (strcmp(my_routine, z_id)) {
1372 fprintf(coerce, "#define %s(", my_routine);
1373 for (i=0; i<ids_paramed; i++) {
1374 if (i > 0)
1375 fprintf(coerce, ", %s", symbol(param_id_list[i]));
1376 else
1377 fprintf(coerce, "%s", symbol(param_id_list[i]));
1379 fprintf(coerce, ") %s(", z_id);
1380 for (i=0; i<ids_paramed; i++) {
1381 if (i > 0)
1382 fputs(", ", coerce);
1383 fprintf(coerce, "(%s) ", arg_type[i]);
1384 fprintf(coerce, "%s(%s)",
1385 sym_table[param_id_list[i]].var_formal?"&":"",
1386 symbol(param_id_list[i]));
1388 fprintf(coerce, ")\n");
1390 out = orig_out;
1391 new_line ();
1392 /* We now always use ANSI C prototypes. */
1393 my_output (z_id);
1394 my_output ("(");
1395 if (ids_paramed == 0) my_output ("void");
1396 for (i=0; i<ids_paramed; i++) {
1397 if (i > 0) my_output (",");
1398 my_output (arg_type[i]);
1399 my_output (symbol (param_id_list[i]));
1401 my_output (")");
1402 new_line ();