]> gcc.gnu.org Git - gcc.git/blob - gcc/ch/parse.c
regs.h (HARD_REGNO_CALLER_SAVE_MODE): New macro.
[gcc.git] / gcc / ch / parse.c
1 /* Parser for GNU CHILL (CCITT High-Level Language) -*- C -*-
2 Copyright (C) 1992, 1993 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /*
21 * This is a two-pass parser. In pass 1, we collect declarations,
22 * ignoring actions and most expressions. We store only the
23 * declarations and close, open and re-lex the input file to save
24 * main memory. We anticipate that the compiler will be processing
25 * *very* large single programs which are mechanically generated,
26 * and so we want to store a minimum of information between passes.
27 *
28 * yylex detects the end of the main input file and returns the
29 * END_PASS_1 token. We then re-initialize each CHILL compiler
30 * module's global variables and re-process the input file. The
31 * grant file is output. If the user has requested it, GNU CHILL
32 * exits at this time - its only purpose was to generate the grant
33 * file. Optionally, the compiler may exit if errors were detected
34 * in pass 1.
35 *
36 * As each symbol scope is entered, we install its declarations into
37 * the symbol table. Undeclared types and variables are announced
38 * now.
39 *
40 * Then code is generated.
41 */
42
43 #include "config.h"
44 #include "system.h"
45 #include "tree.h"
46 #include "ch-tree.h"
47 #include "lex.h"
48 #include "actions.h"
49 #include "tasking.h"
50 #include "parse.h"
51 #include "toplev.h"
52
53 /* Since parsers are distinct for each language, put the
54 language string definition here. (fnf) */
55 char *language_string = "GNU CHILL";
56
57 /* Common code to be done before expanding any action. */
58 #define INIT_ACTION { \
59 if (! ignoring) emit_line_note (input_filename, lineno); }
60
61 /* Pop a scope for an ON handler. */
62 #define POP_USED_ON_CONTEXT pop_handler(1)
63
64 /* Pop a scope for an ON handler that wasn't there. */
65 #define POP_UNUSED_ON_CONTEXT pop_handler(0)
66
67 #define PUSH_ACTION push_action()
68
69 /* Cause the `yydebug' variable to be defined. */
70 #define YYDEBUG 1
71
72 extern struct rtx_def* gen_label_rtx PROTO((void));
73 extern void emit_jump PROTO((struct rtx_def *));
74 extern void emit_label PROTO((struct rtx_def *));
75
76 static int parse_action PROTO((void));
77
78 extern int lineno;
79 extern char *input_filename;
80 extern tree generic_signal_type_node;
81 extern tree signal_code;
82 extern int all_static_flag;
83 extern int ignore_case;
84
85 #if 0
86 static int quasi_signal = 0; /* 1 if processing a quasi signal decl */
87 #endif
88
89 int parsing_newmode; /* 0 while parsing SYNMODE;
90 1 while parsing NEWMODE. */
91 int expand_exit_needed = 0;
92
93 /* Gets incremented if we see errors such that we don't want to run pass 2. */
94
95 int serious_errors = 0;
96
97 static tree current_fieldlist;
98
99 /* We don't care about expressions during pass 1, except while we're
100 parsing the RHS of a SYN definition, or while parsing a mode that
101 we need. NOTE: This also causes mode expressions to be ignored. */
102 int ignoring = 1; /* 1 to ignore expressions */
103
104 /* True if we have seen an action not in a (user) function. */
105 int seen_action = 0;
106 int build_constructor = 0;
107
108 /* The action_nesting_level of the current procedure body. */
109 int proc_action_level = 0;
110
111 /* This is the identifier of the label that prefixes the current action,
112 or NULL if there was none. It is cleared at the end of an action,
113 or when starting a nested action list, so get it while you can! */
114 static tree label = NULL_TREE; /* for statement labels */
115
116 #if 0
117 static tree current_block;
118 #endif
119
120 int in_pseudo_module = 0;
121 int pass = 0; /* 0 for init_decl_processing,
122 1 for pass 1, 2 for pass 2 */
123 \f
124 /* re-initialize global variables for pass 2 */
125 static void
126 ch_parse_init ()
127 {
128 expand_exit_needed = 0;
129 label = NULL_TREE; /* for statement labels */
130 current_module = NULL;
131 in_pseudo_module = 0;
132 }
133
134 static void
135 check_end_label (start, end)
136 tree start, end;
137 {
138 if (end != NULL_TREE)
139 {
140 if (start == NULL_TREE && pass == 1)
141 error ("there was no start label to match the end label '%s'",
142 IDENTIFIER_POINTER(end));
143 else if (start != end && pass == 1)
144 error ("start label '%s' does not match end label '%s'",
145 IDENTIFIER_POINTER(start),
146 IDENTIFIER_POINTER(end));
147 }
148 }
149
150
151 /*
152 * given a tree which is an id, a type or a decl,
153 * return the associated type, or issue an error and
154 * return error_mark_node.
155 */
156 tree
157 get_type_of (id_or_decl)
158 tree id_or_decl;
159 {
160 tree type = id_or_decl;
161
162 if (id_or_decl == NULL_TREE
163 || TREE_CODE (id_or_decl) == ERROR_MARK)
164 return error_mark_node;
165
166 if (pass == 1 || ignoring == 1)
167 return id_or_decl;
168
169 if (TREE_CODE (type) == IDENTIFIER_NODE)
170 {
171 type = lookup_name (id_or_decl);
172 if (type == NULL_TREE)
173 {
174 error ("`%s' not declared", IDENTIFIER_POINTER (id_or_decl));
175 type = error_mark_node;
176 }
177 }
178 if (TREE_CODE (type) == TYPE_DECL)
179 type = TREE_TYPE (type);
180 return type; /* was a type all along */
181 }
182
183
184 static void
185 end_function ()
186 {
187 if (CH_DECL_PROCESS (current_function_decl))
188 {
189 /* finishing a process */
190 if (! ignoring)
191 {
192 tree result =
193 build_chill_function_call
194 (lookup_name (get_identifier ("__stop_process")),
195 NULL_TREE);
196 expand_expr_stmt (result);
197 emit_line_note (input_filename, lineno);
198 }
199 }
200 else
201 {
202 /* finishing a procedure.. */
203 if (! ignoring)
204 {
205 if (result_never_set
206 && TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl)))
207 != VOID_TYPE)
208 warning ("No RETURN or RESULT in procedure");
209 chill_expand_return (NULL_TREE, 1);
210 }
211 }
212 finish_chill_function ();
213 pop_chill_function_context ();
214 }
215
216 static tree
217 build_prefix_clause (id)
218 tree id;
219 {
220 if (!id)
221 {
222 if (current_module && current_module->name)
223 { char *module_name = IDENTIFIER_POINTER (current_module->name);
224 if (module_name[0] && module_name[0] != '_')
225 return current_module->name;
226 }
227 error ("PREFIXED clause with no prelix in unlabeled module");
228 }
229 return id;
230 }
231
232 void
233 possibly_define_exit_label (label)
234 tree label;
235 {
236 if (label)
237 define_label (input_filename, lineno, munge_exit_label (label));
238 }
239
240 #define MAX_LOOK_AHEAD 2
241 static enum terminal terminal_buffer[MAX_LOOK_AHEAD+1];
242 YYSTYPE yylval;
243 static YYSTYPE val_buffer[MAX_LOOK_AHEAD+1];
244
245 /*enum terminal current_token, lookahead_token;*/
246
247 #define TOKEN_NOT_READ dummy_last_terminal
248
249 #ifdef __GNUC__
250 __inline__
251 #endif
252 static enum terminal
253 PEEK_TOKEN()
254 {
255 if (terminal_buffer[0] == TOKEN_NOT_READ)
256 {
257 terminal_buffer[0] = yylex();
258 val_buffer[0] = yylval;
259 }
260 return terminal_buffer[0];
261 }
262 #define PEEK_TREE() val_buffer[0].ttype
263 #define PEEK_TOKEN1() peek_token_(1)
264 #define PEEK_TOKEN2() peek_token_(2)
265 static int
266 peek_token_ (i)
267 int i;
268 {
269 if (i > MAX_LOOK_AHEAD)
270 fatal ("internal error - too much lookahead");
271 if (terminal_buffer[i] == TOKEN_NOT_READ)
272 {
273 terminal_buffer[i] = yylex();
274 val_buffer[i] = yylval;
275 }
276 return terminal_buffer[i];
277 }
278
279 static void
280 pushback_token (code, node)
281 int code;
282 tree node;
283 {
284 int i;
285 if (terminal_buffer[MAX_LOOK_AHEAD] != TOKEN_NOT_READ)
286 fatal ("internal error - cannot pushback token");
287 for (i = MAX_LOOK_AHEAD; i > 0; i--)
288 {
289 terminal_buffer[i] = terminal_buffer[i - 1];
290 val_buffer[i] = val_buffer[i - 1];
291 }
292 terminal_buffer[0] = code;
293 val_buffer[0].ttype = node;
294 }
295
296 static void
297 forward_token_()
298 {
299 int i;
300 for (i = 0; i < MAX_LOOK_AHEAD; i++)
301 {
302 terminal_buffer[i] = terminal_buffer[i+1];
303 val_buffer[i] = val_buffer[i+1];
304 }
305 terminal_buffer[MAX_LOOK_AHEAD] = TOKEN_NOT_READ;
306 }
307 #define FORWARD_TOKEN() forward_token_()
308
309 /* Skip the next token.
310 if it isn't TOKEN, the parser is broken. */
311
312 void
313 require(token)
314 enum terminal token;
315 {
316 if (PEEK_TOKEN() != token)
317 {
318 char buf[80];
319 sprintf (buf, "internal parser error - expected token %d", (int)token);
320 fatal(buf);
321 }
322 FORWARD_TOKEN();
323 }
324
325 int
326 check_token (token)
327 enum terminal token;
328 {
329 if (PEEK_TOKEN() != token)
330 return 0;
331 FORWARD_TOKEN ();
332 return 1;
333 }
334
335 /* return 0 if expected token was not found,
336 else return 1.
337 */
338 int
339 expect(token, message)
340 enum terminal token;
341 char *message;
342 {
343 if (PEEK_TOKEN() != token)
344 {
345 if (pass == 1)
346 error(message ? message : "syntax error");
347 return 0;
348 }
349 else
350 FORWARD_TOKEN();
351 return 1;
352 }
353
354 /* define a SYNONYM __PROCNAME__ (__procname__) which holds
355 the name of the current procedure.
356 This should be quit the same as __FUNCTION__ in C */
357 static void
358 define__PROCNAME__ ()
359 {
360 char *fname;
361 tree string;
362 tree procname;
363
364 if (current_function_decl == NULL_TREE)
365 fname = "toplevel";
366 else
367 fname = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
368
369 string = build_chill_string (strlen (fname), fname);
370 procname = get_identifier (ignore_case ? "__procname__" : "__PROCNAME__");
371 push_syndecl (procname, NULL_TREE, string);
372 }
373
374 /* Forward declarations. */
375 static tree parse_expression ();
376 static tree parse_primval ();
377 static tree parse_mode PROTO((void));
378 static tree parse_opt_mode PROTO((void));
379 static tree parse_untyped_expr ();
380 static tree parse_opt_untyped_expr ();
381 static int parse_definition PROTO((int));
382 static void parse_opt_actions ();
383 static void parse_body PROTO((void));
384 static tree parse_if_expression_body PROTO((void));
385 static tree parse_opt_handler PROTO((void));
386
387 static tree
388 parse_opt_name_string (allow_all)
389 int allow_all; /* 1 if ALL is allowed as a postfix */
390 {
391 enum terminal token = PEEK_TOKEN();
392 tree name;
393 if (token != NAME)
394 {
395 if (token == ALL && allow_all)
396 {
397 FORWARD_TOKEN ();
398 return ALL_POSTFIX;
399 }
400 return NULL_TREE;
401 }
402 name = PEEK_TREE();
403 for (;;)
404 {
405 FORWARD_TOKEN ();
406 token = PEEK_TOKEN();
407 if (token != '!')
408 return name;
409 FORWARD_TOKEN();
410 token = PEEK_TOKEN();
411 if (token == ALL && allow_all)
412 return get_identifier3(IDENTIFIER_POINTER (name), "!", "*");
413 if (token != NAME)
414 {
415 if (pass == 1)
416 error ("'%s!' is not followed by an identifier",
417 IDENTIFIER_POINTER (name));
418 return name;
419 }
420 name = get_identifier3(IDENTIFIER_POINTER(name),
421 "!", IDENTIFIER_POINTER(PEEK_TREE()));
422 }
423 }
424
425 static tree
426 parse_simple_name_string ()
427 {
428 enum terminal token = PEEK_TOKEN();
429 tree name;
430 if (token != NAME)
431 {
432 error ("expected a name here");
433 return error_mark_node;
434 }
435 name = PEEK_TREE ();
436 FORWARD_TOKEN ();
437 return name;
438 }
439
440 static tree
441 parse_name_string ()
442 {
443 tree name = parse_opt_name_string (0);
444 if (name)
445 return name;
446 if (pass == 1)
447 error ("expected a name string here");
448 return error_mark_node;
449 }
450
451 static tree
452 parse_defining_occurrence ()
453 {
454 if (PEEK_TOKEN () == NAME)
455 {
456 tree id = PEEK_TREE();
457 FORWARD_TOKEN ();
458 return id;
459 }
460 return NULL;
461 }
462
463 /* Matches: <name_string>
464 Returns if pass 1: the identifier.
465 Returns if pass 2: a decl or value for identifier. */
466
467 static tree
468 parse_name ()
469 {
470 tree name = parse_name_string ();
471 if (pass == 1 || ignoring)
472 return name;
473 else
474 {
475 tree decl = lookup_name (name);
476 if (decl == NULL_TREE)
477 {
478 error ("`%s' undeclared", IDENTIFIER_POINTER (name));
479 return error_mark_node;
480 }
481 else if (TREE_CODE (TREE_TYPE (decl)) == ERROR_MARK)
482 return error_mark_node;
483 else if (TREE_CODE (decl) == CONST_DECL)
484 return DECL_INITIAL (decl);
485 else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
486 return convert_from_reference (decl);
487 else
488 return decl;
489 }
490 }
491
492 static tree
493 parse_optlabel()
494 {
495 tree label = parse_defining_occurrence();
496 if (label != NULL)
497 expect(COLON, "expected a ':' here");
498 return label;
499 }
500
501 static void
502 parse_semi_colon ()
503 {
504 enum terminal token = PEEK_TOKEN ();
505 if (token == SC)
506 FORWARD_TOKEN ();
507 else if (pass == 1)
508 (token == END ? pedwarn : error) ("expected ';' here");
509 label = NULL_TREE;
510 }
511
512 static void
513 parse_opt_end_label_semi_colon (start_label)
514 tree start_label;
515 {
516 if (PEEK_TOKEN() == NAME)
517 {
518 tree end_label = parse_name_string ();
519 check_end_label (start_label, end_label);
520 }
521 parse_semi_colon ();
522 }
523
524 static void
525 parse_modulion (label)
526 tree label;
527 {
528 tree module_name;
529
530 label = set_module_name (label);
531 module_name = push_module (label, 0);
532 FORWARD_TOKEN();
533
534 push_action ();
535 parse_body();
536 expect(END, "expected END here");
537 parse_opt_handler ();
538 parse_opt_end_label_semi_colon (label);
539 find_granted_decls ();
540 pop_module ();
541 }
542
543 static void
544 parse_spec_module (label)
545 tree label;
546 {
547 tree module_name = push_module (set_module_name (label), 1);
548 int save_ignoring = ignoring;
549 ignoring = pass == 2;
550 FORWARD_TOKEN(); /* SKIP SPEC */
551 expect (MODULE, "expected 'MODULE' here");
552
553 while (parse_definition (1)) { }
554 if (parse_action ())
555 error ("action not allowed in SPEC MODULE");
556 expect(END, "expected END here");
557 parse_opt_end_label_semi_colon (label);
558 find_granted_decls ();
559 pop_module ();
560 ignoring = save_ignoring;
561 }
562
563 /* Matches: <name_string> ( "," <name_string> )*
564 Returns either a single IDENTIFIER_NODE,
565 or a chain (TREE_LIST) of IDENTIFIER_NODES.
566 (Since a single identifier is the common case, we avoid wasting space
567 (twice, once for each pass) with extra TREE_LIST nodes in that case.)
568 (Will not return NULL_TREE even if ignoring is true.) */
569
570 static tree
571 parse_defining_occurrence_list ()
572 {
573 tree chain = NULL_TREE;
574 tree name = parse_defining_occurrence ();
575 if (name == NULL_TREE)
576 {
577 error("missing defining occurrence");
578 return NULL_TREE;
579 }
580 if (! check_token (COMMA))
581 return name;
582 chain = build_tree_list (NULL_TREE, name);
583 for (;;)
584 {
585 name = parse_defining_occurrence ();
586 if (name == NULL)
587 {
588 error ("bad defining occurrence following ','");
589 break;
590 }
591 chain = tree_cons (NULL_TREE, name, chain);
592 if (! check_token (COMMA))
593 break;
594 }
595 return nreverse (chain);
596 }
597
598 static void
599 parse_mode_definition (is_newmode)
600 int is_newmode;
601 {
602 tree mode, names;
603 int save_ignoring = ignoring;
604 ignoring = pass == 2;
605 names = parse_defining_occurrence_list ();
606 expect (EQL, "missing '=' in mode definition");
607 mode = parse_mode ();
608 if (names == NULL_TREE || TREE_CODE (names) == TREE_LIST)
609 {
610 for ( ; names != NULL_TREE; names = TREE_CHAIN (names))
611 push_modedef (names, mode, is_newmode);
612 }
613 else
614 push_modedef (names, mode, is_newmode);
615 ignoring = save_ignoring;
616 }
617
618 void
619 parse_mode_definition_statement (is_newmode)
620 int is_newmode;
621 {
622 FORWARD_TOKEN (); /* skip SYNMODE or NEWMODE */
623 parse_mode_definition (is_newmode);
624 while (PEEK_TOKEN () == COMMA)
625 {
626 FORWARD_TOKEN ();
627 parse_mode_definition (is_newmode);
628 }
629 parse_semi_colon ();
630 }
631
632 static void
633 parse_synonym_definition ()
634 { tree expr = NULL_TREE;
635 tree names = parse_defining_occurrence_list ();
636 tree mode = parse_opt_mode ();
637 if (! expect (EQL, "missing '=' in synonym definition"))
638 mode = error_mark_node;
639 else
640 {
641 if (mode)
642 expr = parse_untyped_expr ();
643 else
644 expr = parse_expression ();
645 }
646 if (names == NULL_TREE || TREE_CODE (names) == TREE_LIST)
647 {
648 for ( ; names != NULL_TREE; names = TREE_CHAIN (names))
649 push_syndecl (names, mode, expr);
650 }
651 else
652 push_syndecl (names, mode, expr);
653 }
654
655 static void
656 parse_synonym_definition_statement()
657 {
658 int save_ignoring= ignoring;
659 ignoring = pass == 2;
660 require (SYN);
661 parse_synonym_definition ();
662 while (PEEK_TOKEN () == COMMA)
663 {
664 FORWARD_TOKEN ();
665 parse_synonym_definition ();
666 }
667 ignoring = save_ignoring;
668 parse_semi_colon ();
669 }
670
671 /* Attempts to match: "(" <exception list> ")" ":".
672 Return NULL_TREE on failure, and non-NULL on success.
673 On success, if pass 1, return a TREE_LIST of IDENTIFIER_NODEs. */
674
675 static tree
676 parse_on_exception_list ()
677 {
678 tree name;
679 tree list = NULL_TREE;
680 int tok1 = PEEK_TOKEN ();
681 int tok2 = PEEK_TOKEN1 ();
682
683 /* This requires a lot of look-ahead, because we cannot
684 easily a priori distinguish an exception-list from an expression. */
685 if (tok1 != LPRN || tok2 != NAME)
686 {
687 if (tok1 == NAME && tok2 == COLON && pass == 1)
688 error ("missing '(' in exception list");
689 return 0;
690 }
691 require (LPRN);
692 name = parse_name_string ();
693 if (PEEK_TOKEN () == RPRN && PEEK_TOKEN1 () == COLON)
694 {
695 /* Matched: '(' <name_string> ')' ':' */
696 FORWARD_TOKEN (); FORWARD_TOKEN ();
697 return pass == 1 ? build_tree_list (NULL_TREE, name) : name;
698 }
699 if (PEEK_TOKEN() == COMMA)
700 {
701 if (pass == 1)
702 list = build_tree_list (NULL_TREE, name);
703 while (check_token (COMMA))
704 {
705 tree old_names = list;
706 name = parse_name_string ();
707 if (pass == 1)
708 {
709 for ( ; old_names != NULL_TREE; old_names = TREE_CHAIN (old_names))
710 {
711 if (TREE_VALUE (old_names) == name)
712 {
713 error ("ON exception names must be unique");
714 goto continue_parsing;
715 }
716 }
717 list = tree_cons (NULL_TREE, name, list);
718 continue_parsing:
719 ;
720 }
721 }
722 if (! check_token (RPRN) || ! check_token(COLON))
723 error ("syntax error in exception list");
724 return pass == 1 ? nreverse (list) : name;
725 }
726 /* Matched: '(' name_string
727 but it doesn't match the syntax of an exception list.
728 It could be the beginning of an expression, so back up. */
729 pushback_token (NAME, name);
730 pushback_token (LPRN, 0);
731 return NULL_TREE;
732 }
733
734 static void
735 parse_on_alternatives ()
736 {
737 for (;;)
738 {
739 tree except_list = parse_on_exception_list ();
740 if (except_list != NULL)
741 chill_handle_on_labels (except_list);
742 else if (parse_action ())
743 expand_exit_needed = 1;
744 else
745 break;
746 }
747 }
748
749 static tree
750 parse_opt_handler ()
751 {
752 if (! check_token (ON))
753 {
754 POP_UNUSED_ON_CONTEXT;
755 return NULL_TREE;
756 }
757 if (check_token (END))
758 {
759 pedwarn ("empty ON-condition");
760 POP_UNUSED_ON_CONTEXT;
761 return NULL_TREE;
762 }
763 if (! ignoring)
764 {
765 chill_start_on ();
766 expand_exit_needed = 0;
767 }
768 if (PEEK_TOKEN () != ELSE)
769 {
770 parse_on_alternatives ();
771 if (! ignoring && expand_exit_needed)
772 expand_exit_something ();
773 }
774 if (check_token (ELSE))
775 {
776 chill_start_default_handler ();
777 label = NULL_TREE;
778 parse_opt_actions ();
779 if (! ignoring)
780 {
781 emit_line_note (input_filename, lineno);
782 expand_exit_something ();
783 }
784 }
785 expect (END, "missing 'END' after");
786 if (! ignoring)
787 chill_finish_on ();
788 POP_USED_ON_CONTEXT;
789 return integer_zero_node;
790 }
791
792 static void
793 parse_loc_declaration (in_spec_module)
794 int in_spec_module;
795 {
796 tree names = parse_defining_occurrence_list ();
797 int save_ignoring = ignoring;
798 int is_static, lifetime_bound;
799 tree mode, init_value = NULL_TREE;
800 int loc_decl = 0;
801
802 ignoring = pass == 2;
803 mode = parse_mode ();
804 ignoring = save_ignoring;
805 is_static = check_token (STATIC);
806 if (check_token (BASED))
807 {
808 expect(LPRN, "BASED must be followed by (NAME)");
809 do_based_decls (names, mode, parse_name_string ());
810 expect(RPRN, "BASED must be followed by (NAME)");
811 return;
812 }
813 if (check_token (LOC))
814 {
815 /* loc-identity declaration */
816 if (pass == 1)
817 mode = build_chill_reference_type (mode);
818 loc_decl = 1;
819 }
820 lifetime_bound = check_token (INIT);
821 if (lifetime_bound && loc_decl)
822 {
823 if (pass == 1)
824 error ("INIT not allowed at loc-identity declaration");
825 lifetime_bound = 0;
826 }
827 if (PEEK_TOKEN () == ASGN || PEEK_TOKEN() == EQL)
828 {
829 save_ignoring = ignoring;
830 ignoring = pass == 1;
831 if (PEEK_TOKEN() == EQL)
832 {
833 if (pass == 1)
834 error ("'=' used where ':=' is required");
835 }
836 FORWARD_TOKEN();
837 if (! lifetime_bound)
838 push_handler ();
839 init_value = parse_untyped_expr ();
840 if (in_spec_module)
841 {
842 error ("initialization is not allowed in spec module");
843 init_value = NULL_TREE;
844 }
845 if (! lifetime_bound)
846 parse_opt_handler ();
847 ignoring = save_ignoring;
848 }
849 if (init_value == NULL_TREE && loc_decl && pass == 1)
850 error ("loc-identity declaration without initialisation");
851 do_decls (names, mode,
852 is_static || global_bindings_p ()
853 /* the variable becomes STATIC if all_static_flag is set and
854 current functions doesn't have the RECURSIVE attribute */
855 || (all_static_flag && !CH_DECL_RECURSIVE (current_function_decl)),
856 lifetime_bound, init_value, in_spec_module);
857
858 /* Free any temporaries we made while initializing the decl. */
859 free_temp_slots ();
860 }
861
862 static void
863 parse_declaration_statement (in_spec_module)
864 int in_spec_module;
865 {
866 int save_ignoring = ignoring;
867 ignoring = pass == 2;
868 require (DCL);
869 parse_loc_declaration (in_spec_module);
870 while (PEEK_TOKEN () == COMMA)
871 {
872 FORWARD_TOKEN ();
873 parse_loc_declaration (in_spec_module);
874 }
875 ignoring = save_ignoring;
876 parse_semi_colon ();
877 }
878
879 tree
880 parse_optforbid ()
881 {
882 if (check_token (FORBID) == 0)
883 return NULL_TREE;
884 if (check_token (ALL))
885 return ignoring ? NULL_TREE : build_int_2 (-1, -1);
886 #if 0
887 if (check_token (LPRN))
888 {
889 tree list = parse_forbidlist ();
890 expect (RPRN, "missing ')' after FORBID list");
891 return list;
892 }
893 #endif
894 error ("bad syntax following FORBID");
895 return NULL_TREE;
896 }
897
898 /* Matches: <grant postfix> or <seize postfix>
899 Returns: A (singleton) TREE_LIST. */
900
901 tree
902 parse_postfix (grant_or_seize)
903 enum terminal grant_or_seize;
904 {
905 tree name = parse_opt_name_string (1);
906 tree forbid = NULL_TREE;
907 if (name == NULL_TREE)
908 {
909 error ("expected a postfix name here");
910 name = error_mark_node;
911 }
912 if (grant_or_seize == GRANT)
913 forbid = parse_optforbid ();
914 return build_tree_list (forbid, name);
915 }
916
917 tree
918 parse_postfix_list (grant_or_seize)
919 enum terminal grant_or_seize;
920 {
921 tree list = parse_postfix (grant_or_seize);
922 while (check_token (COMMA))
923 list = chainon (list, parse_postfix (grant_or_seize));
924 return list;
925 }
926
927 void
928 parse_rename_clauses (grant_or_seize)
929 enum terminal grant_or_seize;
930 {
931 for (;;)
932 {
933 tree rename_old_prefix, rename_new_prefix, postfix;
934 require (LPRN);
935 rename_old_prefix = parse_opt_name_string (0);
936 expect (ARROW, "missing '->' in rename clause");
937 rename_new_prefix = parse_opt_name_string (0);
938 expect (RPRN, "missing ')' in rename clause");
939 expect ('!', "missing '!' in rename clause");
940 postfix = parse_postfix (grant_or_seize);
941
942 if (grant_or_seize == GRANT)
943 chill_grant (rename_old_prefix, rename_new_prefix,
944 TREE_VALUE (postfix), TREE_PURPOSE (postfix));
945 else
946 chill_seize (rename_old_prefix, rename_new_prefix,
947 TREE_VALUE (postfix));
948
949 if (PEEK_TOKEN () != COMMA)
950 break;
951 FORWARD_TOKEN ();
952 if (PEEK_TOKEN () != LPRN)
953 {
954 error ("expected another rename clause");
955 break;
956 }
957 }
958 }
959
960 static tree
961 parse_opt_prefix_clause ()
962 {
963 if (check_token (PREFIXED) == 0)
964 return NULL_TREE;
965 return build_prefix_clause (parse_opt_name_string (0));
966 }
967
968 void
969 parse_grant_statement ()
970 {
971 require (GRANT);
972 if (PEEK_TOKEN () == LPRN)
973 parse_rename_clauses (GRANT);
974 else
975 {
976 tree window = parse_postfix_list (GRANT);
977 tree new_prefix = parse_opt_prefix_clause ();
978 tree t;
979 for (t = window; t; t = TREE_CHAIN (t))
980 chill_grant (NULL_TREE, new_prefix, TREE_VALUE (t), TREE_PURPOSE (t));
981 }
982 }
983
984 void
985 parse_seize_statement ()
986 {
987 require (SEIZE);
988 if (PEEK_TOKEN () == LPRN)
989 parse_rename_clauses (SEIZE);
990 else
991 {
992 tree seize_window = parse_postfix_list (SEIZE);
993 tree old_prefix = parse_opt_prefix_clause ();
994 tree t;
995 for (t = seize_window; t; t = TREE_CHAIN (t))
996 chill_seize (old_prefix, NULL_TREE, TREE_VALUE (t));
997 }
998 }
999
1000 /* In pass 1, this returns a TREE_LIST, one node for each parameter.
1001 In pass 2, we get a list of PARM_DECLs chained together.
1002 In either case, the list is in reverse order. */
1003
1004 static tree
1005 parse_param_name_list ()
1006 {
1007 tree list = NULL_TREE;
1008 do
1009 {
1010 tree new_link;
1011 tree name = parse_defining_occurrence ();
1012 if (name == NULL_TREE)
1013 {
1014 error ("syntax error in parameter name list");
1015 return list;
1016 }
1017 if (pass == 1)
1018 new_link = build_tree_list (NULL_TREE, name);
1019 /* else if (current_module->is_spec_module) ; nothing */
1020 else /* pass == 2 */
1021 {
1022 new_link = make_node (PARM_DECL);
1023 DECL_NAME (new_link) = name;
1024 DECL_ASSEMBLER_NAME (new_link) = name;
1025 }
1026
1027 TREE_CHAIN (new_link) = list;
1028 list = new_link;
1029 } while (check_token (COMMA));
1030 return list;
1031 }
1032
1033 static tree
1034 parse_param_attr ()
1035 {
1036 tree attr;
1037 switch (PEEK_TOKEN ())
1038 {
1039 case PARAMATTR: /* INOUT is returned here */
1040 attr = PEEK_TREE ();
1041 FORWARD_TOKEN ();
1042 return attr;
1043 case IN:
1044 FORWARD_TOKEN ();
1045 return ridpointers[(int) RID_IN];
1046 case LOC:
1047 FORWARD_TOKEN ();
1048 return ridpointers[(int) RID_LOC];
1049 #if 0
1050 case DYNAMIC:
1051 FORWARD_TOKEN ();
1052 return ridpointers[(int) RID_DYNAMIC];
1053 #endif
1054 default:
1055 return NULL_TREE;
1056 }
1057 }
1058
1059 /* We wrap CHILL array parameters in a STRUCT. The original parameter
1060 name is unpacked from the struct at get_identifier time */
1061
1062 /* In pass 1, returns list of types; in pass 2: chain of PARM_DECLs. */
1063
1064 static tree
1065 parse_formpar ()
1066 {
1067 tree names = parse_param_name_list ();
1068 tree mode = parse_mode ();
1069 tree paramattr = parse_param_attr ();
1070 return chill_munge_params (nreverse (names), mode, paramattr);
1071 }
1072
1073 /*
1074 * Note: build_process_header depends upon the *exact*
1075 * representation of STRUCT fields and of formal parameter
1076 * lists. If either is changed, build_process_header will
1077 * also need change. Push_extern_process is affected as well.
1078 */
1079 static tree
1080 parse_formparlist ()
1081 {
1082 tree list = NULL_TREE;
1083 if (PEEK_TOKEN() == RPRN)
1084 return NULL_TREE;
1085 for (;;)
1086 {
1087 list = chainon (list, parse_formpar ());
1088 if (! check_token (COMMA))
1089 break;
1090 }
1091 return list;
1092 }
1093
1094 static tree
1095 parse_opt_result_spec ()
1096 {
1097 tree mode;
1098 int is_nonref, is_loc, is_dynamic;
1099 if (!check_token (RETURNS))
1100 return void_type_node;
1101 expect (LPRN, "expected '(' after RETURNS");
1102 mode = parse_mode ();
1103 is_nonref = check_token (NONREF);
1104 is_loc = check_token (LOC);
1105 is_dynamic = check_token (DYNAMIC);
1106 if (is_nonref && !is_loc)
1107 error ("NONREF specific without LOC in result attribute");
1108 if (is_dynamic && !is_loc)
1109 error ("DYNAMIC specific without LOC in result attribute");
1110 mode = get_type_of (mode);
1111 if (is_loc && ! ignoring)
1112 mode = build_chill_reference_type (mode);
1113 expect (RPRN, "expected ')' after RETURNS");
1114 return mode;
1115 }
1116
1117 static tree
1118 parse_opt_except ()
1119 {
1120 tree list = NULL_TREE;
1121 if (!check_token (EXCEPTIONS))
1122 return NULL_TREE;
1123 expect (LPRN, "expected '(' after EXCEPTIONS");
1124 do
1125 {
1126 tree except_name = parse_name_string ();
1127 tree name;
1128 for (name = list; name != NULL_TREE; name = TREE_CHAIN (name))
1129 if (TREE_VALUE (name) == except_name && pass == 1)
1130 {
1131 error ("exception names must be unique");
1132 break;
1133 }
1134 if (name == NULL_TREE && !ignoring)
1135 list = tree_cons (NULL_TREE, except_name, list);
1136 } while (check_token (COMMA));
1137 expect (RPRN, "expected ')' after EXCEPTIONS");
1138 return list;
1139 }
1140
1141 static tree
1142 parse_opt_recursive ()
1143 {
1144 if (check_token (RECURSIVE))
1145 return ridpointers[RID_RECURSIVE];
1146 else
1147 return NULL_TREE;
1148 }
1149
1150 static tree
1151 parse_procedureattr ()
1152 {
1153 tree generality;
1154 tree optrecursive;
1155 switch (PEEK_TOKEN ())
1156 {
1157 case GENERAL:
1158 FORWARD_TOKEN ();
1159 generality = ridpointers[RID_GENERAL];
1160 break;
1161 case SIMPLE:
1162 FORWARD_TOKEN ();
1163 generality = ridpointers[RID_SIMPLE];
1164 break;
1165 case INLINE:
1166 FORWARD_TOKEN ();
1167 generality = ridpointers[RID_INLINE];
1168 break;
1169 default:
1170 generality = NULL_TREE;
1171 }
1172 optrecursive = parse_opt_recursive ();
1173 if (pass != 1)
1174 return NULL_TREE;
1175 if (generality)
1176 generality = build_tree_list (NULL_TREE, generality);
1177 if (optrecursive)
1178 generality = tree_cons (NULL_TREE, optrecursive, generality);
1179 return generality;
1180 }
1181
1182 /* Parse the body and last part of a procedure or process definition. */
1183
1184 static void
1185 parse_proc_body (name, exceptions)
1186 tree name;
1187 tree exceptions;
1188 {
1189 int save_proc_action_level = proc_action_level;
1190 proc_action_level = action_nesting_level;
1191 if (exceptions != NULL_TREE)
1192 /* set up a handler for reraising exceptions */
1193 push_handler ();
1194 push_action ();
1195 define__PROCNAME__ ();
1196 parse_body ();
1197 proc_action_level = save_proc_action_level;
1198 expect (END, "'END' was expected here");
1199 parse_opt_handler ();
1200 if (exceptions != NULL_TREE)
1201 chill_reraise_exceptions (exceptions);
1202 parse_opt_end_label_semi_colon (name);
1203 end_function ();
1204 }
1205
1206 static void
1207 parse_procedure_definition (in_spec_module)
1208 int in_spec_module;
1209 {
1210 int save_ignoring = ignoring;
1211 tree name = parse_defining_occurrence ();
1212 tree params, result, exceptlist, attributes;
1213 int save_chill_at_module_level = chill_at_module_level;
1214 chill_at_module_level = 0;
1215 if (!in_spec_module)
1216 ignoring = pass == 2;
1217 require (COLON); require (PROC);
1218 expect (LPRN, "missing '(' after PROC");
1219 params = parse_formparlist ();
1220 expect (RPRN, "missing ')' in PROC");
1221 result = parse_opt_result_spec ();
1222 exceptlist = parse_opt_except ();
1223 attributes = parse_procedureattr ();
1224 ignoring = save_ignoring;
1225 if (in_spec_module)
1226 {
1227 expect (END, "missing 'END'");
1228 parse_opt_end_label_semi_colon (name);
1229 push_extern_function (name, result, params, exceptlist, 0);
1230 return;
1231 }
1232 push_chill_function_context ();
1233 start_chill_function (name, result, params, exceptlist, attributes);
1234 current_module->procedure_seen = 1;
1235 parse_proc_body (name, TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
1236 chill_at_module_level = save_chill_at_module_level;
1237 }
1238
1239 static tree
1240 parse_processpar ()
1241 {
1242 tree names = parse_defining_occurrence_list ();
1243 tree mode = parse_mode ();
1244 tree paramattr = parse_param_attr ();
1245
1246 if (names && TREE_CODE (names) == IDENTIFIER_NODE)
1247 names = build_tree_list (NULL_TREE, names);
1248 return tree_cons (tree_cons (paramattr, mode, NULL_TREE), names, NULL_TREE);
1249 }
1250
1251 static tree
1252 parse_processparlist ()
1253 {
1254 tree list = NULL_TREE;
1255 if (PEEK_TOKEN() == RPRN)
1256 return NULL_TREE;
1257 for (;;)
1258 {
1259 list = chainon (list, parse_processpar ());
1260 if (! check_token (COMMA))
1261 break;
1262 }
1263 return list;
1264 }
1265
1266 static void
1267 parse_process_definition (in_spec_module)
1268 int in_spec_module;
1269 {
1270 int save_ignoring = ignoring;
1271 tree name = parse_defining_occurrence ();
1272 tree params;
1273 tree tmp;
1274 if (!in_spec_module)
1275 ignoring = 0;
1276 require (COLON); require (PROCESS);
1277 expect (LPRN, "missing '(' after PROCESS");
1278 params = parse_processparlist (in_spec_module);
1279 expect (RPRN, "missing ')' in PROCESS");
1280 ignoring = save_ignoring;
1281 if (in_spec_module)
1282 {
1283 expect (END, "missing 'END'");
1284 parse_opt_end_label_semi_colon (name);
1285 push_extern_process (name, params, NULL_TREE, 0);
1286 return;
1287 }
1288 tmp = build_process_header (name, params);
1289 parse_proc_body (name, NULL_TREE);
1290 build_process_wrapper (name, tmp);
1291 }
1292
1293 static void
1294 parse_signal_definition ()
1295 {
1296 tree signame = parse_defining_occurrence ();
1297 tree modes = NULL_TREE;
1298 tree dest = NULL_TREE;
1299
1300 if (check_token (EQL))
1301 {
1302 expect (LPRN, "missing '(' after 'SIGNAL <name> ='");
1303 for (;;)
1304 {
1305 tree mode = parse_mode ();
1306 modes = tree_cons (NULL_TREE, mode, modes);
1307 if (! check_token (COMMA))
1308 break;
1309 }
1310 expect (RPRN, "missing ')'");
1311 modes = nreverse (modes);
1312 }
1313
1314 if (check_token (TO))
1315 {
1316 tree decl;
1317 int save_ignoring = ignoring;
1318 ignoring = 0;
1319 decl = parse_name ();
1320 ignoring = save_ignoring;
1321 if (pass > 1)
1322 {
1323 if (decl == NULL_TREE
1324 || TREE_CODE (decl) == ERROR_MARK
1325 || TREE_CODE (decl) != FUNCTION_DECL
1326 || !CH_DECL_PROCESS (decl))
1327 error ("must specify a PROCESS name");
1328 else
1329 dest = decl;
1330 }
1331 }
1332
1333 if (! global_bindings_p ())
1334 error ("SIGNAL must be in global reach");
1335 else
1336 {
1337 tree struc = build_signal_struct_type (signame, modes, dest);
1338 tree decl =
1339 generate_tasking_code_variable (signame,
1340 &signal_code,
1341 current_module->is_spec_module);
1342 /* remember the code variable in the struct type */
1343 DECL_TASKING_CODE_DECL (struc) = (struct lang_decl *)decl;
1344 CH_DECL_SIGNAL (struc) = 1;
1345 add_taskstuff_to_list (decl, "_TT_Signal",
1346 current_module->is_spec_module ?
1347 NULL_TREE : signal_code, struc, NULL_TREE);
1348 }
1349
1350 }
1351
1352 static void
1353 parse_signal_definition_statement ()
1354 {
1355 int save_ignoring = ignoring;
1356 ignoring = pass == 2;
1357 require (SIGNAL);
1358 for (;;)
1359 {
1360 parse_signal_definition ();
1361 if (! check_token (COMMA))
1362 break;
1363 if (PEEK_TOKEN () == SC)
1364 {
1365 error ("syntax error while parsing signal definition statement");
1366 break;
1367 }
1368 }
1369 parse_semi_colon ();
1370 ignoring = save_ignoring;
1371 }
1372
1373 static int
1374 parse_definition (in_spec_module)
1375 int in_spec_module;
1376 {
1377 switch (PEEK_TOKEN ())
1378 {
1379 case NAME:
1380 if (PEEK_TOKEN1() == COLON)
1381 {
1382 if (PEEK_TOKEN2() == PROC)
1383 {
1384 parse_procedure_definition (in_spec_module);
1385 return 1;
1386 }
1387 else if (PEEK_TOKEN2() == PROCESS)
1388 {
1389 parse_process_definition (in_spec_module);
1390 return 1;
1391 }
1392 }
1393 return 0;
1394 case DCL:
1395 parse_declaration_statement(in_spec_module);
1396 break;
1397 case GRANT:
1398 parse_grant_statement ();
1399 break;
1400 case NEWMODE:
1401 parse_mode_definition_statement(1);
1402 break;
1403 case SC:
1404 label = NULL_TREE;
1405 FORWARD_TOKEN();
1406 return 1;
1407 case SEIZE:
1408 parse_seize_statement ();
1409 break;
1410 case SIGNAL:
1411 parse_signal_definition_statement ();
1412 break;
1413 case SYN:
1414 parse_synonym_definition_statement();
1415 break;
1416 case SYNMODE:
1417 parse_mode_definition_statement(0);
1418 break;
1419 default:
1420 return 0;
1421 }
1422 return 1;
1423 }
1424
1425 static void
1426 parse_then_clause ()
1427 {
1428 expect (THEN, "expected 'THEN' after 'IF'");
1429 if (! ignoring)
1430 emit_line_note (input_filename, lineno);
1431 parse_opt_actions ();
1432 }
1433
1434 static void
1435 parse_opt_else_clause ()
1436 {
1437 while (check_token (ELSIF))
1438 {
1439 tree cond = parse_expression ();
1440 if (! ignoring)
1441 expand_start_elseif (truthvalue_conversion (cond));
1442 parse_then_clause ();
1443 }
1444 if (check_token (ELSE))
1445 {
1446 if (! ignoring)
1447 { emit_line_note (input_filename, lineno);
1448 expand_start_else ();
1449 }
1450 parse_opt_actions ();
1451 }
1452 }
1453
1454 static tree parse_expr_list ()
1455 {
1456 tree expr = parse_expression ();
1457 tree list = ignoring ? NULL_TREE : build_tree_list (NULL_TREE, expr);
1458 while (check_token (COMMA))
1459 {
1460 expr = parse_expression ();
1461 if (! ignoring)
1462 list = tree_cons (NULL_TREE, expr, list);
1463 }
1464 return list;
1465 }
1466
1467 static tree
1468 parse_range_list_clause ()
1469 {
1470 tree name = parse_opt_name_string (0);
1471 if (name == NULL_TREE)
1472 return NULL_TREE;
1473 while (check_token (COMMA))
1474 {
1475 name = parse_name_string (0);
1476 }
1477 if (check_token (SC))
1478 {
1479 sorry ("case range list");
1480 return error_mark_node;
1481 }
1482 pushback_token (NAME, name);
1483 return NULL_TREE;
1484 }
1485
1486 static void
1487 pushback_paren_expr (expr)
1488 tree expr;
1489 {
1490 if (pass == 1 && !ignoring)
1491 expr = build1 (PAREN_EXPR, NULL_TREE, expr);
1492 pushback_token (EXPR, expr);
1493 }
1494
1495 /* Matches: <case label> */
1496
1497 static tree
1498 parse_case_label ()
1499 {
1500 tree expr;
1501 if (check_token (ELSE))
1502 return case_else_node;
1503 /* Does this also handle the case of a mode name? FIXME */
1504 expr = parse_expression ();
1505 if (check_token (COLON))
1506 {
1507 tree max_expr = parse_expression ();
1508 if (! ignoring)
1509 expr = build (RANGE_EXPR, NULL_TREE, expr, max_expr);
1510 }
1511 return expr;
1512 }
1513
1514 /* Parses: <case_label_list>
1515 Fails if not followed by COMMA or COLON.
1516 If it fails, it backs up if needed, and returns NULL_TREE.
1517 IN_TUPLE is true if we are parsing a tuple element,
1518 and 0 if we are parsing a case label specification. */
1519
1520 static tree
1521 parse_case_label_list (selector, in_tuple)
1522 tree selector;
1523 int in_tuple;
1524 {
1525 tree expr, list;
1526 if (! check_token (LPRN))
1527 return NULL_TREE;
1528 if (check_token (MUL))
1529 {
1530 expect (RPRN, "missing ')' after '*' case label list");
1531 if (ignoring)
1532 return integer_zero_node;
1533 expr = build (RANGE_EXPR, NULL_TREE, NULL_TREE, NULL_TREE);
1534 expr = build_tree_list (NULL_TREE, expr);
1535 return expr;
1536 }
1537 expr = parse_case_label ();
1538 if (check_token (RPRN))
1539 {
1540 if ((in_tuple || PEEK_TOKEN () != COMMA) && PEEK_TOKEN () != COLON)
1541 {
1542 /* Ooops! It looks like it was the start of an action or
1543 unlabelled tuple element, and not a case label, so back up. */
1544 if (expr != NULL_TREE && TREE_CODE (expr) == RANGE_EXPR)
1545 {
1546 error ("misplaced colon in case label");
1547 expr = error_mark_node;
1548 }
1549 pushback_paren_expr (expr);
1550 return NULL_TREE;
1551 }
1552 list = build_tree_list (NULL_TREE, expr);
1553 if (expr == case_else_node && selector != NULL_TREE)
1554 ELSE_LABEL_SPECIFIED (selector) = 1;
1555 return list;
1556 }
1557 list = build_tree_list (NULL_TREE, expr);
1558 if (expr == case_else_node && selector != NULL_TREE)
1559 ELSE_LABEL_SPECIFIED (selector) = 1;
1560
1561 while (check_token (COMMA))
1562 {
1563 expr = parse_case_label ();
1564 list = tree_cons (NULL_TREE, expr, list);
1565 if (expr == case_else_node && selector != NULL_TREE)
1566 ELSE_LABEL_SPECIFIED (selector) = 1;
1567 }
1568 expect (RPRN, "missing ')' at end of case label list");
1569 return nreverse (list);
1570 }
1571
1572 /* Parses: <case_label_specification>
1573 Must be followed by a COLON.
1574 If it fails, it backs up if needed, and returns NULL_TREE. */
1575
1576 static tree
1577 parse_case_label_specification (selectors)
1578 tree selectors;
1579 {
1580 tree list_list = NULL_TREE;
1581 tree list;
1582 list = parse_case_label_list (selectors, 0);
1583 if (list == NULL_TREE)
1584 return NULL_TREE;
1585 list_list = build_tree_list (NULL_TREE, list);
1586 while (check_token (COMMA))
1587 {
1588 if (selectors != NULL_TREE)
1589 selectors = TREE_CHAIN (selectors);
1590 list = parse_case_label_list (selectors, 0);
1591 if (list == NULL_TREE)
1592 {
1593 error ("unrecognized case label list after ','");
1594 return list_list;
1595 }
1596 list_list = tree_cons (NULL_TREE, list, list_list);
1597 }
1598 return nreverse (list_list);
1599 }
1600
1601 static void
1602 parse_single_dimension_case_action (selector)
1603 tree selector;
1604 {
1605 int no_completeness_check = 0;
1606
1607 /* The case label/action toggle. It is 0 initially, and when an action
1608 was last seen. It is 1 integer_zero_node when a label was last seen. */
1609 int caseaction_flag = 0;
1610
1611 if (! ignoring)
1612 {
1613 expand_exit_needed = 0;
1614 selector = check_case_selector (selector);
1615 expand_start_case (1, selector, TREE_TYPE (selector), "CASE statement");
1616 push_momentary ();
1617 }
1618
1619 for (;;)
1620 {
1621 tree label_spec = parse_case_label_specification (selector);
1622 if (label_spec != NULL_TREE)
1623 {
1624 expect (COLON, "missing ':' in case alternative");
1625 if (! ignoring)
1626 {
1627 no_completeness_check |= chill_handle_single_dimension_case_label (
1628 selector, label_spec, &expand_exit_needed, &caseaction_flag);
1629 }
1630 }
1631 else if (parse_action ())
1632 {
1633 expand_exit_needed = 1;
1634 caseaction_flag = 0;
1635 }
1636 else
1637 break;
1638 }
1639
1640 if (! ignoring)
1641 {
1642 if (expand_exit_needed || caseaction_flag == 1)
1643 expand_exit_something ();
1644 }
1645 if (check_token (ELSE))
1646 {
1647 if (! ignoring)
1648 chill_handle_case_default ();
1649 parse_opt_actions ();
1650 if (! ignoring)
1651 {
1652 emit_line_note (input_filename, lineno);
1653 expand_exit_something ();
1654 }
1655 }
1656 else if (! ignoring && TREE_CODE (selector) != ERROR_MARK &&
1657 ! no_completeness_check)
1658 check_missing_cases (TREE_TYPE (selector));
1659
1660 expect (ESAC, "missing 'ESAC' after 'CASE'");
1661 if (! ignoring)
1662 {
1663 expand_end_case (selector);
1664 pop_momentary ();
1665 }
1666 }
1667
1668 static void
1669 parse_multi_dimension_case_action (selector)
1670 tree selector;
1671 {
1672 struct rtx_def *begin_test_label = 0, *end_case_label, *new_label;
1673 tree action_labels = NULL_TREE;
1674 tree tests = NULL_TREE;
1675 int save_lineno = lineno;
1676 char *save_filename = input_filename;
1677
1678 /* We can't compute the range of an (ELSE) label until all of the CASE
1679 label specifications have been seen, however, the code for the actions
1680 between them is generated on the fly. We can still generate everything in
1681 one pass is we use the following form:
1682
1683 Compile a CASE of the form
1684
1685 case S1,...,Sn of
1686 (X11),...,(X1n): A1;
1687 ...
1688 (Xm1),...,(Xmn): Am;
1689 else Ae;
1690 esac;
1691
1692 into:
1693
1694 goto L0;
1695 L1: A1; goto L99;
1696 ...
1697 Lm: Am; goto L99;
1698 Le: Ae; goto L99;
1699 L0:
1700 T1 := s1; ...; Tn := Sn;
1701 if (T1 = X11 and ... and Tn = X1n) GOTO L1;
1702 ...
1703 if (T1 = Xm1 and ... and Tn = Xmn) GOTO Lm;
1704 GOTO Le;
1705 L99;
1706 */
1707
1708 if (! ignoring)
1709 {
1710 selector = check_case_selector_list (selector);
1711 begin_test_label = gen_label_rtx ();
1712 end_case_label = gen_label_rtx ();
1713 emit_jump (begin_test_label);
1714 }
1715
1716 for (;;)
1717 {
1718 tree label_spec = parse_case_label_specification (selector);
1719 if (label_spec != NULL_TREE)
1720 {
1721 expect (COLON, "missing ':' in case alternative");
1722 if (! ignoring)
1723 {
1724 tests = tree_cons (label_spec, NULL_TREE, tests);
1725
1726 if (action_labels != NULL_TREE)
1727 emit_jump (end_case_label);
1728
1729 new_label = gen_label_rtx ();
1730 emit_label (new_label);
1731 emit_line_note (input_filename, lineno);
1732 action_labels = tree_cons (NULL_TREE, NULL_TREE, action_labels);
1733 TREE_CST_RTL (action_labels) = new_label;
1734 }
1735 }
1736 else if (! parse_action ())
1737 {
1738 if (action_labels != NULL_TREE)
1739 emit_jump (end_case_label);
1740 break;
1741 }
1742 }
1743
1744 if (check_token (ELSE))
1745 {
1746 if (! ignoring)
1747 {
1748 new_label = gen_label_rtx ();
1749 emit_label (new_label);
1750 emit_line_note (input_filename, lineno);
1751 action_labels = tree_cons (NULL_TREE, NULL_TREE, action_labels);
1752 TREE_CST_RTL (action_labels) = new_label;
1753 }
1754 parse_opt_actions ();
1755 if (! ignoring)
1756 emit_jump (end_case_label);
1757 }
1758
1759 expect (ESAC, "missing 'ESAC' after 'CASE'");
1760
1761 if (! ignoring)
1762 {
1763 emit_label (begin_test_label);
1764 emit_line_note (save_filename, save_lineno);
1765 if (tests != NULL_TREE)
1766 {
1767 tree cond;
1768 tests = nreverse (tests);
1769 action_labels = nreverse (action_labels);
1770 compute_else_ranges (selector, tests);
1771
1772 cond = build_multi_case_selector_expression (selector, TREE_PURPOSE (tests));
1773 expand_start_cond (truthvalue_conversion (cond), label ? 1 : 0);
1774 emit_jump (TREE_CST_RTL (action_labels));
1775
1776 for (tests = TREE_CHAIN (tests), action_labels = TREE_CHAIN (action_labels);
1777 tests != NULL_TREE && action_labels != NULL_TREE;
1778 tests = TREE_CHAIN (tests), action_labels = TREE_CHAIN (action_labels))
1779 {
1780 cond =
1781 build_multi_case_selector_expression (selector, TREE_PURPOSE (tests));
1782 expand_start_elseif (truthvalue_conversion (cond));
1783 emit_jump (TREE_CST_RTL (action_labels));
1784 }
1785 if (action_labels != NULL_TREE)
1786 {
1787 expand_start_else ();
1788 emit_jump (TREE_CST_RTL (action_labels));
1789 }
1790 expand_end_cond ();
1791 }
1792 emit_label (end_case_label);
1793 }
1794 }
1795
1796 static void
1797 parse_case_action (label)
1798 tree label;
1799 {
1800 tree selector;
1801 int multi_dimension_case = 0;
1802
1803 require (CASE);
1804 selector = parse_expr_list ();
1805 selector = nreverse (selector);
1806 expect (OF, "missing 'OF' after 'CASE'");
1807 parse_range_list_clause ();
1808
1809 PUSH_ACTION;
1810 if (label)
1811 pushlevel (1);
1812
1813 if (! ignoring)
1814 {
1815 expand_exit_needed = 0;
1816 if (TREE_CODE (selector) == TREE_LIST)
1817 {
1818 if (TREE_CHAIN (selector) != NULL_TREE)
1819 multi_dimension_case = 1;
1820 else
1821 selector = TREE_VALUE (selector);
1822 }
1823 }
1824
1825 /* We want to use the regular CASE support for the single dimension case. The
1826 multi dimension case requires different handling. Note that when "ignoring"
1827 is true we parse using the single dimension code. This is OK since it will
1828 still parse correctly. */
1829 if (multi_dimension_case)
1830 parse_multi_dimension_case_action (selector);
1831 else
1832 parse_single_dimension_case_action (selector);
1833
1834 if (label)
1835 {
1836 possibly_define_exit_label (label);
1837 poplevel (0, 0, 0);
1838 }
1839 }
1840
1841 /* Matches: [ <asm_operand> { "," <asm_operand> }* ],
1842 where <asm_operand> = STRING '(' <expression> ')'
1843 These are the operands other than the first string and colon
1844 in asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x)) */
1845
1846 static tree
1847 parse_asm_operands ()
1848 {
1849 tree list = NULL_TREE;
1850 if (PEEK_TOKEN () != STRING)
1851 return NULL_TREE;
1852 for (;;)
1853 {
1854 tree string, expr;
1855 if (PEEK_TOKEN () != STRING)
1856 {
1857 error ("bad ASM operand");
1858 return list;
1859 }
1860 string = PEEK_TREE();
1861 FORWARD_TOKEN ();
1862 expect (LPRN, "missing '(' in ASM operand");
1863 expr = parse_expression ();
1864 expect (RPRN, "missing ')' in ASM operand");
1865 list = tree_cons (string, expr, list);
1866 if (! check_token (COMMA))
1867 break;
1868 }
1869 return nreverse (list);
1870 }
1871
1872 /* Matches: STRING { ',' STRING }* */
1873
1874 static tree
1875 parse_asm_clobbers ()
1876 {
1877 tree list = NULL_TREE;
1878 for (;;)
1879 {
1880 tree string;
1881 if (PEEK_TOKEN () != STRING)
1882 {
1883 error ("bad ASM operand");
1884 return list;
1885 }
1886 string = PEEK_TREE();
1887 FORWARD_TOKEN ();
1888 list = tree_cons (NULL_TREE, string, list);
1889 if (! check_token (COMMA))
1890 break;
1891 }
1892 return list;
1893 }
1894
1895 void
1896 ch_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
1897 tree string, outputs, inputs, clobbers;
1898 int vol;
1899 char *filename;
1900 int line;
1901 {
1902 int noutputs = list_length (outputs);
1903 register int i;
1904 /* o[I] is the place that output number I should be written. */
1905 register tree *o = (tree *) alloca (noutputs * sizeof (tree));
1906 register tree tail;
1907
1908 if (TREE_CODE (string) == ADDR_EXPR)
1909 string = TREE_OPERAND (string, 0);
1910 if (TREE_CODE (string) != STRING_CST)
1911 {
1912 error ("asm template is not a string constant");
1913 return;
1914 }
1915
1916 /* Record the contents of OUTPUTS before it is modified. */
1917 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
1918 o[i] = TREE_VALUE (tail);
1919
1920 #if 0
1921 /* Perform default conversions on array and function inputs. */
1922 /* Don't do this for other types--
1923 it would screw up operands expected to be in memory. */
1924 for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), i++)
1925 if (TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == ARRAY_TYPE
1926 || TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE)
1927 TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail));
1928 #endif
1929
1930 /* Generate the ASM_OPERANDS insn;
1931 store into the TREE_VALUEs of OUTPUTS some trees for
1932 where the values were actually stored. */
1933 expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
1934
1935 /* Copy all the intermediate outputs into the specified outputs. */
1936 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
1937 {
1938 if (o[i] != TREE_VALUE (tail))
1939 {
1940 expand_expr (build_chill_modify_expr (o[i], TREE_VALUE (tail)),
1941 0, VOIDmode, 0);
1942 free_temp_slots ();
1943 }
1944 /* Detect modification of read-only values.
1945 (Otherwise done by build_modify_expr.) */
1946 else
1947 {
1948 tree type = TREE_TYPE (o[i]);
1949 if (TYPE_READONLY (type)
1950 || ((TREE_CODE (type) == RECORD_TYPE
1951 || TREE_CODE (type) == UNION_TYPE)
1952 && TYPE_FIELDS_READONLY (type)))
1953 warning ("readonly location modified by 'asm'");
1954 }
1955 }
1956
1957 /* Those MODIFY_EXPRs could do autoincrements. */
1958 emit_queue ();
1959 }
1960
1961 static void
1962 parse_asm_action ()
1963 {
1964 tree insn;
1965 require (ASM_KEYWORD);
1966 expect (LPRN, "missing '('");
1967 PUSH_ACTION;
1968 if (!ignoring)
1969 emit_line_note (input_filename, lineno);
1970 insn = parse_expression ();
1971 if (check_token (COLON))
1972 {
1973 tree output_operand, input_operand, clobbered_regs;
1974 output_operand = parse_asm_operands ();
1975 if (check_token (COLON))
1976 input_operand = parse_asm_operands ();
1977 else
1978 input_operand = NULL_TREE;
1979 if (check_token (COLON))
1980 clobbered_regs = parse_asm_clobbers ();
1981 else
1982 clobbered_regs = NULL_TREE;
1983 expect (RPRN, "missing ')'");
1984 if (!ignoring)
1985 ch_expand_asm_operands (insn, output_operand, input_operand,
1986 clobbered_regs, FALSE,
1987 input_filename, lineno);
1988 }
1989 else
1990 {
1991 expect (RPRN, "missing ')'");
1992 STRIP_NOPS (insn);
1993 if (ignoring) { }
1994 else if ((TREE_CODE (insn) == ADDR_EXPR
1995 && TREE_CODE (TREE_OPERAND (insn, 0)) == STRING_CST)
1996 || TREE_CODE (insn) == STRING_CST)
1997 expand_asm (insn);
1998 else
1999 error ("argument of `asm' is not a constant string");
2000 }
2001 }
2002
2003 static void
2004 parse_begin_end_block (label)
2005 tree label;
2006 {
2007 require (BEGINTOKEN);
2008 #if 0
2009 /* don't make a linenote at BEGIN */
2010 INIT_ACTION;
2011 #endif
2012 pushlevel (1);
2013 if (! ignoring)
2014 {
2015 clear_last_expr ();
2016 push_momentary ();
2017 expand_start_bindings (label ? 1 : 0);
2018 }
2019 push_handler ();
2020 parse_body ();
2021 expect (END, "missing 'END'");
2022 /* Note that the opthandler comes before the poplevel
2023 - hence a handler is in the scope of the block. */
2024 parse_opt_handler ();
2025 possibly_define_exit_label (label);
2026 if (! ignoring)
2027 {
2028 emit_line_note (input_filename, lineno);
2029 expand_end_bindings (getdecls (), kept_level_p (), 0);
2030 }
2031 poplevel (kept_level_p (), 0, 0);
2032 if (! ignoring)
2033 pop_momentary ();
2034 parse_opt_end_label_semi_colon (label);
2035 }
2036
2037 static void
2038 parse_if_action (label)
2039 tree label;
2040 {
2041 tree cond;
2042 require (IF);
2043 PUSH_ACTION;
2044 cond = parse_expression ();
2045 if (label)
2046 pushlevel (1);
2047 if (! ignoring)
2048 {
2049 expand_start_cond (truthvalue_conversion (cond),
2050 label ? 1 : 0);
2051 }
2052 parse_then_clause ();
2053 parse_opt_else_clause ();
2054 expect (FI, "expected 'FI' after 'IF'");
2055 if (! ignoring)
2056 {
2057 emit_line_note (input_filename, lineno);
2058 expand_end_cond ();
2059 }
2060 if (label)
2061 {
2062 possibly_define_exit_label (label);
2063 poplevel (0, 0, 0);
2064 }
2065 }
2066
2067 /* Matches: <iteration> (as in a <for control>). */
2068
2069 static void
2070 parse_iteration ()
2071 {
2072 tree loop_counter = parse_defining_occurrence ();
2073 if (check_token (ASGN))
2074 {
2075 tree start_value = parse_expression ();
2076 tree step_value
2077 = check_token (BY) ? parse_expression () : NULL_TREE;
2078 int going_down = check_token (DOWN);
2079 tree end_value;
2080 if (check_token (TO))
2081 end_value = parse_expression ();
2082 else
2083 {
2084 error ("expected 'TO' in step enumeration");
2085 end_value = error_mark_node;
2086 }
2087 if (!ignoring)
2088 build_loop_iterator (loop_counter, start_value, step_value,
2089 end_value, going_down, 0, 0);
2090 }
2091 else
2092 {
2093 int going_down = check_token (DOWN);
2094 tree expr;
2095 if (check_token (IN))
2096 expr = parse_expression ();
2097 else
2098 {
2099 error ("expected 'IN' in FOR control here");
2100 expr = error_mark_node;
2101 }
2102 if (!ignoring)
2103 {
2104 tree low_bound, high_bound;
2105 if (expr && TREE_CODE (expr) == TYPE_DECL)
2106 {
2107 expr = TREE_TYPE (expr);
2108 /* FIXME: expr must be an array or powerset */
2109 low_bound = convert (expr, TYPE_MIN_VALUE (expr));
2110 high_bound = convert (expr, TYPE_MAX_VALUE (expr));
2111 }
2112 else
2113 {
2114 low_bound = expr;
2115 high_bound = NULL_TREE;
2116 }
2117 build_loop_iterator (loop_counter, low_bound,
2118 NULL_TREE, high_bound,
2119 going_down, 1, 0);
2120 }
2121 }
2122 }
2123
2124 /* Matches: '(' <event list> ')' ':'.
2125 Or; returns NULL_EXPR. */
2126
2127 static tree
2128 parse_delay_case_event_list ()
2129 {
2130 tree event_list = NULL_TREE;
2131 tree event;
2132 if (! check_token (LPRN))
2133 return NULL_TREE;
2134 event = parse_expression ();
2135 if (PEEK_TOKEN () == ')' && PEEK_TOKEN1 () != ':')
2136 {
2137 /* Oops. */
2138 require (RPRN);
2139 pushback_paren_expr (event);
2140 return NULL_TREE;
2141 }
2142 for (;;)
2143 {
2144 if (! ignoring)
2145 event_list = tree_cons (NULL_TREE, event, event_list);
2146 if (! check_token (COMMA))
2147 break;
2148 event = parse_expression ();
2149 }
2150 expect (RPRN, "missing ')'");
2151 expect (COLON, "missing ':'");
2152 return ignoring ? error_mark_node : event_list;
2153 }
2154
2155 static void
2156 parse_delay_case_action (label)
2157 tree label;
2158 {
2159 tree label_cnt = NULL_TREE, set_location, priority;
2160 tree combined_event_list = NULL_TREE;
2161 require (DELAY);
2162 require (CASE);
2163 PUSH_ACTION;
2164 pushlevel (1);
2165 expand_exit_needed = 0;
2166 if (check_token (SET))
2167 {
2168 set_location = parse_expression ();
2169 parse_semi_colon ();
2170 }
2171 else
2172 set_location = NULL_TREE;
2173 if (check_token (PRIORITY))
2174 {
2175 priority = parse_expression ();
2176 parse_semi_colon ();
2177 }
2178 else
2179 priority = NULL_TREE;
2180 if (! ignoring)
2181 label_cnt = build_delay_case_start (set_location, priority);
2182 for (;;)
2183 {
2184 tree event_list = parse_delay_case_event_list ();
2185 if (event_list)
2186 {
2187 if (! ignoring )
2188 {
2189 int if_or_elseif = combined_event_list == NULL_TREE;
2190 build_delay_case_label (event_list, if_or_elseif);
2191 combined_event_list = chainon (combined_event_list, event_list);
2192 }
2193 }
2194 else if (parse_action ())
2195 {
2196 if (! ignoring)
2197 {
2198 expand_exit_needed = 1;
2199 if (combined_event_list == NULL_TREE)
2200 error ("missing DELAY CASE alternative");
2201 }
2202 }
2203 else
2204 break;
2205 }
2206 expect (ESAC, "missing 'ESAC' in DELAY CASE'");
2207 if (! ignoring)
2208 build_delay_case_end (label_cnt, combined_event_list);
2209 possibly_define_exit_label (label);
2210 poplevel (0, 0, 0);
2211 }
2212
2213 static void
2214 parse_do_action (label)
2215 tree label;
2216 {
2217 tree condition;
2218 int token;
2219 require (DO);
2220 if (check_token (WITH))
2221 {
2222 tree list = NULL_TREE;
2223 for (;;)
2224 {
2225 tree name = parse_primval ();
2226 if (! ignoring && TREE_CODE (name) != ERROR_MARK)
2227 {
2228 if (TREE_CODE (TREE_TYPE (name)) == REFERENCE_TYPE)
2229 name = convert (TREE_TYPE (TREE_TYPE (name)), name);
2230 else
2231 {
2232 int is_loc = chill_location (name);
2233 if (is_loc == 1) /* This is probably not possible */
2234 warning ("non-referable location in DO WITH");
2235
2236 if (is_loc > 1)
2237 name = build_chill_arrow_expr (name, 1);
2238 name = decl_temp1 (get_identifier ("__with_element"),
2239 TREE_TYPE (name),
2240 0, name, 0, 0);
2241 if (is_loc > 1)
2242 name = build_chill_indirect_ref (name, NULL_TREE, 0);
2243
2244 }
2245 if (TREE_CODE (TREE_TYPE (name)) != RECORD_TYPE)
2246 error ("WITH element must be of STRUCT mode");
2247 else
2248 list = tree_cons (NULL_TREE, name, list);
2249 }
2250 if (! check_token (COMMA))
2251 break;
2252 }
2253 pushlevel (1);
2254 push_action ();
2255 for (list = nreverse (list); list != NULL_TREE; list = TREE_CHAIN (list))
2256 shadow_record_fields (TREE_VALUE (list));
2257
2258 parse_semi_colon ();
2259 parse_opt_actions ();
2260 expect (OD, "missing 'OD' in 'DO WITH'");
2261 if (! ignoring)
2262 emit_line_note (input_filename, lineno);
2263 possibly_define_exit_label (label);
2264 parse_opt_handler ();
2265 parse_opt_end_label_semi_colon (label);
2266 poplevel (0, 0, 0);
2267 return;
2268 }
2269 token = PEEK_TOKEN();
2270 if (token != FOR && token != WHILE)
2271 {
2272 push_handler ();
2273 parse_opt_actions ();
2274 expect (OD, "Missing 'OD' after 'DO'");
2275 parse_opt_handler ();
2276 parse_opt_end_label_semi_colon (label);
2277 return;
2278 }
2279 if (! ignoring)
2280 emit_line_note (input_filename, lineno);
2281 push_loop_block ();
2282 if (check_token (FOR))
2283 {
2284 if (check_token (EVER))
2285 {
2286 if (!ignoring)
2287 build_loop_iterator (NULL_TREE, NULL_TREE,
2288 NULL_TREE, NULL_TREE,
2289 0, 0, 1);
2290 }
2291 else
2292 {
2293 parse_iteration ();
2294 while (check_token (COMMA))
2295 parse_iteration ();
2296 }
2297 }
2298 else if (!ignoring)
2299 build_loop_iterator (NULL_TREE, NULL_TREE,
2300 NULL_TREE, NULL_TREE,
2301 0, 0, 1);
2302
2303 begin_loop_scope ();
2304 if (! ignoring)
2305 build_loop_start (label);
2306 condition = check_token (WHILE) ? parse_expression () : NULL_TREE;
2307 if (! ignoring)
2308 top_loop_end_check (condition);
2309 parse_semi_colon ();
2310 parse_opt_actions ();
2311 if (! ignoring)
2312 build_loop_end ();
2313 expect (OD, "Missing 'OD' after 'DO'");
2314 /* Note that the handler is inside the reach of the DO. */
2315 parse_opt_handler ();
2316 end_loop_scope (label);
2317 pop_loop_block ();
2318 parse_opt_end_label_semi_colon (label);
2319 }
2320
2321 /* Matches: '(' <signal name> [ 'IN' <defining occurrence list> ']' ')' ':'
2322 or: '(' <buffer location> IN (defining occurrence> ')' ':'
2323 or: returns NULL_TREE. */
2324
2325 static tree
2326 parse_receive_spec ()
2327 {
2328 tree val;
2329 tree name_list = NULL_TREE;
2330 if (!check_token (LPRN))
2331 return NULL_TREE;
2332 val = parse_primval ();
2333 if (check_token (IN))
2334 {
2335 #if 0
2336 if (flag_local_loop_counter)
2337 name_list = parse_defining_occurrence_list ();
2338 else
2339 #endif
2340 {
2341 for (;;)
2342 {
2343 tree loc = parse_primval ();
2344 if (! ignoring)
2345 name_list = tree_cons (NULL_TREE, loc, name_list);
2346 if (! check_token (COMMA))
2347 break;
2348 }
2349 }
2350 }
2351 if (! check_token (RPRN))
2352 {
2353 error ("missing ')' in signal/buffer receive alternative");
2354 return NULL_TREE;
2355 }
2356 if (check_token (COLON))
2357 {
2358 if (ignoring || val == NULL_TREE || TREE_CODE (val) == ERROR_MARK)
2359 return error_mark_node;
2360 else
2361 return build_receive_case_label (val, name_list);
2362 }
2363
2364 /* We saw: '(' <primitive value> ')' not followed by ':'.
2365 Presumably the start of an action. Backup and fail. */
2366 if (name_list != NULL_TREE)
2367 error ("misplaced 'IN' in signal/buffer receive alternative");
2368 pushback_paren_expr (val);
2369 return NULL_TREE;
2370 }
2371
2372 /* To understand the code generation for this, see ch-tasking.c,
2373 and the 2-page comments preceding the
2374 build_chill_receive_case_start () definition. */
2375
2376 static void
2377 parse_receive_case_action (label)
2378 tree label;
2379 {
2380 tree instance_location;
2381 tree have_else_actions;
2382 int spec_seen = 0;
2383 tree alt_list = NULL_TREE;
2384 require (RECEIVE);
2385 require (CASE);
2386 push_action ();
2387 pushlevel (1);
2388 if (! ignoring)
2389 {
2390 expand_exit_needed = 0;
2391 }
2392
2393 if (check_token (SET))
2394 {
2395 instance_location = parse_expression ();
2396 parse_semi_colon ();
2397 }
2398 else
2399 instance_location = NULL_TREE;
2400 if (! ignoring)
2401 instance_location = build_receive_case_start (instance_location);
2402
2403 for (;;)
2404 {
2405 tree receive_spec = parse_receive_spec ();
2406 if (receive_spec)
2407 {
2408 if (! ignoring)
2409 alt_list = tree_cons (NULL_TREE, receive_spec, alt_list);
2410 spec_seen++;
2411 }
2412 else if (parse_action ())
2413 {
2414 if (! spec_seen && pass == 1)
2415 error ("missing RECEIVE alternative");
2416 if (! ignoring)
2417 expand_exit_needed = 1;
2418 spec_seen = 1;
2419 }
2420 else
2421 break;
2422 }
2423 if (check_token (ELSE))
2424 {
2425 if (! ignoring)
2426 {
2427 emit_line_note (input_filename, lineno);
2428 if (build_receive_case_if_generated ())
2429 expand_start_else ();
2430 }
2431 parse_opt_actions ();
2432 have_else_actions = integer_one_node;
2433 }
2434 else
2435 have_else_actions = integer_zero_node;
2436 expect (ESAC, "missing 'ESAC' matching 'RECEIVE CASE'");
2437 if (! ignoring)
2438 {
2439 build_receive_case_end (instance_location, nreverse (alt_list),
2440 have_else_actions);
2441 }
2442 possibly_define_exit_label (label);
2443 poplevel (0, 0, 0);
2444 }
2445
2446 static void
2447 parse_send_action ()
2448 {
2449 tree signal = NULL_TREE;
2450 tree buffer = NULL_TREE;
2451 tree value_list;
2452 tree with_expr, to_expr, priority;
2453 require (SEND);
2454 /* The tricky part is distinguishing between a SEND buffer action,
2455 and a SEND signal action. */
2456 if (pass != 2 || PEEK_TOKEN () != NAME)
2457 {
2458 /* If this is pass 2, it's a SEND buffer action.
2459 If it's pass 1, we don't care. */
2460 buffer = parse_primval ();
2461 }
2462 else
2463 {
2464 /* We have to specifically check for signalname followed by
2465 a '(', since we allow a signalname to be used (syntactically)
2466 as a "function". */
2467 tree name = parse_name ();
2468 if (TREE_CODE (name) == TYPE_DECL && CH_DECL_SIGNAL (name))
2469 signal = name; /* It's a SEND signal action! */
2470 else
2471 {
2472 /* It's not a legal SEND signal action.
2473 Back up and try as a SEND buffer action. */
2474 pushback_token (EXPR, name);
2475 buffer = parse_primval ();
2476 }
2477 }
2478 if (check_token (LPRN))
2479 {
2480 value_list = NULL_TREE;
2481 for (;;)
2482 {
2483 tree expr = parse_untyped_expr ();
2484 if (! ignoring)
2485 value_list = tree_cons (NULL_TREE, expr, value_list);
2486 if (! check_token (COMMA))
2487 break;
2488 }
2489 value_list = nreverse (value_list);
2490 expect (RPRN, "missing ')'");
2491 }
2492 else
2493 value_list = NULL_TREE;
2494 if (check_token (WITH))
2495 with_expr = parse_expression ();
2496 else
2497 with_expr = NULL_TREE;
2498 if (check_token (TO))
2499 to_expr = parse_expression ();
2500 else
2501 to_expr = NULL_TREE;
2502 if (check_token (PRIORITY))
2503 priority = parse_expression ();
2504 else
2505 priority = NULL_TREE;
2506 PUSH_ACTION;
2507 if (ignoring)
2508 return;
2509
2510 if (signal)
2511 { /* It's a <send signal action>! */
2512 tree sigdesc = build_signal_descriptor (signal, value_list);
2513 if (sigdesc != NULL_TREE && TREE_CODE (sigdesc) != ERROR_MARK)
2514 {
2515 tree sendto = to_expr ? to_expr : IDENTIFIER_SIGNAL_DEST (signal);
2516 expand_send_signal (sigdesc, with_expr,
2517 sendto, priority, DECL_NAME (signal));
2518 }
2519 }
2520 else
2521 {
2522 /* all checks are done in expand_send_buffer */
2523 expand_send_buffer (buffer, value_list, priority, with_expr, to_expr);
2524 }
2525 }
2526
2527 static void
2528 parse_start_action ()
2529 {
2530 tree name, copy_number, param_list, startset;
2531 require (START);
2532 name = parse_name_string ();
2533 expect (LPRN, "missing '(' in START action");
2534 PUSH_ACTION;
2535 /* copy number is a required parameter */
2536 copy_number = parse_expression ();
2537 if (!ignoring
2538 && (copy_number == NULL_TREE
2539 || TREE_CODE (copy_number) == ERROR_MARK
2540 || TREE_CODE (TREE_TYPE (copy_number)) != INTEGER_TYPE))
2541 {
2542 error ("PROCESS copy number must be integer");
2543 copy_number = integer_zero_node;
2544 }
2545 if (check_token (COMMA))
2546 param_list = parse_expr_list (); /* user parameters */
2547 else
2548 param_list = NULL_TREE;
2549 expect (RPRN, "missing ')'");
2550 startset = check_token (SET) ? parse_primval () : NULL;
2551 build_start_process (name, copy_number, param_list, startset);
2552 }
2553
2554 static void
2555 parse_opt_actions ()
2556 {
2557 while (parse_action ()) ;
2558 }
2559
2560 static int
2561 parse_action ()
2562 {
2563 tree label = NULL_TREE;
2564 tree expr, rhs, loclist;
2565 enum tree_code op;
2566
2567 if (current_function_decl == global_function_decl
2568 && PEEK_TOKEN () != SC
2569 && PEEK_TOKEN () != END)
2570 seen_action = 1, build_constructor = 1;
2571
2572 if (PEEK_TOKEN () == NAME && PEEK_TOKEN1 () == COLON)
2573 {
2574 label = parse_defining_occurrence ();
2575 require (COLON);
2576 INIT_ACTION;
2577 define_label (input_filename, lineno, label);
2578 }
2579
2580 switch (PEEK_TOKEN ())
2581 {
2582 case AFTER:
2583 {
2584 int delay;
2585 require (AFTER);
2586 expr = parse_primval ();
2587 delay = check_token (DELAY);
2588 expect (IN, "missing 'IN'");
2589 push_action ();
2590 pushlevel (1);
2591 build_after_start (expr, delay);
2592 parse_opt_actions ();
2593 expect (TIMEOUT, "missing 'TIMEOUT'");
2594 build_after_timeout_start ();
2595 parse_opt_actions ();
2596 expect (END, "missing 'END'");
2597 build_after_end ();
2598 possibly_define_exit_label (label);
2599 poplevel (0, 0, 0);
2600 }
2601 goto bracketed_action;
2602 case ASM_KEYWORD:
2603 parse_asm_action ();
2604 goto no_handler_action;
2605 case ASSERT:
2606 require (ASSERT);
2607 PUSH_ACTION;
2608 expr = parse_expression ();
2609 if (! ignoring)
2610 { tree assertfail = ridpointers[(int) RID_ASSERTFAIL];
2611 expr = build (TRUTH_ORIF_EXPR, void_type_node, expr,
2612 build_cause_exception (assertfail, 0));
2613 expand_expr_stmt (fold (expr));
2614 }
2615 goto handler_action;
2616 case AT:
2617 require (AT);
2618 PUSH_ACTION;
2619 expr = parse_primval ();
2620 expect (IN, "missing 'IN'");
2621 pushlevel (1);
2622 if (! ignoring)
2623 build_at_action (expr);
2624 parse_opt_actions ();
2625 expect (TIMEOUT, "missing 'TIMEOUT'");
2626 if (! ignoring)
2627 expand_start_else ();
2628 parse_opt_actions ();
2629 expect (END, "missing 'END'");
2630 if (! ignoring)
2631 expand_end_cond ();
2632 possibly_define_exit_label (label);
2633 poplevel (0, 0, 0);
2634 goto bracketed_action;
2635 case BEGINTOKEN:
2636 parse_begin_end_block (label);
2637 return 1;
2638 case CASE:
2639 parse_case_action (label);
2640 goto bracketed_action;
2641 case CAUSE:
2642 require (CAUSE);
2643 expr = parse_name_string ();
2644 PUSH_ACTION;
2645 if (! ignoring && TREE_CODE (expr) != ERROR_MARK)
2646 expand_cause_exception (expr);
2647 goto no_handler_action;
2648 case CONTINUE:
2649 require (CONTINUE);
2650 expr = parse_expression ();
2651 PUSH_ACTION;
2652 if (! ignoring)
2653 expand_continue_event (expr);
2654 goto handler_action;
2655 case CYCLE:
2656 require (CYCLE);
2657 PUSH_ACTION;
2658 expr = parse_primval ();
2659 expect (IN, "missing 'IN' after 'CYCLE'");
2660 pushlevel (1);
2661 /* We a tree list where TREE_VALUE is the label
2662 and TREE_PURPOSE is the variable denotes the timeout id. */
2663 expr = build_cycle_start (expr);
2664 parse_opt_actions ();
2665 expect (END, "missing 'END'");
2666 if (! ignoring)
2667 build_cycle_end (expr);
2668 possibly_define_exit_label (label);
2669 poplevel (0, 0, 0);
2670 goto bracketed_action;
2671 case DELAY:
2672 if (PEEK_TOKEN1 () == CASE)
2673 {
2674 parse_delay_case_action (label);
2675 goto bracketed_action;
2676 }
2677 require (DELAY);
2678 PUSH_ACTION;
2679 expr = parse_primval ();
2680 rhs = check_token (PRIORITY) ? parse_expression () : NULL_TREE;
2681 if (! ignoring)
2682 build_delay_action (expr, rhs);
2683 goto handler_action;
2684 case DO:
2685 parse_do_action (label);
2686 return 1;
2687 case EXIT:
2688 require (EXIT);
2689 expr = parse_name_string ();
2690 PUSH_ACTION;
2691 lookup_and_handle_exit (expr);
2692 goto no_handler_action;
2693 case GOTO:
2694 require (GOTO);
2695 expr = parse_name_string ();
2696 PUSH_ACTION;
2697 lookup_and_expand_goto (expr);
2698 goto no_handler_action;
2699 case IF:
2700 parse_if_action (label);
2701 goto bracketed_action;
2702 case RECEIVE:
2703 if (PEEK_TOKEN1 () != CASE)
2704 return 0;
2705 parse_receive_case_action (label);
2706 goto bracketed_action;
2707 case RESULT:
2708 require (RESULT);
2709 PUSH_ACTION;
2710 expr = parse_untyped_expr ();
2711 if (! ignoring)
2712 chill_expand_result (expr, 1);
2713 goto handler_action;
2714 case RETURN:
2715 require (RETURN);
2716 PUSH_ACTION;
2717 expr = parse_opt_untyped_expr ();
2718 if (! ignoring)
2719 {
2720 /* Do this as RESULT expr and RETURN to get exceptions */
2721 chill_expand_result (expr, 0);
2722 expand_goto_except_cleanup (proc_action_level);
2723 chill_expand_return (NULL_TREE, 0);
2724 }
2725 if (expr)
2726 goto handler_action;
2727 else
2728 goto no_handler_action;
2729 case SC:
2730 require (SC);
2731 return 1;
2732 case SEND:
2733 parse_send_action ();
2734 goto handler_action;
2735 case START:
2736 parse_start_action ();
2737 goto handler_action;
2738 case STOP:
2739 require (STOP);
2740 PUSH_ACTION;
2741 if (! ignoring)
2742 { tree func = lookup_name (get_identifier ("__stop_process"));
2743 tree result = build_chill_function_call (func, NULL_TREE);
2744 expand_expr_stmt (result);
2745 }
2746 goto no_handler_action;
2747 case CALL:
2748 require (CALL);
2749 /* Fall through to here ... */
2750 case EXPR:
2751 case LPRN:
2752 case NAME:
2753 /* This handles calls and assignments. */
2754 PUSH_ACTION;
2755 expr = parse_primval ();
2756 switch (PEEK_TOKEN ())
2757 {
2758 case END:
2759 parse_semi_colon (); /* Emits error message. */
2760 case ON:
2761 case SC:
2762 if (!ignoring && TREE_CODE (expr) != ERROR_MARK)
2763 {
2764 if (TREE_CODE (expr) != CALL_EXPR
2765 && TREE_TYPE (expr) != void_type_node
2766 && ! TREE_SIDE_EFFECTS (expr))
2767 {
2768 if (TREE_CODE (expr) == FUNCTION_DECL)
2769 error ("missing parenthesis for procedure call");
2770 else
2771 error ("expression is not an action");
2772 expr = error_mark_node;
2773 }
2774 else
2775 expand_expr_stmt (expr);
2776 }
2777 goto handler_action;
2778 default:
2779 loclist
2780 = ignoring ? NULL_TREE : build_tree_list (NULL_TREE, expr);
2781 while (PEEK_TOKEN () == COMMA)
2782 {
2783 FORWARD_TOKEN ();
2784 expr = parse_primval ();
2785 if (!ignoring && TREE_CODE (expr) != ERROR_MARK)
2786 loclist = tree_cons (NULL_TREE, expr, loclist);
2787 }
2788 }
2789 switch (PEEK_TOKEN ())
2790 {
2791 case OR: op = BIT_IOR_EXPR; break;
2792 case XOR: op = BIT_XOR_EXPR; break;
2793 case ORIF: op = TRUTH_ORIF_EXPR; break;
2794 case AND: op = BIT_AND_EXPR; break;
2795 case ANDIF: op = TRUTH_ANDIF_EXPR; break;
2796 case PLUS: op = PLUS_EXPR; break;
2797 case SUB: op = MINUS_EXPR; break;
2798 case CONCAT: op = CONCAT_EXPR; break;
2799 case MUL: op = MULT_EXPR; break;
2800 case DIV: op = TRUNC_DIV_EXPR; break;
2801 case MOD: op = FLOOR_MOD_EXPR; break;
2802 case REM: op = TRUNC_MOD_EXPR; break;
2803
2804 default:
2805 error ("syntax error in action");
2806 case SC: case ON:
2807 case ASGN: op = NOP_EXPR; break;
2808 ;
2809 }
2810
2811 /* Looks like it was an assignment action. */
2812 FORWARD_TOKEN ();
2813 if (op != NOP_EXPR)
2814 expect (ASGN, "expected ':=' here");
2815 rhs = parse_untyped_expr ();
2816 if (!ignoring)
2817 expand_assignment_action (loclist, op, rhs);
2818 goto handler_action;
2819
2820 default:
2821 return 0;
2822 }
2823
2824 bracketed_action:
2825 /* We've parsed a bracketed action. */
2826 parse_opt_handler ();
2827 parse_opt_end_label_semi_colon (label);
2828 return 1;
2829
2830 no_handler_action:
2831 if (parse_opt_handler () != NULL_TREE && pass == 1)
2832 error ("no handler is permitted on this action.");
2833 parse_semi_colon ();
2834 return 1;
2835
2836 handler_action:
2837 parse_opt_handler ();
2838 parse_semi_colon ();
2839 return 1;
2840 }
2841
2842 static void
2843 parse_body ()
2844 {
2845 again:
2846 while (parse_definition (0)) ;
2847
2848 while (parse_action ()) ;
2849
2850 if (parse_definition (0))
2851 {
2852 if (pass == 1)
2853 pedwarn ("definition follows action");
2854 goto again;
2855 }
2856 }
2857
2858 static tree
2859 parse_opt_untyped_expr ()
2860 {
2861 switch (PEEK_TOKEN ())
2862 {
2863 case ON:
2864 case END:
2865 case SC:
2866 case COMMA:
2867 case COLON:
2868 case RPRN:
2869 return NULL_TREE;
2870 default:
2871 return parse_untyped_expr ();
2872 }
2873 }
2874
2875 static tree
2876 parse_call (function)
2877 tree function;
2878 {
2879 tree arg1, arg2, arg_list = NULL_TREE;
2880 enum terminal tok;
2881 require (LPRN);
2882 arg1 = parse_opt_untyped_expr ();
2883 if (arg1 != NULL_TREE)
2884 {
2885 tok = PEEK_TOKEN ();
2886 if (tok == UP || tok == COLON)
2887 {
2888 FORWARD_TOKEN ();
2889 #if 0
2890 /* check that arg1 isn't untyped (or mode);*/
2891 #endif
2892 arg2 = parse_expression ();
2893 expect (RPRN, "expected ')' to terminate slice");
2894 if (ignoring)
2895 return integer_zero_node;
2896 else if (tok == UP)
2897 return build_chill_slice_with_length (function, arg1, arg2);
2898 else
2899 return build_chill_slice_with_range (function, arg1, arg2);
2900 }
2901 if (!ignoring)
2902 arg_list = build_tree_list (NULL_TREE, arg1);
2903 while (check_token (COMMA))
2904 {
2905 arg2 = parse_untyped_expr ();
2906 if (!ignoring)
2907 arg_list = tree_cons (NULL_TREE, arg2, arg_list);
2908 }
2909 }
2910
2911 expect (RPRN, "expected ')' here");
2912 return ignoring ? function
2913 : build_generalized_call (function, nreverse (arg_list));
2914 }
2915
2916 /* Matches: <field name list>
2917 Returns: A list of IDENTIFIER_NODEs (or NULL_TREE if ignoring),
2918 in reverse order. */
2919
2920 static tree
2921 parse_tuple_fieldname_list ()
2922 {
2923 tree list = NULL_TREE;
2924 do
2925 {
2926 tree name;
2927 if (!check_token (DOT))
2928 {
2929 error ("bad tuple field name list");
2930 return NULL_TREE;
2931 }
2932 name = parse_simple_name_string ();
2933 list = ignoring ? NULL_TREE : tree_cons (NULL_TREE, name, list);
2934 } while (check_token (COMMA));
2935 return list;
2936 }
2937
2938 /* Returns one or nore TREE_LIST nodes, in reverse order. */
2939
2940 static tree
2941 parse_tuple_element ()
2942 {
2943 /* The tupleelement chain is built in reverse order,
2944 and put in forward order when the list is used. */
2945 tree value, label;
2946 if (PEEK_TOKEN () == DOT)
2947 {
2948 /* Parse a labelled structure tuple. */
2949 tree list = parse_tuple_fieldname_list (), field;
2950 expect (COLON, "missing ':' in tuple");
2951 value = parse_untyped_expr ();
2952 if (ignoring)
2953 return NULL_TREE;
2954 /* FIXME: Should use save_expr(value), but that
2955 confuses nested calls to digest_init! */
2956 /* Re-use the list of field names as a list of name-value pairs. */
2957 for (field = list; field != NULL_TREE; field = TREE_CHAIN (field))
2958 { tree field_name = TREE_VALUE (field);
2959 TREE_PURPOSE (field) = field_name;
2960 TREE_VALUE (field) = value;
2961 TUPLE_NAMED_FIELD (field) = 1;
2962 }
2963 return list;
2964 }
2965
2966 label = parse_case_label_list (NULL_TREE, 1);
2967 if (label)
2968 {
2969 expect (COLON, "missing ':' in tuple");
2970 value = parse_untyped_expr ();
2971 if (ignoring || label == NULL_TREE)
2972 return NULL_TREE;
2973 if (TREE_CODE (label) != TREE_LIST)
2974 {
2975 error ("invalid syntax for label in tuple");
2976 return NULL_TREE;
2977 }
2978 else
2979 {
2980 /* FIXME: Should use save_expr(value), but that
2981 confuses nested calls to digest_init! */
2982 tree link = label;
2983 for (; link != NULL_TREE; link = TREE_CHAIN (link))
2984 { tree index = TREE_VALUE (link);
2985 if (pass == 1 && TREE_CODE (index) != TREE_LIST)
2986 index = build1 (PAREN_EXPR, NULL_TREE, index);
2987 TREE_VALUE (link) = value;
2988 TREE_PURPOSE (link) = index;
2989 }
2990 return nreverse (label);
2991 }
2992 }
2993
2994 value = parse_untyped_expr ();
2995 if (check_token (COLON))
2996 {
2997 /* A powerset range [or possibly a labeled Array?] */
2998 tree value2 = parse_untyped_expr ();
2999 return ignoring ? NULL_TREE : build_tree_list (value, value2);
3000 }
3001 return ignoring ? NULL_TREE : build_tree_list (NULL_TREE, value);
3002 }
3003
3004 /* Matches: a COMMA-separated list of tuple elements.
3005 Returns a list (of TREE_LIST nodes). */
3006 static tree
3007 parse_opt_element_list ()
3008 {
3009 tree list = NULL_TREE;
3010 if (PEEK_TOKEN () == RPC)
3011 return NULL_TREE;
3012 for (;;)
3013 {
3014 tree element = parse_tuple_element ();
3015 list = chainon (element, list); /* Built in reverse order */
3016 if (PEEK_TOKEN () == RPC)
3017 break;
3018 if (!check_token (COMMA))
3019 {
3020 error ("bad syntax in tuple");
3021 return NULL_TREE;
3022 }
3023 }
3024 return nreverse (list);
3025 }
3026
3027 /* Parses: '[' elements ']'
3028 If modename is non-NULL it prefixed the tuple. */
3029
3030 static tree
3031 parse_tuple (modename)
3032 tree modename;
3033 {
3034 tree list;
3035 require (LPC);
3036 list = parse_opt_element_list ();
3037 expect (RPC, "missing ']' after tuple");
3038 if (ignoring)
3039 return integer_zero_node;
3040 list = build_nt (CONSTRUCTOR, NULL_TREE, list);
3041 if (modename == NULL_TREE)
3042 return list;
3043 else if (pass == 1)
3044 TREE_TYPE (list) = modename;
3045 else if (TREE_CODE (modename) != TYPE_DECL)
3046 {
3047 error ("non-mode name before tuple");
3048 return error_mark_node;
3049 }
3050 else
3051 list = chill_expand_tuple (TREE_TYPE (modename), list);
3052 return list;
3053 }
3054
3055 static tree
3056 parse_primval ()
3057 {
3058 tree val;
3059 switch (PEEK_TOKEN ())
3060 {
3061 case NUMBER:
3062 case FLOATING:
3063 case STRING:
3064 case SINGLECHAR:
3065 case BITSTRING:
3066 case CONST:
3067 case EXPR:
3068 val = PEEK_TREE();
3069 FORWARD_TOKEN ();
3070 break;
3071 case THIS:
3072 val = build_chill_function_call (PEEK_TREE (), NULL_TREE);
3073 FORWARD_TOKEN ();
3074 break;
3075 case LPRN:
3076 FORWARD_TOKEN ();
3077 val = parse_expression ();
3078 expect (RPRN, "missing right parenthesis");
3079 if (pass == 1 && ! ignoring)
3080 val = build1 (PAREN_EXPR, NULL_TREE, val);
3081 break;
3082 case LPC:
3083 val = parse_tuple (NULL_TREE);
3084 break;
3085 case NAME:
3086 val = parse_name ();
3087 if (PEEK_TOKEN() == LPC)
3088 val = parse_tuple (val); /* Matched: <mode_name> <tuple> */
3089 break;
3090 default:
3091 if (!ignoring)
3092 error ("invalid expression/location syntax");
3093 val = error_mark_node;
3094 }
3095 for (;;)
3096 {
3097 tree name, args;
3098 switch (PEEK_TOKEN ())
3099 {
3100 case DOT:
3101 FORWARD_TOKEN ();
3102 name = parse_simple_name_string ();
3103 val = ignoring ? val : build_chill_component_ref (val, name);
3104 continue;
3105 case ARROW:
3106 FORWARD_TOKEN ();
3107 name = parse_opt_name_string (0);
3108 val = ignoring ? val : build_chill_indirect_ref (val, name, 1);
3109 continue;
3110 case LPRN:
3111 /* The SEND buffer action syntax is ambiguous, at least when
3112 parsed left-to-right. In the example 'SEND foo(v) ...' the
3113 phrase 'foo(v)' could be a buffer location procedure call
3114 (which then must be followed by the value to send).
3115 On the other hand, if 'foo' is a buffer, stop parsing
3116 after 'foo', and let parse_send_action pick up '(v) as
3117 the value ot send.
3118
3119 We handle the ambiguity for SEND signal action differently,
3120 since we allow (as an extension) a signal to be used as
3121 a "function" (see build_generalized_call). */
3122 if (TREE_TYPE (val) != NULL_TREE
3123 && CH_IS_BUFFER_MODE (TREE_TYPE (val)))
3124 return val;
3125 val = parse_call (val);
3126 continue;
3127 case STRING:
3128 case BITSTRING:
3129 case SINGLECHAR:
3130 case NAME:
3131 /* Handle string repetition. (See comment in parse_operand5.) */
3132 args = parse_primval ();
3133 val = ignoring ? val : build_generalized_call (val, args);
3134 continue;
3135 default:
3136 break;
3137 }
3138 break;
3139 }
3140 return val;
3141 }
3142
3143 static tree
3144 parse_operand6 ()
3145 {
3146 if (check_token (RECEIVE))
3147 {
3148 tree location = parse_primval ();
3149 sorry ("RECEIVE expression");
3150 return integer_one_node;
3151 }
3152 else if (check_token (ARROW))
3153 {
3154 tree location = parse_primval ();
3155 return ignoring ? location : build_chill_arrow_expr (location, 0);
3156 }
3157 else
3158 return parse_primval();
3159 }
3160
3161 static tree
3162 parse_operand5()
3163 {
3164 enum tree_code op;
3165 /* We are supposed to be looking for a <string repetition operator>,
3166 but in general we can't distinguish that from a parenthesized
3167 expression. This is especially difficult if we allow the
3168 string operand to be a constant expression (as requested by
3169 some users), and not just a string literal.
3170 Consider: LPRN expr RPRN LPRN expr RPRN
3171 Is that a function call or string repetition?
3172 Instead, we handle string repetition in parse_primval,
3173 and build_generalized_call. */
3174 tree rarg;
3175 switch (PEEK_TOKEN())
3176 {
3177 case NOT: op = BIT_NOT_EXPR; break;
3178 case SUB: op = NEGATE_EXPR; break;
3179 default:
3180 op = NOP_EXPR;
3181 }
3182 if (op != NOP_EXPR)
3183 FORWARD_TOKEN();
3184 rarg = parse_operand6();
3185 return (op == NOP_EXPR || ignoring) ? rarg
3186 : build_chill_unary_op (op, rarg);
3187 }
3188
3189 static tree
3190 parse_operand4 ()
3191 {
3192 tree larg = parse_operand5(), rarg;
3193 enum tree_code op;
3194 for (;;)
3195 {
3196 switch (PEEK_TOKEN())
3197 {
3198 case MUL: op = MULT_EXPR; break;
3199 case DIV: op = TRUNC_DIV_EXPR; break;
3200 case MOD: op = FLOOR_MOD_EXPR; break;
3201 case REM: op = TRUNC_MOD_EXPR; break;
3202 default:
3203 return larg;
3204 }
3205 FORWARD_TOKEN();
3206 rarg = parse_operand5();
3207 if (!ignoring)
3208 larg = build_chill_binary_op (op, larg, rarg);
3209 }
3210 }
3211
3212 static tree
3213 parse_operand3 ()
3214 {
3215 tree larg = parse_operand4 (), rarg;
3216 enum tree_code op;
3217 for (;;)
3218 {
3219 switch (PEEK_TOKEN())
3220 {
3221 case PLUS: op = PLUS_EXPR; break;
3222 case SUB: op = MINUS_EXPR; break;
3223 case CONCAT: op = CONCAT_EXPR; break;
3224 default:
3225 return larg;
3226 }
3227 FORWARD_TOKEN();
3228 rarg = parse_operand4();
3229 if (!ignoring)
3230 larg = build_chill_binary_op (op, larg, rarg);
3231 }
3232 }
3233
3234 static tree
3235 parse_operand2 ()
3236 {
3237 tree larg = parse_operand3 (), rarg;
3238 enum tree_code op;
3239 for (;;)
3240 {
3241 if (check_token (IN))
3242 {
3243 rarg = parse_operand3();
3244 if (! ignoring)
3245 larg = build_chill_binary_op (SET_IN_EXPR, larg, rarg);
3246 }
3247 else
3248 {
3249 switch (PEEK_TOKEN())
3250 {
3251 case GT: op = GT_EXPR; break;
3252 case GTE: op = GE_EXPR; break;
3253 case LT: op = LT_EXPR; break;
3254 case LTE: op = LE_EXPR; break;
3255 case EQL: op = EQ_EXPR; break;
3256 case NE: op = NE_EXPR; break;
3257 default:
3258 return larg;
3259 }
3260 FORWARD_TOKEN();
3261 rarg = parse_operand3();
3262 if (!ignoring)
3263 larg = build_compare_expr (op, larg, rarg);
3264 }
3265 }
3266 }
3267
3268 static tree
3269 parse_operand1 ()
3270 {
3271 tree larg = parse_operand2 (), rarg;
3272 enum tree_code op;
3273 for (;;)
3274 {
3275 switch (PEEK_TOKEN())
3276 {
3277 case AND: op = BIT_AND_EXPR; break;
3278 case ANDIF: op = TRUTH_ANDIF_EXPR; break;
3279 default:
3280 return larg;
3281 }
3282 FORWARD_TOKEN();
3283 rarg = parse_operand2();
3284 if (!ignoring)
3285 larg = build_chill_binary_op (op, larg, rarg);
3286 }
3287 }
3288
3289 static tree
3290 parse_operand0 ()
3291 {
3292 tree larg = parse_operand1(), rarg;
3293 enum tree_code op;
3294 for (;;)
3295 {
3296 switch (PEEK_TOKEN())
3297 {
3298 case OR: op = BIT_IOR_EXPR; break;
3299 case XOR: op = BIT_XOR_EXPR; break;
3300 case ORIF: op = TRUTH_ORIF_EXPR; break;
3301 default:
3302 return larg;
3303 }
3304 FORWARD_TOKEN();
3305 rarg = parse_operand1();
3306 if (!ignoring)
3307 larg = build_chill_binary_op (op, larg, rarg);
3308 }
3309 }
3310
3311 static tree
3312 parse_expression ()
3313 {
3314 return parse_operand0 ();
3315 }
3316
3317 static tree
3318 parse_case_expression ()
3319 {
3320 tree selector_list;
3321 tree else_expr;
3322 tree case_expr;
3323 tree case_alt_list = NULL_TREE;
3324
3325 require (CASE);
3326 selector_list = parse_expr_list ();
3327 selector_list = nreverse (selector_list);
3328
3329 expect (OF, "missing 'OF'");
3330 while (PEEK_TOKEN () == LPRN)
3331 {
3332 tree label_spec = parse_case_label_specification (selector_list);
3333 tree sub_expr;
3334 expect (COLON, "missing ':' in value case alternative");
3335 sub_expr = parse_expression ();
3336 expect (SC, "missing ';'");
3337 if (! ignoring)
3338 case_alt_list = tree_cons (label_spec, sub_expr, case_alt_list);
3339 }
3340 if (check_token (ELSE))
3341 {
3342 else_expr = parse_expression ();
3343 if (check_token (SC) && pass == 1)
3344 warning("there should not be a ';' here");
3345 }
3346 else
3347 else_expr = NULL_TREE;
3348 expect (ESAC, "missing 'ESAC' in 'CASE' expression");
3349
3350 if (ignoring)
3351 return integer_zero_node;
3352
3353 /* If this is a multi dimension case, then transform it into an COND_EXPR
3354 here. This must be done before store_expr is called since it has some
3355 special handling for COND_EXPR expressions. */
3356 if (TREE_CHAIN (selector_list) != NULL_TREE)
3357 {
3358 case_alt_list = nreverse (case_alt_list);
3359 compute_else_ranges (selector_list, case_alt_list);
3360 case_expr =
3361 build_chill_multi_dimension_case_expr (selector_list, case_alt_list, else_expr);
3362 }
3363 else
3364 case_expr = build_chill_case_expr (selector_list, case_alt_list, else_expr);
3365
3366 return case_expr;
3367 }
3368
3369 static tree
3370 parse_then_alternative ()
3371 {
3372 expect (THEN, "missing 'THEN' in 'IF' expression");
3373 return parse_expression ();
3374 }
3375
3376 static tree
3377 parse_else_alternative ()
3378 {
3379 if (check_token (ELSIF))
3380 return parse_if_expression_body ();
3381 else if (check_token (ELSE))
3382 return parse_expression ();
3383 error ("missing ELSE/ELSIF in IF expression");
3384 return error_mark_node;
3385 }
3386
3387 /* Matches: <boolean expression> <then alternative> <else alternative> */
3388
3389 static tree
3390 parse_if_expression_body ()
3391 {
3392 tree bool_expr, then_expr, else_expr;
3393 bool_expr = parse_expression ();
3394 then_expr = parse_then_alternative ();
3395 else_expr = parse_else_alternative ();
3396 if (ignoring)
3397 return integer_zero_node;
3398 else
3399 return build_nt (COND_EXPR, bool_expr, then_expr, else_expr);
3400 }
3401
3402 static tree
3403 parse_if_expression ()
3404 {
3405 tree expr;
3406 require (IF);
3407 expr = parse_if_expression_body ();
3408 expect (FI, "missing 'FI' at end of conditional expression");
3409 return expr;
3410 }
3411
3412 /* An <untyped_expr> is a superset of <expr>. It also includes
3413 <conditional expressions> and untyped <tuples>, whose types
3414 are not given by their constituents. Hence, these are only
3415 allowed in certain contexts that expect a certain type.
3416 You should call convert() to fix up the <untyped_expr>. */
3417
3418 static tree
3419 parse_untyped_expr ()
3420 {
3421 tree val;
3422 switch (PEEK_TOKEN())
3423 {
3424 case IF:
3425 return parse_if_expression ();
3426 case CASE:
3427 return parse_case_expression ();
3428 case LPRN:
3429 switch (PEEK_TOKEN1())
3430 {
3431 case IF:
3432 case CASE:
3433 if (pass == 1)
3434 pedwarn ("conditional expression not allowed inside parentheses");
3435 goto skip_lprn;
3436 case LPC:
3437 if (pass == 1)
3438 pedwarn ("mode-less tuple not allowed inside parentheses");
3439 skip_lprn:
3440 FORWARD_TOKEN ();
3441 val = parse_untyped_expr ();
3442 expect (RPRN, "missing ')'");
3443 return val;
3444 default: ;
3445 /* fall through */
3446 }
3447 default:
3448 return parse_operand0 ();
3449 }
3450 }
3451
3452 /* Matches: <index mode> */
3453
3454 static tree
3455 parse_index_mode ()
3456 {
3457 /* This is another one that is nasty to parse!
3458 Let's feel our way ahead ... */
3459 tree lower, upper;
3460 if (PEEK_TOKEN () == NAME)
3461 {
3462 tree name = parse_name ();
3463 switch (PEEK_TOKEN ())
3464 {
3465 case COMMA:
3466 case RPRN:
3467 case SC: /* An error */
3468 /* This can only (legally) be a discrete mode name. */
3469 return name;
3470 case LPRN:
3471 /* This could be named discrete range,
3472 a cast, or some other expression (maybe). */
3473 require (LPRN);
3474 lower = parse_expression ();
3475 if (check_token (COLON))
3476 {
3477 upper = parse_expression ();
3478 expect (RPRN, "missing ')'");
3479 /* Matched: <mode_name> '(' <expr> ':' <expr> ')' */
3480 if (ignoring)
3481 return NULL_TREE;
3482 else
3483 return build_chill_range_type (name, lower, upper);
3484 }
3485 /* Looks like a cast or procedure call or something.
3486 Backup, and try again. */
3487 pushback_token (EXPR, lower);
3488 pushback_token (LPRN, NULL_TREE);
3489 lower = parse_call (name);
3490 goto parse_literal_range_colon;
3491 default:
3492 /* This has to be the start of an expression. */
3493 pushback_token (EXPR, name);
3494 goto parse_literal_range;
3495 }
3496 }
3497 /* It's not a name. But it could still be a discrete mode. */
3498 lower = parse_opt_mode ();
3499 if (lower)
3500 return lower;
3501 parse_literal_range:
3502 /* Nope, it's a discrete literal range. */
3503 lower = parse_expression ();
3504 parse_literal_range_colon:
3505 expect (COLON, "expected ':' here");
3506
3507 upper = parse_expression ();
3508 return ignoring ? NULL_TREE
3509 : build_chill_range_type (NULL_TREE, lower, upper);
3510 }
3511
3512 static tree
3513 parse_set_mode ()
3514 {
3515 int set_name_cnt = 0; /* count of named set elements */
3516 int set_is_numbered = 0; /* TRUE if set elements have explicit values */
3517 int set_is_not_numbered = 0;
3518 tree list = NULL_TREE;
3519 tree mode = ignoring ? void_type_node : start_enum (NULL_TREE);
3520 require (SET);
3521 expect (LPRN, "missing left parenthesis after SET");
3522 for (;;)
3523 {
3524 tree name, value = NULL_TREE;
3525 if (check_token (MUL))
3526 name = NULL_TREE;
3527 else
3528 {
3529 name = parse_defining_occurrence ();
3530 if (check_token (EQL))
3531 {
3532 value = parse_expression ();
3533 set_is_numbered = 1;
3534 }
3535 else
3536 set_is_not_numbered = 1;
3537 set_name_cnt++;
3538 }
3539 name = build_enumerator (name, value);
3540 if (pass == 1)
3541 list = chainon (name, list);
3542 if (! check_token (COMMA))
3543 break;
3544 }
3545 expect (RPRN, "missing right parenthesis after SET");
3546 if (!ignoring)
3547 {
3548 if (set_is_numbered && set_is_not_numbered)
3549 /* Z.200 doesn't allow mixed numbered and unnumbered set elements,
3550 but we can do it. Print a warning */
3551 pedwarn ("mixed numbered and unnumbered set elements is not standard");
3552 mode = finish_enum (mode, list);
3553 if (set_name_cnt == 0)
3554 error ("SET mode must define at least one named value");
3555 CH_ENUM_IS_NUMBERED(mode) = set_is_numbered ? 1 : 0;
3556 }
3557 return mode;
3558 }
3559
3560 /* parse layout POS:
3561 returns a tree with following layout
3562
3563 treelist
3564 pupose=treelist value=NULL_TREE (to indicate POS)
3565 pupose=word value=treelist | NULL_TREE
3566 pupose=startbit value=treelist | NULL_TREE
3567 purpose= value=
3568 integer_zero | integer_one length | endbit
3569 */
3570 static tree
3571 parse_pos ()
3572 {
3573 tree word;
3574 tree startbit = NULL_TREE, endbit = NULL_TREE;
3575 tree what = NULL_TREE;
3576
3577 require (LPRN);
3578 word = parse_untyped_expr ();
3579 if (check_token (COMMA))
3580 {
3581 startbit = parse_untyped_expr ();
3582 if (check_token (COMMA))
3583 {
3584 what = integer_zero_node;
3585 endbit = parse_untyped_expr ();
3586 }
3587 else if (check_token (COLON))
3588 {
3589 what = integer_one_node;
3590 endbit = parse_untyped_expr ();
3591 }
3592 }
3593 require (RPRN);
3594
3595 /* build the tree as described above */
3596 if (what != NULL_TREE)
3597 what = tree_cons (what, endbit, NULL_TREE);
3598 if (startbit != NULL_TREE)
3599 startbit = tree_cons (startbit, what, NULL_TREE);
3600 endbit = tree_cons (word, startbit, NULL_TREE);
3601 return tree_cons (endbit, NULL_TREE, NULL_TREE);
3602 }
3603
3604 /* parse layout STEP
3605 returns a tree with the following layout
3606
3607 treelist
3608 pupose=NULL_TREE value=treelist (to indicate STEP)
3609 pupose=POS(see baove) value=stepsize | NULL_TREE
3610 */
3611 static tree
3612 parse_step ()
3613 {
3614 tree pos;
3615 tree stepsize = NULL_TREE;
3616
3617 require (LPRN);
3618 require (POS);
3619 pos = parse_pos ();
3620 if (check_token (COMMA))
3621 stepsize = parse_untyped_expr ();
3622 require (RPRN);
3623 TREE_VALUE (pos) = stepsize;
3624 return tree_cons (NULL_TREE, pos, NULL_TREE);
3625 }
3626
3627 /* returns layout for fields or array elements.
3628 NULL_TREE no layout specified
3629 integer_one_node PACK specified
3630 integer_zero_node NOPACK specified
3631 tree_list PURPOSE POS
3632 tree_list VALUE STEP
3633 */
3634 static tree
3635 parse_opt_layout (in)
3636 int in; /* 0 ... parse structure, 1 ... parse array */
3637 {
3638 tree val = NULL_TREE;
3639
3640 if (check_token (PACK))
3641 {
3642 return integer_one_node;
3643 }
3644 else if (check_token (NOPACK))
3645 {
3646 return integer_zero_node;
3647 }
3648 else if (check_token (POS))
3649 {
3650 val = parse_pos ();
3651 if (in == 1 && pass == 1)
3652 {
3653 error ("POS not allowed for ARRAY");
3654 val = NULL_TREE;
3655 }
3656 return val;
3657 }
3658 else if (check_token (STEP))
3659 {
3660 val = parse_step ();
3661 if (in == 0 && pass == 1)
3662 {
3663 error ("STEP not allowed in field definition");
3664 val = NULL_TREE;
3665 }
3666 return val;
3667 }
3668 else
3669 return NULL_TREE;
3670 }
3671
3672 static tree
3673 parse_field_name_list ()
3674 {
3675 tree chain = NULL_TREE;
3676 tree name = parse_defining_occurrence ();
3677 if (name == NULL_TREE)
3678 {
3679 error("missing field name");
3680 return NULL_TREE;
3681 }
3682 chain = build_tree_list (NULL_TREE, name);
3683 while (check_token (COMMA))
3684 {
3685 name = parse_defining_occurrence ();
3686 if (name == NULL)
3687 {
3688 error ("bad field name following ','");
3689 break;
3690 }
3691 if (! ignoring)
3692 chain = tree_cons (NULL_TREE, name, chain);
3693 }
3694 return chain;
3695 }
3696
3697 /* Matches: <fixed field> or <variant field>, i.e.:
3698 <field name defining occurrence list> <mode> [ <field layout> ].
3699 Returns: A chain of FIELD_DECLs.
3700 NULL_TREE is returned if ignoring is true or an error is seen. */
3701
3702 static tree
3703 parse_fixed_field ()
3704 {
3705 tree field_names = parse_field_name_list ();
3706 tree mode = parse_mode ();
3707 tree layout = parse_opt_layout (0);
3708 return ignoring ? NULL_TREE
3709 : grok_chill_fixedfields (field_names, mode, layout);
3710 }
3711
3712
3713 /* Matches: [ <variant field> { "," <variant field> }* ]
3714 Returns: A chain of FIELD_DECLs.
3715 NULL_TREE is returned if ignoring is true or an error is seen. */
3716
3717 static tree
3718 parse_variant_field_list ()
3719 {
3720 tree fields = NULL_TREE;
3721 if (PEEK_TOKEN () != NAME)
3722 return NULL_TREE;
3723 for (;;)
3724 {
3725 fields = chainon (fields, parse_fixed_field ());
3726 if (PEEK_TOKEN () != COMMA || PEEK_TOKEN1 () != NAME)
3727 break;
3728 require (COMMA);
3729 }
3730 return fields;
3731 }
3732
3733 /* Matches: <variant alternative>
3734 Returns a TREE_LIST node, whose TREE_PURPOSE (if non-NULL) is the label,
3735 and whose TREE_VALUE is the list of FIELD_DECLs. */
3736
3737 static tree
3738 parse_variant_alternative ()
3739 {
3740 tree labels;
3741
3742 if (PEEK_TOKEN () == LPRN)
3743 labels = parse_case_label_specification (NULL_TREE);
3744 else
3745 labels = NULL_TREE;
3746 if (! check_token (COLON))
3747 {
3748 error ("expected ':' in structure variant alternative");
3749 return NULL_TREE;
3750 }
3751
3752 /* We now read a list a variant fields, until we come to the end
3753 of the variant alternative. But since both variant fields
3754 *and* variant alternatives are separated by COMMAs,
3755 we will have to look ahead to distinguish the start of a variant
3756 field from the start of a new variant alternative.
3757 We use the fact that a variant alternative must start with
3758 either a LPRN or a COLON, while a variant field must start with a NAME.
3759 This look-ahead is handled by parse_simple_fields. */
3760 return build_tree_list (labels, parse_variant_field_list ());
3761 }
3762
3763 /* Parse <field> (which is <fixed field> or <alternative field>).
3764 Returns: A chain of FIELD_DECLs (or NULL_TREE on error or if ignoring). */
3765
3766 static tree
3767 parse_field ()
3768 {
3769 if (check_token (CASE))
3770 {
3771 tree tag_list = NULL_TREE, variants, opt_variant_else;
3772 if (PEEK_TOKEN () == NAME)
3773 {
3774 tag_list = nreverse (parse_field_name_list ());
3775 if (pass == 1)
3776 tag_list = lookup_tag_fields (tag_list, current_fieldlist);
3777 }
3778 expect (OF, "missing 'OF' in alternative structure field");
3779
3780 variants = parse_variant_alternative ();
3781 while (check_token (COMMA))
3782 variants = chainon (parse_variant_alternative (), variants);
3783 variants = nreverse (variants);
3784
3785 if (check_token (ELSE))
3786 opt_variant_else = parse_variant_field_list ();
3787 else
3788 opt_variant_else = NULL_TREE;
3789 expect (ESAC, "missing 'ESAC' following alternative structure field");
3790 if (ignoring)
3791 return NULL_TREE;
3792 return grok_chill_variantdefs (tag_list, variants, opt_variant_else);
3793 }
3794 else if (PEEK_TOKEN () == NAME)
3795 return parse_fixed_field ();
3796 else
3797 {
3798 if (pass == 1)
3799 error ("missing field");
3800 return NULL_TREE;
3801 }
3802 }
3803
3804 static tree
3805 parse_structure_mode ()
3806 {
3807 tree save_fieldlist = current_fieldlist;
3808 tree fields;
3809 require (STRUCT);
3810 expect (LPRN, "expected '(' after STRUCT");
3811 current_fieldlist = fields = parse_field ();
3812 while (check_token (COMMA))
3813 fields = chainon (fields, parse_field ());
3814 expect (RPRN, "expected ')' after STRUCT");
3815 current_fieldlist = save_fieldlist;
3816 return ignoring ? void_type_node : build_chill_struct_type (fields);
3817 }
3818
3819 static tree
3820 parse_opt_queue_size ()
3821 {
3822 if (check_token (LPRN))
3823 {
3824 tree size = parse_expression ();
3825 expect (RPRN, "missing ')'");
3826 return size;
3827 }
3828 else
3829 return NULL_TREE;
3830 }
3831
3832 static tree
3833 parse_procedure_mode ()
3834 {
3835 tree param_types = NULL_TREE, result_spec, except_list, recursive;
3836 require (PROC);
3837 expect (LPRN, "missing '(' after PROC");
3838 if (! check_token (RPRN))
3839 {
3840 for (;;)
3841 {
3842 tree pmode = parse_mode ();
3843 tree paramattr = parse_param_attr ();
3844 if (! ignoring)
3845 {
3846 pmode = get_type_of (pmode);
3847 param_types = tree_cons (paramattr, pmode, param_types);
3848 }
3849 if (! check_token (COMMA))
3850 break;
3851 }
3852 expect (RPRN, "missing ')' after PROC");
3853 }
3854 result_spec = parse_opt_result_spec ();
3855 except_list = parse_opt_except ();
3856 recursive = parse_opt_recursive ();
3857 if (ignoring)
3858 return void_type_node;
3859 return build_chill_pointer_type (build_chill_function_type
3860 (result_spec, nreverse (param_types),
3861 except_list, recursive));
3862 }
3863
3864 /* Matches: <mode>
3865 A NAME will be assumed to be a <mode name>, and thus a <mode>.
3866 Returns NULL_TREE if no mode is seen.
3867 (If ignoring is true, the return value may be an arbitrary tree node,
3868 but will be non-NULL if something that could be a mode is seen.) */
3869
3870 static tree
3871 parse_opt_mode ()
3872 {
3873 switch (PEEK_TOKEN ())
3874 {
3875 case ACCESS:
3876 {
3877 tree index_mode, record_mode;
3878 int dynamic = 0;
3879 require (ACCESS);
3880 if (check_token (LPRN))
3881 {
3882 index_mode = parse_index_mode ();
3883 expect (RPRN, "mssing ')'");
3884 }
3885 else
3886 index_mode = NULL_TREE;
3887 record_mode = parse_opt_mode ();
3888 if (record_mode)
3889 dynamic = check_token (DYNAMIC);
3890 return ignoring ? void_type_node
3891 : build_access_mode (index_mode, record_mode, dynamic);
3892 }
3893 case ARRAY:
3894 {
3895 tree index_list = NULL_TREE, base_mode;
3896 int varying;
3897 int num_index_modes = 0;
3898 int i;
3899 tree layouts = NULL_TREE;
3900 FORWARD_TOKEN ();
3901 expect (LPRN, "missing '(' after ARRAY");
3902 for (;;)
3903 {
3904 tree index = parse_index_mode ();
3905 num_index_modes++;
3906 if (!ignoring)
3907 index_list = tree_cons (NULL_TREE, index, index_list);
3908 if (! check_token (COMMA))
3909 break;
3910 }
3911 expect (RPRN, "missing ')' after ARRAY");
3912 varying = check_token (VARYING);
3913 base_mode = parse_mode ();
3914 /* Allow a layout specification for each index mode */
3915 for (i = 0; i < num_index_modes; ++i)
3916 {
3917 tree new_layout = parse_opt_layout (1);
3918 if (new_layout == NULL_TREE)
3919 break;
3920 if (!ignoring)
3921 layouts = tree_cons (NULL_TREE, new_layout, layouts);
3922 }
3923 if (ignoring)
3924 return base_mode;
3925 return build_chill_array_type (get_type_of (base_mode),
3926 index_list, varying, layouts);
3927 }
3928 case ASSOCIATION:
3929 require (ASSOCIATION);
3930 return association_type_node;
3931 case BIN:
3932 { tree length;
3933 FORWARD_TOKEN();
3934 expect (LPRN, "missing left parenthesis after BIN");
3935 length = parse_expression ();
3936 expect (RPRN, "missing right parenthesis after BIN");
3937 return ignoring ? void_type_node : build_chill_bin_type (length);
3938 }
3939 case BOOLS:
3940 {
3941 tree length;
3942 FORWARD_TOKEN ();
3943 expect (LPRN, "missing '(' after BOOLS");
3944 length = parse_expression ();
3945 expect (RPRN, "missing ')' after BOOLS");
3946 if (check_token (VARYING))
3947 error ("VARYING bit-strings not implemented");
3948 return ignoring ? void_type_node : build_bitstring_type (length);
3949 }
3950 case BUFFER:
3951 {
3952 tree qsize, element_mode;
3953 require (BUFFER);
3954 qsize = parse_opt_queue_size ();
3955 element_mode = parse_mode ();
3956 return ignoring ? element_mode
3957 : build_buffer_type (element_mode, qsize);
3958 }
3959 case CHARS:
3960 {
3961 tree length;
3962 int varying;
3963 tree type;
3964 FORWARD_TOKEN ();
3965 expect (LPRN, "missing '(' after CHARS");
3966 length = parse_expression ();
3967 expect (RPRN, "missing ')' after CHARS");
3968 varying = check_token (VARYING);
3969 if (ignoring)
3970 return void_type_node;
3971 type = build_string_type (char_type_node, length);
3972 if (varying)
3973 type = build_varying_struct (type);
3974 return type;
3975 }
3976 case EVENT:
3977 {
3978 tree qsize;
3979 require (EVENT);
3980 qsize = parse_opt_queue_size ();
3981 return ignoring ? void_type_node : build_event_type (qsize);
3982 }
3983 case NAME:
3984 {
3985 tree mode = get_type_of (parse_name ());
3986 if (check_token (LPRN))
3987 {
3988 tree min_value = parse_expression ();
3989 if (check_token (COLON))
3990 {
3991 tree max_value = parse_expression ();
3992 expect (RPRN, "syntax error - expected ')'");
3993 /* Matched: <mode_name> '(' <expr> ':' <expr> ')' */
3994 if (ignoring)
3995 return mode;
3996 else
3997 return build_chill_range_type (mode, min_value, max_value);
3998 }
3999 if (check_token (RPRN))
4000 {
4001 int varying = check_token (VARYING);
4002 if (! ignoring)
4003 {
4004 if (mode == char_type_node || varying)
4005 {
4006 if (mode != char_type_node
4007 && mode != ridpointers[(int) RID_CHAR])
4008 error ("strings must be composed of chars");
4009 mode = build_string_type (char_type_node, min_value);
4010 if (varying)
4011 mode = build_varying_struct (mode);
4012 }
4013 else
4014 {
4015 /* Parameterized mode,
4016 or old-fashioned CHAR(N) string declaration.. */
4017 tree pmode = make_node (LANG_TYPE);
4018 TREE_TYPE (pmode) = mode;
4019 TYPE_DOMAIN (pmode) = min_value;
4020 mode = pmode;
4021 }
4022 }
4023 }
4024 }
4025 return mode;
4026 }
4027 case POWERSET:
4028 { tree mode;
4029 FORWARD_TOKEN ();
4030 mode = parse_mode ();
4031 if (ignoring || TREE_CODE (mode) == ERROR_MARK)
4032 return mode;
4033 return build_powerset_type (get_type_of (mode));
4034 }
4035 case PROC:
4036 return parse_procedure_mode ();
4037 case RANGE:
4038 { tree low, high;
4039 FORWARD_TOKEN();
4040 expect (LPRN, "missing left parenthesis after RANGE");
4041 low = parse_expression ();
4042 expect (COLON, "missing colon");
4043 high = parse_expression ();
4044 expect (RPRN, "missing right parenthesis after RANGE");
4045 return ignoring ? void_type_node
4046 : build_chill_range_type (NULL_TREE, low, high);
4047 }
4048 case READ:
4049 FORWARD_TOKEN ();
4050 {
4051 tree mode2 = get_type_of (parse_mode ());
4052 if (ignoring || TREE_CODE (mode2) == ERROR_MARK)
4053 return mode2;
4054 if (mode2
4055 && TREE_CODE_CLASS (TREE_CODE (mode2)) == 'd'
4056 && CH_IS_BUFFER_MODE (mode2))
4057 {
4058 error ("BUFFER modes may not be readonly");
4059 return mode2;
4060 }
4061 if (mode2
4062 && TREE_CODE_CLASS (TREE_CODE (mode2)) == 'd'
4063 && CH_IS_EVENT_MODE (mode2))
4064 {
4065 error ("EVENT modes may not be readonly");
4066 return mode2;
4067 }
4068 return build_readonly_type (mode2);
4069
4070 }
4071 case REF:
4072 { tree mode;
4073 FORWARD_TOKEN ();
4074 mode = parse_mode ();
4075 if (ignoring)
4076 return mode;
4077 mode = get_type_of (mode);
4078 return (TREE_CODE (mode) == ERROR_MARK) ? mode
4079 : build_chill_pointer_type (mode);
4080 }
4081 case SET:
4082 return parse_set_mode ();
4083 case SIGNAL:
4084 if (pedantic)
4085 error ("SIGNAL is not a valid mode");
4086 return generic_signal_type_node;
4087 case STRUCT:
4088 return parse_structure_mode ();
4089 case TEXT:
4090 {
4091 tree length, index_mode;
4092 int dynamic;
4093 require (TEXT);
4094 expect (LPRN, "missing '('");
4095 length = parse_expression ();
4096 expect (RPRN, "missing ')'");
4097 /* FIXME: This should actually look for an optional index_mode,
4098 but that is tricky to do. */
4099 index_mode = parse_opt_mode ();
4100 dynamic = check_token (DYNAMIC);
4101 return ignoring ? void_type_node
4102 : build_text_mode (length, index_mode, dynamic);
4103 }
4104 case USAGE:
4105 require (USAGE);
4106 return usage_type_node;
4107 case WHERE:
4108 require (WHERE);
4109 return where_type_node;
4110 default:
4111 return NULL_TREE;
4112 }
4113 }
4114
4115 static tree
4116 parse_mode ()
4117 {
4118 tree mode = parse_opt_mode ();
4119 if (mode == NULL_TREE)
4120 {
4121 if (pass == 1)
4122 error ("syntax error - missing mode");
4123 mode = error_mark_node;
4124 }
4125 return mode;
4126 }
4127
4128 static void
4129 parse_program()
4130 {
4131 /* Initialize global variables for current pass. */
4132 int i;
4133 expand_exit_needed = 0;
4134 label = NULL_TREE; /* for statement labels */
4135 current_module = NULL;
4136 current_function_decl = NULL_TREE;
4137 in_pseudo_module = 0;
4138
4139 for (i = 0; i <= MAX_LOOK_AHEAD; i++)
4140 terminal_buffer[i] = TOKEN_NOT_READ;
4141
4142 #if 0
4143 /* skip some junk */
4144 while (PEEK_TOKEN() == HEADEREL)
4145 FORWARD_TOKEN();
4146 #endif
4147
4148 start_outer_function ();
4149
4150 for (;;)
4151 {
4152 tree label = parse_optlabel ();
4153 if (PEEK_TOKEN() == MODULE || PEEK_TOKEN() == REGION)
4154 parse_modulion (label);
4155 else if (PEEK_TOKEN() == SPEC)
4156 parse_spec_module (label);
4157 else break;
4158 }
4159
4160 finish_outer_function ();
4161 }
4162
4163 void
4164 parse_pass_1_2()
4165 {
4166 parse_program();
4167 if (PEEK_TOKEN() != END_PASS_1)
4168 {
4169 error ("syntax error - expected a module or end of file");
4170 serious_errors++;
4171 }
4172 chill_finish_compile ();
4173 if (serious_errors)
4174 exit (FATAL_EXIT_CODE);
4175 switch_to_pass_2 ();
4176 ch_parse_init ();
4177 except_init_pass_2 ();
4178 ignoring = 0;
4179 parse_program();
4180 chill_finish_compile ();
4181 }
4182
4183 int yyparse ()
4184 {
4185 parse_pass_1_2 ();
4186 return 0;
4187 }
4188
4189 /*
4190 * We've had an error. Move the compiler's state back to
4191 * the global binding level. This prevents the loop in
4192 * compile_file in toplev.c from looping forever, since the
4193 * CHILL poplevel() has *no* effect on the value returned by
4194 * global_bindings_p().
4195 */
4196 void
4197 to_global_binding_level ()
4198 {
4199 while (! global_bindings_p ())
4200 current_function_decl = DECL_CONTEXT (current_function_decl);
4201 serious_errors++;
4202 }
4203
4204 #if 1
4205 int yydebug;
4206 /* Sets the value of the 'yydebug' variable to VALUE.
4207 This is a function so we don't have to have YYDEBUG defined
4208 in order to build the compiler. */
4209 void
4210 set_yydebug (value)
4211 int value;
4212 {
4213 #if YYDEBUG != 0
4214 yydebug = value;
4215 #else
4216 warning ("YYDEBUG not defined.");
4217 #endif
4218 }
4219 #endif
This page took 0.210015 seconds and 6 git commands to generate.