]> gcc.gnu.org Git - gcc.git/blame - gcc/ch/parse.c
Fix FSF address in copyright header.
[gcc.git] / gcc / ch / parse.c
CommitLineData
3c79b2da 1/* Parser for GNU CHILL (CCITT High-Level Language) -*- C -*-
e511adc0 2 Copyright (C) 1992, 1993, 1998 Free Software Foundation, Inc.
3c79b2da
PB
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the 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
3c79b2da 43#include "config.h"
75111422 44#include "system.h"
3c79b2da
PB
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"
75111422 51#include "toplev.h"
3c79b2da
PB
52
53/* Since parsers are distinct for each language, put the
54 language string definition here. (fnf) */
55char *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
3c79b2da
PB
72extern struct rtx_def* gen_label_rtx PROTO((void));
73extern void emit_jump PROTO((struct rtx_def *));
c1daea12 74extern struct rtx_def* emit_label PROTO((struct rtx_def *));
3c79b2da 75
75111422 76static int parse_action PROTO((void));
3c79b2da
PB
77
78extern int lineno;
79extern char *input_filename;
80extern tree generic_signal_type_node;
81extern tree signal_code;
82extern int all_static_flag;
83extern int ignore_case;
84
75111422 85#if 0
3c79b2da 86static int quasi_signal = 0; /* 1 if processing a quasi signal decl */
75111422 87#endif
3c79b2da
PB
88
89int parsing_newmode; /* 0 while parsing SYNMODE;
90 1 while parsing NEWMODE. */
91int expand_exit_needed = 0;
92
93/* Gets incremented if we see errors such that we don't want to run pass 2. */
94
95int serious_errors = 0;
96
97static 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. */
102int ignoring = 1; /* 1 to ignore expressions */
103
104/* True if we have seen an action not in a (user) function. */
105int seen_action = 0;
106int build_constructor = 0;
107
108/* The action_nesting_level of the current procedure body. */
109int 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! */
114static tree label = NULL_TREE; /* for statement labels */
115
116#if 0
117static tree current_block;
118#endif
119
120int in_pseudo_module = 0;
121int 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 */
125static void
126ch_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
134static void
135check_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 */
156tree
157get_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
184static void
185end_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
216static tree
217build_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
232void
233possibly_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
241static enum terminal terminal_buffer[MAX_LOOK_AHEAD+1];
242YYSTYPE yylval;
243static 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
75111422 252static enum terminal
3c79b2da
PB
253PEEK_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)
265static int
266peek_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
279static void
280pushback_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
296static void
297forward_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
312void
313require(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
325int
326check_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*/
338int
339expect(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 */
357static void
358define__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. */
375static tree parse_expression ();
376static tree parse_primval ();
377static tree parse_mode PROTO((void));
378static tree parse_opt_mode PROTO((void));
379static tree parse_untyped_expr ();
380static tree parse_opt_untyped_expr ();
381static int parse_definition PROTO((int));
382static void parse_opt_actions ();
383static void parse_body PROTO((void));
384static tree parse_if_expression_body PROTO((void));
385static tree parse_opt_handler PROTO((void));
386
387static tree
388parse_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
425static tree
426parse_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
440static tree
441parse_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
451static tree
452parse_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
467static tree
468parse_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
492static tree
493parse_optlabel()
494{
495 tree label = parse_defining_occurrence();
496 if (label != NULL)
497 expect(COLON, "expected a ':' here");
498 return label;
499}
500
501static void
502parse_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
512static void
513parse_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
3c79b2da
PB
524static void
525parse_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
543static void
544parse_spec_module (label)
545 tree label;
546{
3c79b2da 547 int save_ignoring = ignoring;
12fe4621
KG
548
549 push_module (set_module_name (label), 1);
3c79b2da
PB
550 ignoring = pass == 2;
551 FORWARD_TOKEN(); /* SKIP SPEC */
552 expect (MODULE, "expected 'MODULE' here");
553
554 while (parse_definition (1)) { }
555 if (parse_action ())
556 error ("action not allowed in SPEC MODULE");
557 expect(END, "expected END here");
558 parse_opt_end_label_semi_colon (label);
559 find_granted_decls ();
560 pop_module ();
561 ignoring = save_ignoring;
562}
563
564/* Matches: <name_string> ( "," <name_string> )*
565 Returns either a single IDENTIFIER_NODE,
566 or a chain (TREE_LIST) of IDENTIFIER_NODES.
567 (Since a single identifier is the common case, we avoid wasting space
568 (twice, once for each pass) with extra TREE_LIST nodes in that case.)
569 (Will not return NULL_TREE even if ignoring is true.) */
570
571static tree
572parse_defining_occurrence_list ()
573{
574 tree chain = NULL_TREE;
575 tree name = parse_defining_occurrence ();
576 if (name == NULL_TREE)
577 {
578 error("missing defining occurrence");
579 return NULL_TREE;
580 }
581 if (! check_token (COMMA))
582 return name;
583 chain = build_tree_list (NULL_TREE, name);
584 for (;;)
585 {
586 name = parse_defining_occurrence ();
587 if (name == NULL)
588 {
589 error ("bad defining occurrence following ','");
590 break;
591 }
592 chain = tree_cons (NULL_TREE, name, chain);
593 if (! check_token (COMMA))
594 break;
595 }
596 return nreverse (chain);
597}
598
599static void
600parse_mode_definition (is_newmode)
601 int is_newmode;
602{
603 tree mode, names;
604 int save_ignoring = ignoring;
605 ignoring = pass == 2;
606 names = parse_defining_occurrence_list ();
607 expect (EQL, "missing '=' in mode definition");
608 mode = parse_mode ();
609 if (names == NULL_TREE || TREE_CODE (names) == TREE_LIST)
610 {
611 for ( ; names != NULL_TREE; names = TREE_CHAIN (names))
612 push_modedef (names, mode, is_newmode);
613 }
614 else
615 push_modedef (names, mode, is_newmode);
616 ignoring = save_ignoring;
617}
618
619void
620parse_mode_definition_statement (is_newmode)
621 int is_newmode;
622{
3c79b2da
PB
623 FORWARD_TOKEN (); /* skip SYNMODE or NEWMODE */
624 parse_mode_definition (is_newmode);
625 while (PEEK_TOKEN () == COMMA)
626 {
627 FORWARD_TOKEN ();
628 parse_mode_definition (is_newmode);
629 }
630 parse_semi_colon ();
631}
632
633static void
634parse_synonym_definition ()
635{ tree expr = NULL_TREE;
636 tree names = parse_defining_occurrence_list ();
637 tree mode = parse_opt_mode ();
638 if (! expect (EQL, "missing '=' in synonym definition"))
639 mode = error_mark_node;
640 else
641 {
642 if (mode)
643 expr = parse_untyped_expr ();
644 else
645 expr = parse_expression ();
646 }
647 if (names == NULL_TREE || TREE_CODE (names) == TREE_LIST)
648 {
649 for ( ; names != NULL_TREE; names = TREE_CHAIN (names))
650 push_syndecl (names, mode, expr);
651 }
652 else
653 push_syndecl (names, mode, expr);
654}
655
656static void
657parse_synonym_definition_statement()
658{
659 int save_ignoring= ignoring;
660 ignoring = pass == 2;
661 require (SYN);
662 parse_synonym_definition ();
663 while (PEEK_TOKEN () == COMMA)
664 {
665 FORWARD_TOKEN ();
666 parse_synonym_definition ();
667 }
668 ignoring = save_ignoring;
669 parse_semi_colon ();
670}
671
672/* Attempts to match: "(" <exception list> ")" ":".
673 Return NULL_TREE on failure, and non-NULL on success.
674 On success, if pass 1, return a TREE_LIST of IDENTIFIER_NODEs. */
675
676static tree
677parse_on_exception_list ()
678{
679 tree name;
680 tree list = NULL_TREE;
681 int tok1 = PEEK_TOKEN ();
682 int tok2 = PEEK_TOKEN1 ();
683
684 /* This requires a lot of look-ahead, because we cannot
685 easily a priori distinguish an exception-list from an expression. */
686 if (tok1 != LPRN || tok2 != NAME)
687 {
688 if (tok1 == NAME && tok2 == COLON && pass == 1)
689 error ("missing '(' in exception list");
690 return 0;
691 }
692 require (LPRN);
693 name = parse_name_string ();
694 if (PEEK_TOKEN () == RPRN && PEEK_TOKEN1 () == COLON)
695 {
696 /* Matched: '(' <name_string> ')' ':' */
697 FORWARD_TOKEN (); FORWARD_TOKEN ();
698 return pass == 1 ? build_tree_list (NULL_TREE, name) : name;
699 }
700 if (PEEK_TOKEN() == COMMA)
701 {
702 if (pass == 1)
703 list = build_tree_list (NULL_TREE, name);
704 while (check_token (COMMA))
705 {
706 tree old_names = list;
707 name = parse_name_string ();
708 if (pass == 1)
709 {
710 for ( ; old_names != NULL_TREE; old_names = TREE_CHAIN (old_names))
711 {
712 if (TREE_VALUE (old_names) == name)
713 {
714 error ("ON exception names must be unique");
715 goto continue_parsing;
716 }
717 }
718 list = tree_cons (NULL_TREE, name, list);
719 continue_parsing:
720 ;
721 }
722 }
723 if (! check_token (RPRN) || ! check_token(COLON))
724 error ("syntax error in exception list");
725 return pass == 1 ? nreverse (list) : name;
726 }
727 /* Matched: '(' name_string
728 but it doesn't match the syntax of an exception list.
729 It could be the beginning of an expression, so back up. */
730 pushback_token (NAME, name);
731 pushback_token (LPRN, 0);
732 return NULL_TREE;
733}
734
735static void
736parse_on_alternatives ()
737{
738 for (;;)
739 {
740 tree except_list = parse_on_exception_list ();
741 if (except_list != NULL)
742 chill_handle_on_labels (except_list);
743 else if (parse_action ())
744 expand_exit_needed = 1;
745 else
746 break;
747 }
748}
749
750static tree
751parse_opt_handler ()
752{
753 if (! check_token (ON))
754 {
755 POP_UNUSED_ON_CONTEXT;
756 return NULL_TREE;
757 }
758 if (check_token (END))
759 {
760 pedwarn ("empty ON-condition");
761 POP_UNUSED_ON_CONTEXT;
762 return NULL_TREE;
763 }
764 if (! ignoring)
765 {
766 chill_start_on ();
767 expand_exit_needed = 0;
768 }
769 if (PEEK_TOKEN () != ELSE)
770 {
771 parse_on_alternatives ();
772 if (! ignoring && expand_exit_needed)
773 expand_exit_something ();
774 }
775 if (check_token (ELSE))
776 {
777 chill_start_default_handler ();
778 label = NULL_TREE;
779 parse_opt_actions ();
780 if (! ignoring)
781 {
782 emit_line_note (input_filename, lineno);
783 expand_exit_something ();
784 }
785 }
786 expect (END, "missing 'END' after");
787 if (! ignoring)
788 chill_finish_on ();
789 POP_USED_ON_CONTEXT;
790 return integer_zero_node;
791}
792
793static void
794parse_loc_declaration (in_spec_module)
795 int in_spec_module;
796{
797 tree names = parse_defining_occurrence_list ();
798 int save_ignoring = ignoring;
799 int is_static, lifetime_bound;
800 tree mode, init_value = NULL_TREE;
801 int loc_decl = 0;
802
803 ignoring = pass == 2;
804 mode = parse_mode ();
805 ignoring = save_ignoring;
806 is_static = check_token (STATIC);
807 if (check_token (BASED))
808 {
809 expect(LPRN, "BASED must be followed by (NAME)");
810 do_based_decls (names, mode, parse_name_string ());
811 expect(RPRN, "BASED must be followed by (NAME)");
812 return;
813 }
814 if (check_token (LOC))
815 {
816 /* loc-identity declaration */
817 if (pass == 1)
818 mode = build_chill_reference_type (mode);
819 loc_decl = 1;
820 }
821 lifetime_bound = check_token (INIT);
822 if (lifetime_bound && loc_decl)
823 {
824 if (pass == 1)
825 error ("INIT not allowed at loc-identity declaration");
826 lifetime_bound = 0;
827 }
828 if (PEEK_TOKEN () == ASGN || PEEK_TOKEN() == EQL)
829 {
830 save_ignoring = ignoring;
831 ignoring = pass == 1;
832 if (PEEK_TOKEN() == EQL)
833 {
834 if (pass == 1)
835 error ("'=' used where ':=' is required");
836 }
837 FORWARD_TOKEN();
838 if (! lifetime_bound)
839 push_handler ();
840 init_value = parse_untyped_expr ();
841 if (in_spec_module)
842 {
843 error ("initialization is not allowed in spec module");
844 init_value = NULL_TREE;
845 }
846 if (! lifetime_bound)
847 parse_opt_handler ();
848 ignoring = save_ignoring;
849 }
850 if (init_value == NULL_TREE && loc_decl && pass == 1)
851 error ("loc-identity declaration without initialisation");
852 do_decls (names, mode,
853 is_static || global_bindings_p ()
854 /* the variable becomes STATIC if all_static_flag is set and
855 current functions doesn't have the RECURSIVE attribute */
856 || (all_static_flag && !CH_DECL_RECURSIVE (current_function_decl)),
857 lifetime_bound, init_value, in_spec_module);
858
859 /* Free any temporaries we made while initializing the decl. */
860 free_temp_slots ();
861}
862
863static void
864parse_declaration_statement (in_spec_module)
865 int in_spec_module;
866{
867 int save_ignoring = ignoring;
868 ignoring = pass == 2;
869 require (DCL);
870 parse_loc_declaration (in_spec_module);
871 while (PEEK_TOKEN () == COMMA)
872 {
873 FORWARD_TOKEN ();
874 parse_loc_declaration (in_spec_module);
875 }
876 ignoring = save_ignoring;
877 parse_semi_colon ();
878}
879
880tree
881parse_optforbid ()
882{
883 if (check_token (FORBID) == 0)
884 return NULL_TREE;
885 if (check_token (ALL))
886 return ignoring ? NULL_TREE : build_int_2 (-1, -1);
887#if 0
888 if (check_token (LPRN))
889 {
890 tree list = parse_forbidlist ();
891 expect (RPRN, "missing ')' after FORBID list");
892 return list;
893 }
894#endif
895 error ("bad syntax following FORBID");
896 return NULL_TREE;
897}
898
899/* Matches: <grant postfix> or <seize postfix>
900 Returns: A (singleton) TREE_LIST. */
901
902tree
903parse_postfix (grant_or_seize)
904 enum terminal grant_or_seize;
905{
906 tree name = parse_opt_name_string (1);
907 tree forbid = NULL_TREE;
908 if (name == NULL_TREE)
909 {
910 error ("expected a postfix name here");
911 name = error_mark_node;
912 }
913 if (grant_or_seize == GRANT)
914 forbid = parse_optforbid ();
915 return build_tree_list (forbid, name);
916}
917
918tree
919parse_postfix_list (grant_or_seize)
920 enum terminal grant_or_seize;
921{
922 tree list = parse_postfix (grant_or_seize);
923 while (check_token (COMMA))
924 list = chainon (list, parse_postfix (grant_or_seize));
925 return list;
926}
927
928void
929parse_rename_clauses (grant_or_seize)
930 enum terminal grant_or_seize;
931{
932 for (;;)
933 {
934 tree rename_old_prefix, rename_new_prefix, postfix;
935 require (LPRN);
936 rename_old_prefix = parse_opt_name_string (0);
937 expect (ARROW, "missing '->' in rename clause");
938 rename_new_prefix = parse_opt_name_string (0);
939 expect (RPRN, "missing ')' in rename clause");
940 expect ('!', "missing '!' in rename clause");
941 postfix = parse_postfix (grant_or_seize);
942
943 if (grant_or_seize == GRANT)
944 chill_grant (rename_old_prefix, rename_new_prefix,
945 TREE_VALUE (postfix), TREE_PURPOSE (postfix));
946 else
947 chill_seize (rename_old_prefix, rename_new_prefix,
948 TREE_VALUE (postfix));
949
950 if (PEEK_TOKEN () != COMMA)
951 break;
952 FORWARD_TOKEN ();
953 if (PEEK_TOKEN () != LPRN)
954 {
955 error ("expected another rename clause");
956 break;
957 }
958 }
959}
960
961static tree
962parse_opt_prefix_clause ()
963{
964 if (check_token (PREFIXED) == 0)
965 return NULL_TREE;
966 return build_prefix_clause (parse_opt_name_string (0));
967}
968
969void
970parse_grant_statement ()
971{
972 require (GRANT);
973 if (PEEK_TOKEN () == LPRN)
974 parse_rename_clauses (GRANT);
975 else
976 {
977 tree window = parse_postfix_list (GRANT);
978 tree new_prefix = parse_opt_prefix_clause ();
979 tree t;
980 for (t = window; t; t = TREE_CHAIN (t))
981 chill_grant (NULL_TREE, new_prefix, TREE_VALUE (t), TREE_PURPOSE (t));
982 }
983}
984
985void
986parse_seize_statement ()
987{
988 require (SEIZE);
989 if (PEEK_TOKEN () == LPRN)
990 parse_rename_clauses (SEIZE);
991 else
992 {
993 tree seize_window = parse_postfix_list (SEIZE);
994 tree old_prefix = parse_opt_prefix_clause ();
995 tree t;
996 for (t = seize_window; t; t = TREE_CHAIN (t))
997 chill_seize (old_prefix, NULL_TREE, TREE_VALUE (t));
998 }
999}
1000
1001/* In pass 1, this returns a TREE_LIST, one node for each parameter.
1002 In pass 2, we get a list of PARM_DECLs chained together.
1003 In either case, the list is in reverse order. */
1004
1005static tree
1006parse_param_name_list ()
1007{
1008 tree list = NULL_TREE;
1009 do
1010 {
1011 tree new_link;
1012 tree name = parse_defining_occurrence ();
1013 if (name == NULL_TREE)
1014 {
1015 error ("syntax error in parameter name list");
1016 return list;
1017 }
1018 if (pass == 1)
1019 new_link = build_tree_list (NULL_TREE, name);
1020 /* else if (current_module->is_spec_module) ; nothing */
1021 else /* pass == 2 */
1022 {
1023 new_link = make_node (PARM_DECL);
1024 DECL_NAME (new_link) = name;
1025 DECL_ASSEMBLER_NAME (new_link) = name;
1026 }
1027
1028 TREE_CHAIN (new_link) = list;
1029 list = new_link;
1030 } while (check_token (COMMA));
1031 return list;
1032}
1033
1034static tree
1035parse_param_attr ()
1036{
1037 tree attr;
1038 switch (PEEK_TOKEN ())
1039 {
1040 case PARAMATTR: /* INOUT is returned here */
1041 attr = PEEK_TREE ();
1042 FORWARD_TOKEN ();
1043 return attr;
1044 case IN:
1045 FORWARD_TOKEN ();
1046 return ridpointers[(int) RID_IN];
1047 case LOC:
1048 FORWARD_TOKEN ();
1049 return ridpointers[(int) RID_LOC];
1050#if 0
1051 case DYNAMIC:
1052 FORWARD_TOKEN ();
1053 return ridpointers[(int) RID_DYNAMIC];
1054#endif
1055 default:
1056 return NULL_TREE;
1057 }
1058}
1059
1060/* We wrap CHILL array parameters in a STRUCT. The original parameter
1061 name is unpacked from the struct at get_identifier time */
1062
1063/* In pass 1, returns list of types; in pass 2: chain of PARM_DECLs. */
1064
1065static tree
75111422 1066parse_formpar ()
3c79b2da
PB
1067{
1068 tree names = parse_param_name_list ();
1069 tree mode = parse_mode ();
1070 tree paramattr = parse_param_attr ();
1071 return chill_munge_params (nreverse (names), mode, paramattr);
1072}
1073
1074/*
1075 * Note: build_process_header depends upon the *exact*
1076 * representation of STRUCT fields and of formal parameter
1077 * lists. If either is changed, build_process_header will
1078 * also need change. Push_extern_process is affected as well.
1079 */
1080static tree
75111422 1081parse_formparlist ()
3c79b2da
PB
1082{
1083 tree list = NULL_TREE;
1084 if (PEEK_TOKEN() == RPRN)
1085 return NULL_TREE;
1086 for (;;)
1087 {
75111422 1088 list = chainon (list, parse_formpar ());
3c79b2da
PB
1089 if (! check_token (COMMA))
1090 break;
1091 }
1092 return list;
1093}
1094
1095static tree
1096parse_opt_result_spec ()
1097{
1098 tree mode;
1099 int is_nonref, is_loc, is_dynamic;
1100 if (!check_token (RETURNS))
1101 return void_type_node;
1102 expect (LPRN, "expected '(' after RETURNS");
1103 mode = parse_mode ();
1104 is_nonref = check_token (NONREF);
1105 is_loc = check_token (LOC);
1106 is_dynamic = check_token (DYNAMIC);
1107 if (is_nonref && !is_loc)
1108 error ("NONREF specific without LOC in result attribute");
1109 if (is_dynamic && !is_loc)
1110 error ("DYNAMIC specific without LOC in result attribute");
1111 mode = get_type_of (mode);
1112 if (is_loc && ! ignoring)
1113 mode = build_chill_reference_type (mode);
1114 expect (RPRN, "expected ')' after RETURNS");
1115 return mode;
1116}
1117
1118static tree
1119parse_opt_except ()
1120{
1121 tree list = NULL_TREE;
1122 if (!check_token (EXCEPTIONS))
1123 return NULL_TREE;
1124 expect (LPRN, "expected '(' after EXCEPTIONS");
1125 do
1126 {
1127 tree except_name = parse_name_string ();
1128 tree name;
1129 for (name = list; name != NULL_TREE; name = TREE_CHAIN (name))
1130 if (TREE_VALUE (name) == except_name && pass == 1)
1131 {
1132 error ("exception names must be unique");
1133 break;
1134 }
1135 if (name == NULL_TREE && !ignoring)
1136 list = tree_cons (NULL_TREE, except_name, list);
1137 } while (check_token (COMMA));
1138 expect (RPRN, "expected ')' after EXCEPTIONS");
1139 return list;
1140}
1141
1142static tree
1143parse_opt_recursive ()
1144{
1145 if (check_token (RECURSIVE))
1146 return ridpointers[RID_RECURSIVE];
1147 else
1148 return NULL_TREE;
1149}
1150
1151static tree
1152parse_procedureattr ()
1153{
1154 tree generality;
1155 tree optrecursive;
1156 switch (PEEK_TOKEN ())
1157 {
1158 case GENERAL:
1159 FORWARD_TOKEN ();
1160 generality = ridpointers[RID_GENERAL];
1161 break;
1162 case SIMPLE:
1163 FORWARD_TOKEN ();
1164 generality = ridpointers[RID_SIMPLE];
1165 break;
1166 case INLINE:
1167 FORWARD_TOKEN ();
1168 generality = ridpointers[RID_INLINE];
1169 break;
1170 default:
1171 generality = NULL_TREE;
1172 }
1173 optrecursive = parse_opt_recursive ();
1174 if (pass != 1)
1175 return NULL_TREE;
1176 if (generality)
1177 generality = build_tree_list (NULL_TREE, generality);
1178 if (optrecursive)
1179 generality = tree_cons (NULL_TREE, optrecursive, generality);
1180 return generality;
1181}
1182
1183/* Parse the body and last part of a procedure or process definition. */
1184
1185static void
1186parse_proc_body (name, exceptions)
1187 tree name;
1188 tree exceptions;
1189{
1190 int save_proc_action_level = proc_action_level;
1191 proc_action_level = action_nesting_level;
1192 if (exceptions != NULL_TREE)
1193 /* set up a handler for reraising exceptions */
1194 push_handler ();
1195 push_action ();
1196 define__PROCNAME__ ();
1197 parse_body ();
1198 proc_action_level = save_proc_action_level;
1199 expect (END, "'END' was expected here");
1200 parse_opt_handler ();
1201 if (exceptions != NULL_TREE)
1202 chill_reraise_exceptions (exceptions);
1203 parse_opt_end_label_semi_colon (name);
1204 end_function ();
1205}
1206
1207static void
1208parse_procedure_definition (in_spec_module)
1209 int in_spec_module;
1210{
1211 int save_ignoring = ignoring;
1212 tree name = parse_defining_occurrence ();
1213 tree params, result, exceptlist, attributes;
1214 int save_chill_at_module_level = chill_at_module_level;
1215 chill_at_module_level = 0;
1216 if (!in_spec_module)
1217 ignoring = pass == 2;
1218 require (COLON); require (PROC);
1219 expect (LPRN, "missing '(' after PROC");
75111422 1220 params = parse_formparlist ();
3c79b2da
PB
1221 expect (RPRN, "missing ')' in PROC");
1222 result = parse_opt_result_spec ();
1223 exceptlist = parse_opt_except ();
1224 attributes = parse_procedureattr ();
1225 ignoring = save_ignoring;
1226 if (in_spec_module)
1227 {
1228 expect (END, "missing 'END'");
1229 parse_opt_end_label_semi_colon (name);
1230 push_extern_function (name, result, params, exceptlist, 0);
1231 return;
1232 }
1233 push_chill_function_context ();
1234 start_chill_function (name, result, params, exceptlist, attributes);
1235 current_module->procedure_seen = 1;
1236 parse_proc_body (name, TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
1237 chill_at_module_level = save_chill_at_module_level;
1238}
1239
1240static tree
1241parse_processpar ()
1242{
1243 tree names = parse_defining_occurrence_list ();
1244 tree mode = parse_mode ();
1245 tree paramattr = parse_param_attr ();
75111422 1246
3c79b2da
PB
1247 if (names && TREE_CODE (names) == IDENTIFIER_NODE)
1248 names = build_tree_list (NULL_TREE, names);
1249 return tree_cons (tree_cons (paramattr, mode, NULL_TREE), names, NULL_TREE);
1250}
1251
1252static tree
1253parse_processparlist ()
1254{
1255 tree list = NULL_TREE;
1256 if (PEEK_TOKEN() == RPRN)
1257 return NULL_TREE;
1258 for (;;)
1259 {
1260 list = chainon (list, parse_processpar ());
1261 if (! check_token (COMMA))
1262 break;
1263 }
1264 return list;
1265}
1266
1267static void
1268parse_process_definition (in_spec_module)
1269 int in_spec_module;
1270{
1271 int save_ignoring = ignoring;
1272 tree name = parse_defining_occurrence ();
1273 tree params;
1274 tree tmp;
1275 if (!in_spec_module)
1276 ignoring = 0;
1277 require (COLON); require (PROCESS);
1278 expect (LPRN, "missing '(' after PROCESS");
1279 params = parse_processparlist (in_spec_module);
1280 expect (RPRN, "missing ')' in PROCESS");
1281 ignoring = save_ignoring;
1282 if (in_spec_module)
1283 {
1284 expect (END, "missing 'END'");
1285 parse_opt_end_label_semi_colon (name);
1286 push_extern_process (name, params, NULL_TREE, 0);
1287 return;
1288 }
1289 tmp = build_process_header (name, params);
1290 parse_proc_body (name, NULL_TREE);
1291 build_process_wrapper (name, tmp);
1292}
1293
1294static void
1295parse_signal_definition ()
1296{
1297 tree signame = parse_defining_occurrence ();
1298 tree modes = NULL_TREE;
1299 tree dest = NULL_TREE;
1300
1301 if (check_token (EQL))
1302 {
1303 expect (LPRN, "missing '(' after 'SIGNAL <name> ='");
1304 for (;;)
1305 {
1306 tree mode = parse_mode ();
1307 modes = tree_cons (NULL_TREE, mode, modes);
1308 if (! check_token (COMMA))
1309 break;
1310 }
1311 expect (RPRN, "missing ')'");
1312 modes = nreverse (modes);
1313 }
1314
1315 if (check_token (TO))
1316 {
1317 tree decl;
1318 int save_ignoring = ignoring;
1319 ignoring = 0;
1320 decl = parse_name ();
1321 ignoring = save_ignoring;
1322 if (pass > 1)
1323 {
1324 if (decl == NULL_TREE
1325 || TREE_CODE (decl) == ERROR_MARK
1326 || TREE_CODE (decl) != FUNCTION_DECL
1327 || !CH_DECL_PROCESS (decl))
1328 error ("must specify a PROCESS name");
1329 else
1330 dest = decl;
1331 }
1332 }
1333
1334 if (! global_bindings_p ())
1335 error ("SIGNAL must be in global reach");
1336 else
1337 {
1338 tree struc = build_signal_struct_type (signame, modes, dest);
1339 tree decl =
1340 generate_tasking_code_variable (signame,
1341 &signal_code,
1342 current_module->is_spec_module);
1343 /* remember the code variable in the struct type */
1344 DECL_TASKING_CODE_DECL (struc) = (struct lang_decl *)decl;
1345 CH_DECL_SIGNAL (struc) = 1;
1346 add_taskstuff_to_list (decl, "_TT_Signal",
1347 current_module->is_spec_module ?
1348 NULL_TREE : signal_code, struc, NULL_TREE);
1349 }
1350
1351}
1352
1353static void
1354parse_signal_definition_statement ()
1355{
1356 int save_ignoring = ignoring;
1357 ignoring = pass == 2;
1358 require (SIGNAL);
1359 for (;;)
1360 {
1361 parse_signal_definition ();
1362 if (! check_token (COMMA))
1363 break;
1364 if (PEEK_TOKEN () == SC)
1365 {
1366 error ("syntax error while parsing signal definition statement");
1367 break;
1368 }
1369 }
1370 parse_semi_colon ();
1371 ignoring = save_ignoring;
1372}
1373
1374static int
1375parse_definition (in_spec_module)
1376 int in_spec_module;
1377{
1378 switch (PEEK_TOKEN ())
1379 {
1380 case NAME:
1381 if (PEEK_TOKEN1() == COLON)
75111422
KG
1382 {
1383 if (PEEK_TOKEN2() == PROC)
1384 {
1385 parse_procedure_definition (in_spec_module);
1386 return 1;
1387 }
1388 else if (PEEK_TOKEN2() == PROCESS)
1389 {
1390 parse_process_definition (in_spec_module);
1391 return 1;
1392 }
1393 }
3c79b2da
PB
1394 return 0;
1395 case DCL:
1396 parse_declaration_statement(in_spec_module);
1397 break;
1398 case GRANT:
1399 parse_grant_statement ();
1400 break;
1401 case NEWMODE:
1402 parse_mode_definition_statement(1);
1403 break;
1404 case SC:
1405 label = NULL_TREE;
1406 FORWARD_TOKEN();
1407 return 1;
1408 case SEIZE:
1409 parse_seize_statement ();
1410 break;
1411 case SIGNAL:
1412 parse_signal_definition_statement ();
1413 break;
1414 case SYN:
1415 parse_synonym_definition_statement();
1416 break;
1417 case SYNMODE:
1418 parse_mode_definition_statement(0);
1419 break;
1420 default:
1421 return 0;
1422 }
1423 return 1;
1424}
1425
1426static void
1427parse_then_clause ()
1428{
1429 expect (THEN, "expected 'THEN' after 'IF'");
1430 if (! ignoring)
1431 emit_line_note (input_filename, lineno);
1432 parse_opt_actions ();
1433}
1434
1435static void
1436parse_opt_else_clause ()
1437{
1438 while (check_token (ELSIF))
1439 {
1440 tree cond = parse_expression ();
1441 if (! ignoring)
1442 expand_start_elseif (truthvalue_conversion (cond));
1443 parse_then_clause ();
1444 }
1445 if (check_token (ELSE))
1446 {
1447 if (! ignoring)
1448 { emit_line_note (input_filename, lineno);
1449 expand_start_else ();
1450 }
1451 parse_opt_actions ();
1452 }
1453}
1454
1455static tree parse_expr_list ()
1456{
1457 tree expr = parse_expression ();
1458 tree list = ignoring ? NULL_TREE : build_tree_list (NULL_TREE, expr);
1459 while (check_token (COMMA))
1460 {
1461 expr = parse_expression ();
1462 if (! ignoring)
1463 list = tree_cons (NULL_TREE, expr, list);
1464 }
1465 return list;
1466}
1467
1468static tree
1469parse_range_list_clause ()
1470{
1471 tree name = parse_opt_name_string (0);
1472 if (name == NULL_TREE)
1473 return NULL_TREE;
1474 while (check_token (COMMA))
1475 {
1476 name = parse_name_string (0);
1477 }
1478 if (check_token (SC))
1479 {
1480 sorry ("case range list");
1481 return error_mark_node;
1482 }
1483 pushback_token (NAME, name);
1484 return NULL_TREE;
1485}
1486
1487static void
1488pushback_paren_expr (expr)
1489 tree expr;
1490{
1491 if (pass == 1 && !ignoring)
1492 expr = build1 (PAREN_EXPR, NULL_TREE, expr);
1493 pushback_token (EXPR, expr);
1494}
1495
1496/* Matches: <case label> */
1497
1498static tree
1499parse_case_label ()
1500{
1501 tree expr;
1502 if (check_token (ELSE))
1503 return case_else_node;
1504 /* Does this also handle the case of a mode name? FIXME */
1505 expr = parse_expression ();
1506 if (check_token (COLON))
1507 {
1508 tree max_expr = parse_expression ();
1509 if (! ignoring)
1510 expr = build (RANGE_EXPR, NULL_TREE, expr, max_expr);
1511 }
1512 return expr;
1513}
1514
1515/* Parses: <case_label_list>
1516 Fails if not followed by COMMA or COLON.
1517 If it fails, it backs up if needed, and returns NULL_TREE.
1518 IN_TUPLE is true if we are parsing a tuple element,
1519 and 0 if we are parsing a case label specification. */
1520
1521static tree
1522parse_case_label_list (selector, in_tuple)
1523 tree selector;
1524 int in_tuple;
1525{
1526 tree expr, list;
1527 if (! check_token (LPRN))
1528 return NULL_TREE;
1529 if (check_token (MUL))
1530 {
1531 expect (RPRN, "missing ')' after '*' case label list");
1532 if (ignoring)
1533 return integer_zero_node;
1534 expr = build (RANGE_EXPR, NULL_TREE, NULL_TREE, NULL_TREE);
1535 expr = build_tree_list (NULL_TREE, expr);
1536 return expr;
1537 }
1538 expr = parse_case_label ();
1539 if (check_token (RPRN))
1540 {
1541 if ((in_tuple || PEEK_TOKEN () != COMMA) && PEEK_TOKEN () != COLON)
1542 {
1543 /* Ooops! It looks like it was the start of an action or
1544 unlabelled tuple element, and not a case label, so back up. */
1545 if (expr != NULL_TREE && TREE_CODE (expr) == RANGE_EXPR)
1546 {
1547 error ("misplaced colon in case label");
1548 expr = error_mark_node;
1549 }
1550 pushback_paren_expr (expr);
1551 return NULL_TREE;
1552 }
1553 list = build_tree_list (NULL_TREE, expr);
1554 if (expr == case_else_node && selector != NULL_TREE)
1555 ELSE_LABEL_SPECIFIED (selector) = 1;
1556 return list;
1557 }
1558 list = build_tree_list (NULL_TREE, expr);
1559 if (expr == case_else_node && selector != NULL_TREE)
1560 ELSE_LABEL_SPECIFIED (selector) = 1;
1561
1562 while (check_token (COMMA))
1563 {
1564 expr = parse_case_label ();
1565 list = tree_cons (NULL_TREE, expr, list);
1566 if (expr == case_else_node && selector != NULL_TREE)
1567 ELSE_LABEL_SPECIFIED (selector) = 1;
1568 }
1569 expect (RPRN, "missing ')' at end of case label list");
1570 return nreverse (list);
1571}
1572
1573/* Parses: <case_label_specification>
1574 Must be followed by a COLON.
1575 If it fails, it backs up if needed, and returns NULL_TREE. */
1576
1577static tree
1578parse_case_label_specification (selectors)
1579 tree selectors;
1580{
1581 tree list_list = NULL_TREE;
1582 tree list;
1583 list = parse_case_label_list (selectors, 0);
1584 if (list == NULL_TREE)
1585 return NULL_TREE;
1586 list_list = build_tree_list (NULL_TREE, list);
1587 while (check_token (COMMA))
1588 {
1589 if (selectors != NULL_TREE)
1590 selectors = TREE_CHAIN (selectors);
1591 list = parse_case_label_list (selectors, 0);
1592 if (list == NULL_TREE)
1593 {
1594 error ("unrecognized case label list after ','");
1595 return list_list;
1596 }
1597 list_list = tree_cons (NULL_TREE, list, list_list);
1598 }
1599 return nreverse (list_list);
1600}
1601
1602static void
1603parse_single_dimension_case_action (selector)
1604 tree selector;
1605{
1606 int no_completeness_check = 0;
1607
1608/* The case label/action toggle. It is 0 initially, and when an action
1609 was last seen. It is 1 integer_zero_node when a label was last seen. */
1610 int caseaction_flag = 0;
1611
1612 if (! ignoring)
1613 {
1614 expand_exit_needed = 0;
1615 selector = check_case_selector (selector);
1616 expand_start_case (1, selector, TREE_TYPE (selector), "CASE statement");
1617 push_momentary ();
1618 }
1619
1620 for (;;)
1621 {
1622 tree label_spec = parse_case_label_specification (selector);
1623 if (label_spec != NULL_TREE)
1624 {
1625 expect (COLON, "missing ':' in case alternative");
1626 if (! ignoring)
1627 {
1628 no_completeness_check |= chill_handle_single_dimension_case_label (
1629 selector, label_spec, &expand_exit_needed, &caseaction_flag);
1630 }
1631 }
1632 else if (parse_action ())
1633 {
1634 expand_exit_needed = 1;
1635 caseaction_flag = 0;
1636 }
1637 else
1638 break;
1639 }
1640
1641 if (! ignoring)
1642 {
1643 if (expand_exit_needed || caseaction_flag == 1)
1644 expand_exit_something ();
1645 }
1646 if (check_token (ELSE))
1647 {
1648 if (! ignoring)
1649 chill_handle_case_default ();
1650 parse_opt_actions ();
1651 if (! ignoring)
1652 {
1653 emit_line_note (input_filename, lineno);
1654 expand_exit_something ();
1655 }
1656 }
1657 else if (! ignoring && TREE_CODE (selector) != ERROR_MARK &&
1658 ! no_completeness_check)
1659 check_missing_cases (TREE_TYPE (selector));
1660
1661 expect (ESAC, "missing 'ESAC' after 'CASE'");
1662 if (! ignoring)
1663 {
1664 expand_end_case (selector);
1665 pop_momentary ();
1666 }
1667}
1668
1669static void
1670parse_multi_dimension_case_action (selector)
1671 tree selector;
1672{
75111422 1673 struct rtx_def *begin_test_label = 0, *end_case_label, *new_label;
3c79b2da
PB
1674 tree action_labels = NULL_TREE;
1675 tree tests = NULL_TREE;
3c79b2da
PB
1676 int save_lineno = lineno;
1677 char *save_filename = input_filename;
1678
1679 /* We can't compute the range of an (ELSE) label until all of the CASE
1680 label specifications have been seen, however, the code for the actions
1681 between them is generated on the fly. We can still generate everything in
1682 one pass is we use the following form:
1683
1684 Compile a CASE of the form
1685
1686 case S1,...,Sn of
1687 (X11),...,(X1n): A1;
1688 ...
1689 (Xm1),...,(Xmn): Am;
1690 else Ae;
1691 esac;
1692
1693 into:
1694
1695 goto L0;
1696 L1: A1; goto L99;
1697 ...
1698 Lm: Am; goto L99;
1699 Le: Ae; goto L99;
1700 L0:
1701 T1 := s1; ...; Tn := Sn;
1702 if (T1 = X11 and ... and Tn = X1n) GOTO L1;
1703 ...
1704 if (T1 = Xm1 and ... and Tn = Xmn) GOTO Lm;
1705 GOTO Le;
1706 L99;
1707 */
1708
1709 if (! ignoring)
1710 {
1711 selector = check_case_selector_list (selector);
1712 begin_test_label = gen_label_rtx ();
1713 end_case_label = gen_label_rtx ();
1714 emit_jump (begin_test_label);
1715 }
1716
1717 for (;;)
1718 {
1719 tree label_spec = parse_case_label_specification (selector);
1720 if (label_spec != NULL_TREE)
1721 {
1722 expect (COLON, "missing ':' in case alternative");
1723 if (! ignoring)
1724 {
1725 tests = tree_cons (label_spec, NULL_TREE, tests);
1726
1727 if (action_labels != NULL_TREE)
1728 emit_jump (end_case_label);
1729
1730 new_label = gen_label_rtx ();
1731 emit_label (new_label);
1732 emit_line_note (input_filename, lineno);
1733 action_labels = tree_cons (NULL_TREE, NULL_TREE, action_labels);
1734 TREE_CST_RTL (action_labels) = new_label;
1735 }
1736 }
1737 else if (! parse_action ())
1738 {
1739 if (action_labels != NULL_TREE)
1740 emit_jump (end_case_label);
1741 break;
1742 }
1743 }
1744
1745 if (check_token (ELSE))
1746 {
1747 if (! ignoring)
1748 {
1749 new_label = gen_label_rtx ();
1750 emit_label (new_label);
1751 emit_line_note (input_filename, lineno);
1752 action_labels = tree_cons (NULL_TREE, NULL_TREE, action_labels);
1753 TREE_CST_RTL (action_labels) = new_label;
1754 }
1755 parse_opt_actions ();
1756 if (! ignoring)
1757 emit_jump (end_case_label);
1758 }
1759
1760 expect (ESAC, "missing 'ESAC' after 'CASE'");
1761
1762 if (! ignoring)
1763 {
1764 emit_label (begin_test_label);
1765 emit_line_note (save_filename, save_lineno);
1766 if (tests != NULL_TREE)
1767 {
1768 tree cond;
1769 tests = nreverse (tests);
1770 action_labels = nreverse (action_labels);
1771 compute_else_ranges (selector, tests);
1772
1773 cond = build_multi_case_selector_expression (selector, TREE_PURPOSE (tests));
1774 expand_start_cond (truthvalue_conversion (cond), label ? 1 : 0);
1775 emit_jump (TREE_CST_RTL (action_labels));
1776
1777 for (tests = TREE_CHAIN (tests), action_labels = TREE_CHAIN (action_labels);
1778 tests != NULL_TREE && action_labels != NULL_TREE;
1779 tests = TREE_CHAIN (tests), action_labels = TREE_CHAIN (action_labels))
1780 {
1781 cond =
1782 build_multi_case_selector_expression (selector, TREE_PURPOSE (tests));
1783 expand_start_elseif (truthvalue_conversion (cond));
1784 emit_jump (TREE_CST_RTL (action_labels));
1785 }
1786 if (action_labels != NULL_TREE)
1787 {
1788 expand_start_else ();
1789 emit_jump (TREE_CST_RTL (action_labels));
1790 }
1791 expand_end_cond ();
1792 }
1793 emit_label (end_case_label);
1794 }
1795}
1796
1797static void
1798parse_case_action (label)
1799 tree label;
1800{
1801 tree selector;
1802 int multi_dimension_case = 0;
1803
3c79b2da
PB
1804 require (CASE);
1805 selector = parse_expr_list ();
1806 selector = nreverse (selector);
1807 expect (OF, "missing 'OF' after 'CASE'");
1808 parse_range_list_clause ();
1809
1810 PUSH_ACTION;
1811 if (label)
1812 pushlevel (1);
1813
1814 if (! ignoring)
1815 {
1816 expand_exit_needed = 0;
1817 if (TREE_CODE (selector) == TREE_LIST)
1818 {
1819 if (TREE_CHAIN (selector) != NULL_TREE)
1820 multi_dimension_case = 1;
1821 else
1822 selector = TREE_VALUE (selector);
1823 }
1824 }
1825
1826 /* We want to use the regular CASE support for the single dimension case. The
1827 multi dimension case requires different handling. Note that when "ignoring"
1828 is true we parse using the single dimension code. This is OK since it will
1829 still parse correctly. */
1830 if (multi_dimension_case)
1831 parse_multi_dimension_case_action (selector);
1832 else
1833 parse_single_dimension_case_action (selector);
1834
1835 if (label)
1836 {
1837 possibly_define_exit_label (label);
1838 poplevel (0, 0, 0);
1839 }
1840}
1841
1842/* Matches: [ <asm_operand> { "," <asm_operand> }* ],
1843 where <asm_operand> = STRING '(' <expression> ')'
1844 These are the operands other than the first string and colon
1845 in asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x)) */
1846
1847static tree
1848parse_asm_operands ()
1849{
1850 tree list = NULL_TREE;
1851 if (PEEK_TOKEN () != STRING)
1852 return NULL_TREE;
1853 for (;;)
1854 {
1855 tree string, expr;
1856 if (PEEK_TOKEN () != STRING)
1857 {
1858 error ("bad ASM operand");
1859 return list;
1860 }
1861 string = PEEK_TREE();
1862 FORWARD_TOKEN ();
1863 expect (LPRN, "missing '(' in ASM operand");
1864 expr = parse_expression ();
1865 expect (RPRN, "missing ')' in ASM operand");
1866 list = tree_cons (string, expr, list);
1867 if (! check_token (COMMA))
1868 break;
1869 }
1870 return nreverse (list);
1871}
1872
1873/* Matches: STRING { ',' STRING }* */
1874
1875static tree
1876parse_asm_clobbers ()
1877{
1878 tree list = NULL_TREE;
1879 for (;;)
1880 {
75111422 1881 tree string;
3c79b2da
PB
1882 if (PEEK_TOKEN () != STRING)
1883 {
1884 error ("bad ASM operand");
1885 return list;
1886 }
1887 string = PEEK_TREE();
1888 FORWARD_TOKEN ();
1889 list = tree_cons (NULL_TREE, string, list);
1890 if (! check_token (COMMA))
1891 break;
1892 }
1893 return list;
1894}
1895
1896void
1897ch_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
1898 tree string, outputs, inputs, clobbers;
1899 int vol;
1900 char *filename;
1901 int line;
1902{
1903 int noutputs = list_length (outputs);
1904 register int i;
1905 /* o[I] is the place that output number I should be written. */
1906 register tree *o = (tree *) alloca (noutputs * sizeof (tree));
1907 register tree tail;
1908
1909 if (TREE_CODE (string) == ADDR_EXPR)
1910 string = TREE_OPERAND (string, 0);
1911 if (TREE_CODE (string) != STRING_CST)
1912 {
1913 error ("asm template is not a string constant");
1914 return;
1915 }
1916
1917 /* Record the contents of OUTPUTS before it is modified. */
1918 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
1919 o[i] = TREE_VALUE (tail);
1920
1921#if 0
1922 /* Perform default conversions on array and function inputs. */
1923 /* Don't do this for other types--
1924 it would screw up operands expected to be in memory. */
1925 for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), i++)
1926 if (TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == ARRAY_TYPE
1927 || TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE)
1928 TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail));
1929#endif
1930
1931 /* Generate the ASM_OPERANDS insn;
1932 store into the TREE_VALUEs of OUTPUTS some trees for
1933 where the values were actually stored. */
1934 expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
1935
1936 /* Copy all the intermediate outputs into the specified outputs. */
1937 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
1938 {
1939 if (o[i] != TREE_VALUE (tail))
1940 {
1941 expand_expr (build_chill_modify_expr (o[i], TREE_VALUE (tail)),
1942 0, VOIDmode, 0);
1943 free_temp_slots ();
1944 }
1945 /* Detect modification of read-only values.
1946 (Otherwise done by build_modify_expr.) */
1947 else
1948 {
1949 tree type = TREE_TYPE (o[i]);
1950 if (TYPE_READONLY (type)
1951 || ((TREE_CODE (type) == RECORD_TYPE
1952 || TREE_CODE (type) == UNION_TYPE)
1953 && TYPE_FIELDS_READONLY (type)))
1954 warning ("readonly location modified by 'asm'");
1955 }
1956 }
1957
1958 /* Those MODIFY_EXPRs could do autoincrements. */
1959 emit_queue ();
1960}
1961
1962static void
1963parse_asm_action ()
1964{
1965 tree insn;
1966 require (ASM_KEYWORD);
1967 expect (LPRN, "missing '('");
1968 PUSH_ACTION;
1969 if (!ignoring)
1970 emit_line_note (input_filename, lineno);
1971 insn = parse_expression ();
1972 if (check_token (COLON))
1973 {
1974 tree output_operand, input_operand, clobbered_regs;
1975 output_operand = parse_asm_operands ();
1976 if (check_token (COLON))
1977 input_operand = parse_asm_operands ();
1978 else
1979 input_operand = NULL_TREE;
1980 if (check_token (COLON))
1981 clobbered_regs = parse_asm_clobbers ();
1982 else
1983 clobbered_regs = NULL_TREE;
1984 expect (RPRN, "missing ')'");
1985 if (!ignoring)
1986 ch_expand_asm_operands (insn, output_operand, input_operand,
1987 clobbered_regs, FALSE,
1988 input_filename, lineno);
1989 }
1990 else
1991 {
1992 expect (RPRN, "missing ')'");
1993 STRIP_NOPS (insn);
1994 if (ignoring) { }
1995 else if ((TREE_CODE (insn) == ADDR_EXPR
1996 && TREE_CODE (TREE_OPERAND (insn, 0)) == STRING_CST)
1997 || TREE_CODE (insn) == STRING_CST)
1998 expand_asm (insn);
1999 else
2000 error ("argument of `asm' is not a constant string");
2001 }
2002}
2003
2004static void
2005parse_begin_end_block (label)
2006 tree label;
2007{
2008 require (BEGINTOKEN);
2009#if 0
2010 /* don't make a linenote at BEGIN */
2011 INIT_ACTION;
2012#endif
2013 pushlevel (1);
2014 if (! ignoring)
2015 {
2016 clear_last_expr ();
2017 push_momentary ();
2018 expand_start_bindings (label ? 1 : 0);
2019 }
2020 push_handler ();
2021 parse_body ();
2022 expect (END, "missing 'END'");
2023 /* Note that the opthandler comes before the poplevel
2024 - hence a handler is in the scope of the block. */
2025 parse_opt_handler ();
2026 possibly_define_exit_label (label);
2027 if (! ignoring)
2028 {
2029 emit_line_note (input_filename, lineno);
2030 expand_end_bindings (getdecls (), kept_level_p (), 0);
2031 }
2032 poplevel (kept_level_p (), 0, 0);
2033 if (! ignoring)
2034 pop_momentary ();
2035 parse_opt_end_label_semi_colon (label);
2036}
2037
2038static void
2039parse_if_action (label)
2040 tree label;
2041{
2042 tree cond;
2043 require (IF);
2044 PUSH_ACTION;
2045 cond = parse_expression ();
2046 if (label)
2047 pushlevel (1);
2048 if (! ignoring)
2049 {
2050 expand_start_cond (truthvalue_conversion (cond),
2051 label ? 1 : 0);
2052 }
2053 parse_then_clause ();
2054 parse_opt_else_clause ();
2055 expect (FI, "expected 'FI' after 'IF'");
2056 if (! ignoring)
2057 {
2058 emit_line_note (input_filename, lineno);
2059 expand_end_cond ();
2060 }
2061 if (label)
2062 {
2063 possibly_define_exit_label (label);
2064 poplevel (0, 0, 0);
2065 }
2066}
2067
2068/* Matches: <iteration> (as in a <for control>). */
2069
2070static void
2071parse_iteration ()
2072{
2073 tree loop_counter = parse_defining_occurrence ();
2074 if (check_token (ASGN))
2075 {
2076 tree start_value = parse_expression ();
2077 tree step_value
2078 = check_token (BY) ? parse_expression () : NULL_TREE;
2079 int going_down = check_token (DOWN);
2080 tree end_value;
2081 if (check_token (TO))
2082 end_value = parse_expression ();
2083 else
2084 {
2085 error ("expected 'TO' in step enumeration");
2086 end_value = error_mark_node;
2087 }
2088 if (!ignoring)
2089 build_loop_iterator (loop_counter, start_value, step_value,
2090 end_value, going_down, 0, 0);
2091 }
2092 else
2093 {
2094 int going_down = check_token (DOWN);
2095 tree expr;
2096 if (check_token (IN))
2097 expr = parse_expression ();
2098 else
2099 {
2100 error ("expected 'IN' in FOR control here");
2101 expr = error_mark_node;
2102 }
2103 if (!ignoring)
2104 {
2105 tree low_bound, high_bound;
2106 if (expr && TREE_CODE (expr) == TYPE_DECL)
2107 {
2108 expr = TREE_TYPE (expr);
2109 /* FIXME: expr must be an array or powerset */
2110 low_bound = convert (expr, TYPE_MIN_VALUE (expr));
2111 high_bound = convert (expr, TYPE_MAX_VALUE (expr));
2112 }
2113 else
2114 {
2115 low_bound = expr;
2116 high_bound = NULL_TREE;
2117 }
2118 build_loop_iterator (loop_counter, low_bound,
2119 NULL_TREE, high_bound,
2120 going_down, 1, 0);
2121 }
2122 }
2123}
2124
2125/* Matches: '(' <event list> ')' ':'.
2126 Or; returns NULL_EXPR. */
2127
2128static tree
2129parse_delay_case_event_list ()
2130{
2131 tree event_list = NULL_TREE;
2132 tree event;
2133 if (! check_token (LPRN))
2134 return NULL_TREE;
2135 event = parse_expression ();
2136 if (PEEK_TOKEN () == ')' && PEEK_TOKEN1 () != ':')
2137 {
2138 /* Oops. */
2139 require (RPRN);
2140 pushback_paren_expr (event);
2141 return NULL_TREE;
2142 }
2143 for (;;)
2144 {
2145 if (! ignoring)
2146 event_list = tree_cons (NULL_TREE, event, event_list);
2147 if (! check_token (COMMA))
2148 break;
2149 event = parse_expression ();
2150 }
2151 expect (RPRN, "missing ')'");
2152 expect (COLON, "missing ':'");
2153 return ignoring ? error_mark_node : event_list;
2154}
2155
2156static void
2157parse_delay_case_action (label)
2158 tree label;
2159{
75111422 2160 tree label_cnt = NULL_TREE, set_location, priority;
3c79b2da
PB
2161 tree combined_event_list = NULL_TREE;
2162 require (DELAY);
2163 require (CASE);
2164 PUSH_ACTION;
2165 pushlevel (1);
2166 expand_exit_needed = 0;
2167 if (check_token (SET))
2168 {
2169 set_location = parse_expression ();
2170 parse_semi_colon ();
2171 }
2172 else
2173 set_location = NULL_TREE;
2174 if (check_token (PRIORITY))
2175 {
2176 priority = parse_expression ();
2177 parse_semi_colon ();
2178 }
2179 else
2180 priority = NULL_TREE;
2181 if (! ignoring)
2182 label_cnt = build_delay_case_start (set_location, priority);
2183 for (;;)
2184 {
2185 tree event_list = parse_delay_case_event_list ();
2186 if (event_list)
2187 {
2188 if (! ignoring )
2189 {
2190 int if_or_elseif = combined_event_list == NULL_TREE;
2191 build_delay_case_label (event_list, if_or_elseif);
2192 combined_event_list = chainon (combined_event_list, event_list);
2193 }
2194 }
2195 else if (parse_action ())
2196 {
2197 if (! ignoring)
2198 {
2199 expand_exit_needed = 1;
2200 if (combined_event_list == NULL_TREE)
2201 error ("missing DELAY CASE alternative");
2202 }
2203 }
2204 else
2205 break;
2206 }
2207 expect (ESAC, "missing 'ESAC' in DELAY CASE'");
2208 if (! ignoring)
297a6bfc 2209 build_delay_case_end (combined_event_list);
3c79b2da
PB
2210 possibly_define_exit_label (label);
2211 poplevel (0, 0, 0);
2212}
2213
2214static void
2215parse_do_action (label)
2216 tree label;
2217{
2218 tree condition;
2219 int token;
2220 require (DO);
2221 if (check_token (WITH))
2222 {
2223 tree list = NULL_TREE;
2224 for (;;)
2225 {
2226 tree name = parse_primval ();
2227 if (! ignoring && TREE_CODE (name) != ERROR_MARK)
2228 {
2229 if (TREE_CODE (TREE_TYPE (name)) == REFERENCE_TYPE)
2230 name = convert (TREE_TYPE (TREE_TYPE (name)), name);
2231 else
2232 {
2233 int is_loc = chill_location (name);
2234 if (is_loc == 1) /* This is probably not possible */
2235 warning ("non-referable location in DO WITH");
2236
2237 if (is_loc > 1)
2238 name = build_chill_arrow_expr (name, 1);
2239 name = decl_temp1 (get_identifier ("__with_element"),
2240 TREE_TYPE (name),
2241 0, name, 0, 0);
2242 if (is_loc > 1)
2243 name = build_chill_indirect_ref (name, NULL_TREE, 0);
2244
2245 }
2246 if (TREE_CODE (TREE_TYPE (name)) != RECORD_TYPE)
2247 error ("WITH element must be of STRUCT mode");
2248 else
2249 list = tree_cons (NULL_TREE, name, list);
2250 }
2251 if (! check_token (COMMA))
2252 break;
2253 }
2254 pushlevel (1);
2255 push_action ();
2256 for (list = nreverse (list); list != NULL_TREE; list = TREE_CHAIN (list))
2257 shadow_record_fields (TREE_VALUE (list));
2258
2259 parse_semi_colon ();
2260 parse_opt_actions ();
2261 expect (OD, "missing 'OD' in 'DO WITH'");
2262 if (! ignoring)
2263 emit_line_note (input_filename, lineno);
2264 possibly_define_exit_label (label);
2265 parse_opt_handler ();
2266 parse_opt_end_label_semi_colon (label);
2267 poplevel (0, 0, 0);
2268 return;
2269 }
2270 token = PEEK_TOKEN();
2271 if (token != FOR && token != WHILE)
2272 {
2273 push_handler ();
2274 parse_opt_actions ();
2275 expect (OD, "Missing 'OD' after 'DO'");
2276 parse_opt_handler ();
2277 parse_opt_end_label_semi_colon (label);
2278 return;
2279 }
2280 if (! ignoring)
2281 emit_line_note (input_filename, lineno);
2282 push_loop_block ();
2283 if (check_token (FOR))
2284 {
2285 if (check_token (EVER))
2286 {
2287 if (!ignoring)
2288 build_loop_iterator (NULL_TREE, NULL_TREE,
2289 NULL_TREE, NULL_TREE,
2290 0, 0, 1);
2291 }
2292 else
2293 {
2294 parse_iteration ();
2295 while (check_token (COMMA))
2296 parse_iteration ();
2297 }
2298 }
2299 else if (!ignoring)
2300 build_loop_iterator (NULL_TREE, NULL_TREE,
2301 NULL_TREE, NULL_TREE,
2302 0, 0, 1);
2303
2304 begin_loop_scope ();
2305 if (! ignoring)
2306 build_loop_start (label);
2307 condition = check_token (WHILE) ? parse_expression () : NULL_TREE;
2308 if (! ignoring)
2309 top_loop_end_check (condition);
2310 parse_semi_colon ();
2311 parse_opt_actions ();
2312 if (! ignoring)
2313 build_loop_end ();
2314 expect (OD, "Missing 'OD' after 'DO'");
2315 /* Note that the handler is inside the reach of the DO. */
2316 parse_opt_handler ();
2317 end_loop_scope (label);
2318 pop_loop_block ();
2319 parse_opt_end_label_semi_colon (label);
2320}
2321
2322/* Matches: '(' <signal name> [ 'IN' <defining occurrence list> ']' ')' ':'
2323 or: '(' <buffer location> IN (defining occurrence> ')' ':'
2324 or: returns NULL_TREE. */
2325
2326static tree
2327parse_receive_spec ()
2328{
2329 tree val;
2330 tree name_list = NULL_TREE;
2331 if (!check_token (LPRN))
2332 return NULL_TREE;
2333 val = parse_primval ();
2334 if (check_token (IN))
2335 {
2336#if 0
2337 if (flag_local_loop_counter)
2338 name_list = parse_defining_occurrence_list ();
2339 else
2340#endif
2341 {
2342 for (;;)
2343 {
2344 tree loc = parse_primval ();
2345 if (! ignoring)
2346 name_list = tree_cons (NULL_TREE, loc, name_list);
2347 if (! check_token (COMMA))
2348 break;
2349 }
2350 }
2351 }
2352 if (! check_token (RPRN))
2353 {
2354 error ("missing ')' in signal/buffer receive alternative");
2355 return NULL_TREE;
2356 }
2357 if (check_token (COLON))
2358 {
2359 if (ignoring || val == NULL_TREE || TREE_CODE (val) == ERROR_MARK)
2360 return error_mark_node;
2361 else
2362 return build_receive_case_label (val, name_list);
2363 }
2364
2365 /* We saw: '(' <primitive value> ')' not followed by ':'.
2366 Presumably the start of an action. Backup and fail. */
2367 if (name_list != NULL_TREE)
2368 error ("misplaced 'IN' in signal/buffer receive alternative");
2369 pushback_paren_expr (val);
2370 return NULL_TREE;
2371}
2372
2373/* To understand the code generation for this, see ch-tasking.c,
2374 and the 2-page comments preceding the
2375 build_chill_receive_case_start () definition. */
2376
2377static void
2378parse_receive_case_action (label)
2379 tree label;
2380{
2381 tree instance_location;
2382 tree have_else_actions;
2383 int spec_seen = 0;
2384 tree alt_list = NULL_TREE;
2385 require (RECEIVE);
2386 require (CASE);
2387 push_action ();
2388 pushlevel (1);
2389 if (! ignoring)
2390 {
2391 expand_exit_needed = 0;
2392 }
2393
2394 if (check_token (SET))
2395 {
2396 instance_location = parse_expression ();
2397 parse_semi_colon ();
2398 }
2399 else
2400 instance_location = NULL_TREE;
2401 if (! ignoring)
2402 instance_location = build_receive_case_start (instance_location);
2403
2404 for (;;)
2405 {
2406 tree receive_spec = parse_receive_spec ();
2407 if (receive_spec)
2408 {
2409 if (! ignoring)
2410 alt_list = tree_cons (NULL_TREE, receive_spec, alt_list);
2411 spec_seen++;
2412 }
2413 else if (parse_action ())
2414 {
2415 if (! spec_seen && pass == 1)
2416 error ("missing RECEIVE alternative");
2417 if (! ignoring)
2418 expand_exit_needed = 1;
2419 spec_seen = 1;
2420 }
2421 else
2422 break;
2423 }
2424 if (check_token (ELSE))
2425 {
2426 if (! ignoring)
2427 {
2428 emit_line_note (input_filename, lineno);
2429 if (build_receive_case_if_generated ())
2430 expand_start_else ();
2431 }
2432 parse_opt_actions ();
2433 have_else_actions = integer_one_node;
2434 }
2435 else
2436 have_else_actions = integer_zero_node;
2437 expect (ESAC, "missing 'ESAC' matching 'RECEIVE CASE'");
2438 if (! ignoring)
2439 {
297a6bfc 2440 build_receive_case_end (nreverse (alt_list), have_else_actions);
3c79b2da
PB
2441 }
2442 possibly_define_exit_label (label);
2443 poplevel (0, 0, 0);
2444}
2445
2446static void
2447parse_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
2527static void
2528parse_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
2554static void
2555parse_opt_actions ()
2556{
2557 while (parse_action ()) ;
2558}
2559
75111422 2560static int
3c79b2da
PB
2561parse_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
2842static void
2843parse_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
2858static tree
2859parse_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
2875static tree
2876parse_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
2920static tree
2921parse_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
2940static tree
2941parse_tuple_element ()
2942{
2943 /* The tupleelement chain is built in reverse order,
2944 and put in forward order when the list is used. */
75111422 2945 tree value, label;
3c79b2da
PB
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). */
3006static tree
3007parse_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
3030static tree
3031parse_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
3055static tree
3056parse_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;
75111422
KG
3135 default:
3136 break;
3c79b2da
PB
3137 }
3138 break;
3139 }
3140 return val;
3141}
3142
3143static tree
3144parse_operand6 ()
3145{
3146 if (check_token (RECEIVE))
3147 {
12fe4621 3148 tree location ATTRIBUTE_UNUSED = parse_primval ();
3c79b2da
PB
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
3161static tree
3162parse_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
3189static tree
3190parse_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
3212static tree
3213parse_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
3234static tree
3235parse_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
3268static tree
3269parse_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
3289static tree
3290parse_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
3311static tree
3312parse_expression ()
3313{
3314 return parse_operand0 ();
3315}
3316
3317static tree
3318parse_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
3369static tree
3370parse_then_alternative ()
3371{
3372 expect (THEN, "missing 'THEN' in 'IF' expression");
3373 return parse_expression ();
3374}
3375
3376static tree
3377parse_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
3389static tree
3390parse_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
3402static tree
3403parse_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
3418static tree
3419parse_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
3454static tree
3455parse_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
3512static tree
3513parse_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*/
3570static tree
3571parse_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*/
3611static tree
3612parse_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*/
3634static tree
3635parse_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
3672static tree
3673parse_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
3702static tree
3703parse_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
3717static tree
3718parse_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
3737static tree
3738parse_variant_alternative ()
3739{
75111422
KG
3740 tree labels;
3741
3c79b2da
PB
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
3766static tree
3767parse_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
3804static tree
3805parse_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
3819static tree
3820parse_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
3832static tree
3833parse_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
3870static tree
3871parse_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
4115static tree
4116parse_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
4128static void
4129parse_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
4163void
4164parse_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
4183int 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 */
4196void
4197to_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
4205int 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. */
4209void
4210set_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.471441 seconds and 5 git commands to generate.