1 /* $Id: occam.g,v 1.12 1994/06/24 12:27:07 ceriel Exp $ */
3 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4 * See the copyright notice in the ACK home directory, in the file "Copyright".
16 #define MAXERRORS 10 /* Maximum number of insert/delete errors */
18 static void nonconst(), nonpositive(), rep_cleanup(), check_assoc();
22 extern int lineno, LLsymb;
23 union type_info info, none;
25 %token AFTER, ALLOCATE, ALT, AND, ANY, BYTE, CHAN, DEF, FALSE, FOR, IF, LOAD;
26 %token NOT, NOW, OR, PAR, PLACED, PORT, PRI, PROC, SEQ, SKIP, TABLE, TRUE;
27 %token VALUE, VAR, WAIT, WHILE;
28 %token IDENTIFIER, NUMBER, CHAR_CONST, STRING;
29 %token AS, LE, GE, NE, LS, RS, BA, BO, BX, BS;
31 %start occam, program;
33 program : { init_builtins();
42 declaration ':' process
46 primitive { struct expr *e; } :
47 statement(&e) { if (!valueless(e))
48 report("primitive may not have a value");
52 | WAIT val_expr(&e) { int BEGIN=0, END=0, TEST=0;
56 Label(new_label(&BEGIN));
59 code_bool(e, positive, &END, &BEGIN);
66 guard(register *F;) { struct expr *e1, *e2;
67 register full_guard=0;
69 static char EXPECT_INP[]="input process expected as guard";
74 report("boolean part of guard has no value");
75 code_bool(e1, positive, &T, F);
79 { if (!input_process(e2))
86 code_bool(e2, positive, &T, F);
94 if (!input_process(e1))
102 code_bool(e1, positive, &T, F);
109 guarded_process(register *END;) { struct symbol *v;
110 struct expr *e1, *e2;
111 struct replicator to_test;
115 guard(&F) process { branch(END);
118 | ALT { line=lineno; oind=ind; }
120 replicator(&v, &e1, &e2)
121 { rep_init(v, e1, e2, &to_test); }
123 { rep_test(v, e1, e2, &to_test);
127 [ %while (tabulated(oind, ind)) guarded_process(END) ]*
131 conditional(register *END; ) { struct symbol *v;
132 struct expr *e1, *e2;
133 struct replicator to_test;
137 val_expr(&e1) { if (!valued(e1))
138 report("conditional needs valued expression");
139 code_bool(e1, positive, &T, &F);
147 | IF { line=lineno; oind=ind; }
149 replicator(&v, &e1, &e2)
150 { rep_init(v, e1, e2, &to_test); }
152 { rep_test(v, e1, e2, &to_test);
156 [ %while (tabulated(oind, ind)) conditional(END) ]*
160 replicator(register struct symbol **s; register struct expr **e1; register struct expr **e2; )
161 { register char *index; }:
162 IDENTIFIER { index=token.t_sval; }
163 '=' '[' val_expr(e1) FOR val_expr(e2) ']'
164 { if (!valued(*e1) || !valued(*e2))
165 report("replicator needs valued expressions");
167 var_memory(&info, T_VAR, 1);
169 T_VAR|T_REP|T_USED|T_ASSIGNED, 1, &info);
173 construct { struct symbol *v;
174 struct expr *e1, *e2;
175 struct replicator to_test;
177 int BEGIN=0, END=0, NONZERO;
179 SEQ { line=lineno; oind=ind; }
181 replicator(&v, &e1, &e2)
182 { rep_init(v, e1, e2, &to_test); }
184 { rep_test(v, e1, e2, &to_test);
188 [ %while (tabulated(oind, ind)) process ]*
191 [ PAR { line=lineno; oind=ind;
195 replicator(&v, &e1, &e2)
196 { rep_init(v, e1, e2, &to_test);
203 rep_test(v, e1, e2, &to_test);
207 [ %while (tabulated(oind, ind))
220 | ALT { line=lineno; oind=ind;
222 Label(new_label(&BEGIN));
225 replicator(&v, &e1, &e2)
226 { rep_init(v, e1, e2, &to_test); }
227 guarded_process(&END)
228 { rep_test(v, e1, e2, &to_test);
232 [ %while (tabulated(oind, ind)) guarded_process(&END)
240 | IF { line=lineno; oind=ind; }
242 replicator(&v, &e1, &e2)
243 { rep_init(v, e1, e2, &to_test); }
245 { rep_test(v, e1, e2, &to_test);
249 [ %while (tabulated(oind, ind)) conditional(&END) ]*
252 | WHILE val_expr(&e1) { if (!valued(e1))
253 report("WHILE needs valued expression");
255 Label(new_label(&BEGIN));
260 code_bool(e1, negative, &DONE, &BEGIN);
266 subscript(register *byte; register struct expr **e; )
268 register slice=0, err=0;
271 [ BYTE { *byte=T_BYTE; }
273 val_expr(e) { if (!valued(*e))
276 [ FOR expression(&e1)
277 { static char siz[]="slize size";
286 *e=new_node(FOR, *e, e1, *byte);
293 "slice must be '[' value FOR constant ']'" :
294 "subscript needs valued expression");
298 chan { register type, arr_siz=1; register char *name; struct expr *e; }:
299 IDENTIFIER { type=T_CHAN;
302 [ '[' expression(&e) ']'
303 { static char siz[]="channel array size";
315 { chan_memory(&info, arr_siz);
316 chan_init(&info, arr_siz);
317 insert(name, type, arr_siz, &info);
321 var { register type, byte=0, arr_siz=1;
325 IDENTIFIER { type=T_VAR; name=token.t_sval; }
327 [ BYTE { byte=T_BYTE; }
330 { static char siz[]="variable array size";
342 { var_memory(&info, type, arr_siz);
343 insert(name, type, arr_siz, &info);
347 const_def { register char *name; struct expr *e; }:
348 IDENTIFIER { name=token.t_sval; }
350 { if (!constant(e) && !arr_constant(e))
351 nonconst("expression in constant definition");
353 insert(name, T_CONST|T_USED, 0, &info);
357 form_parm(register struct par_list ***aapars; register *g_type;)
358 { register char *name;
359 register type= *g_type;
361 [ VAR { type=T_VAR|T_ASSIGNED|T_USED; }
362 | CHAN { type=T_CHAN; }
363 | VALUE { type=T_VALUE|T_ASSIGNED; }
367 report("VAR, CHAN or VALUE expected");
376 { pars_add(aapars, type&(T_TYPE|T_ARR),
377 insert(name, type|T_PARAM, 0, &none));
381 form_parms(struct par_list **apars;) { int type= -1; }:
382 '(' form_parm(&apars, &type)
383 [ ',' form_parm(&apars, &type)
394 const_def [ ',' const_def ]*
398 proc_declaration { struct par_list *pars=nil;
399 register struct symbol *proc;
401 register old_min_offset;
403 PROC IDENTIFIER { branch(&OVER);
404 proc=insert(token.t_sval,
405 T_PROC|T_RECURS, 0, &none);
406 old_min_offset=min_offset;
410 form_parms(&pars) ? { form_offsets(pars);
411 proc->s_info.proc.pars=pars;
413 '=' process { epilogue(proc);
415 proc->s_type&= ~T_RECURS;
416 min_offset=old_min_offset;
421 vector_constant(register struct expr **e;)
422 { struct table *pt=nil, **apt= &pt;
426 | STRING { register char *ps= token.t_sval;
429 Tlen+= len= (*ps++ & 0377);
431 table_add(&apt, (long) *ps++);
434 { register char *ps= token.t_sval;
437 Tlen+= len= (*ps++ & 0377);
439 table_add(&apt, (long) *ps++);
443 table_add(&apt, (long) Tlen);
444 *e=new_table(E_BTAB, pt);
448 item(register struct expr **e;)
450 register struct symbol *var;
451 struct par_list *pars=nil;
453 int byte, err=0, subs_call=0;
454 struct expr_list *elp=nil, **aelp= &elp;
456 IDENTIFIER { line=lineno;
458 var=searchall(token.t_sval);
460 if (var_constant(var))
461 *e=copy_const(var->s_info.t_const);
464 pars=var->s_info.proc.pars;
468 [ %while (line==lineno || tabulated(oind, ind))
469 [ subscript(&byte, &e1)
470 { *e=new_node('[', *e, e1, byte); }
471 | '(' { if (!var_declared(var)) {
472 var->s_type=T_PROC|T_USED|T_NOTDECL;
473 var->s_info.proc.pars=nil;
476 if (!var_proc(var)) {
477 report("%s is not a named process",
483 { check_param(&pars, e1, &err);
484 expr_list_add(&aelp, e1);
486 [ ',' expression(&e1)
487 { check_param(&pars, e1, &err);
488 expr_list_add(&aelp, e1);
493 report("too few actual parameters");
496 { *e=new_call(*e, elp); }
500 { if (!subs_call && var_proc(var)) {
502 report("no actual parameters");
503 *e=new_call(*e, (char *)nil);
507 [ subscript(&byte, &e1)
508 { *e=new_node('[', *e, e1, byte); }
512 statement(register struct expr **e;)
514 struct expr_list *elp=nil, **aelp= &elp;
519 { *e=new_node(AS, *e, e1, 0); }
525 { if (e1!=nil) check_io(out, e1);
526 expr_list_add(&aelp, e1);
528 [ %while (1) ';' io_arg(&e1)
529 { if (e1!=nil) check_io(out, e1);
530 expr_list_add(&aelp, e1);
533 { *e=new_io(out, *e, elp); }
537 io_arg(struct expr **e; ) :
542 table(register struct expr **e;)
543 { struct table *pt=nil, **apt= &pt;
547 TABLE '[' { type=E_TABLE; }
548 [ BYTE { type=E_BTAB; }
550 expression(&e1) { if (!constant(e1))
551 nonconst("table element");
553 table_add(&apt, e1->u.cst);
556 [ ',' expression(&e1)
558 nonconst("table element");
560 table_add(&apt, e1->u.cst);
564 { *e=new_table(type, pt); }
568 arithmetic_op: '+' | '-' | '*' | '/' | BS
571 comparison_op: '<' | '>' | LE | GE | NE | '=' | AFTER
574 logical_op: BA | BO | BX
583 monadic_op(register *op;):
588 operator: arithmetic_op | comparison_op | logical_op | boolean_op | shift_op
591 element(register struct expr **e;) :
592 %default NUMBER { *e=new_const(token.t_lval); }
594 | TRUE { *e=new_const(-1L); }
595 | FALSE { *e=new_const(0L); }
596 | NOW { *e=new_now(); }
597 | CHAR_CONST { *e=new_const(token.t_lval); }
598 | '(' expression(e) ')' { if (valueless(*e))
599 warning("primitive should not be parenthesized");
603 expression(register struct expr **e;)
608 [ %while (1) { if (op!=0) check_assoc(op, LLsymb);
611 operator element(&e1)
612 { *e=new_node(op, *e, e1, 0); }
614 | monadic_op(&op) element(&e1)
615 { *e=new_node(op, e1, (char *)nil, 0); }
618 val_expr(register struct expr **e;) :
619 expression(e) { used(*e); }
626 main(argc, argv) register argc; register char **argv;
628 while (argc > 1 && argv[1][0] == '-') {
629 do_option(&argv[1][1]);
649 fatal("illegal option: %c", *--text);
651 case 'L' : /* no fil/lin */
654 case 'V' : /* set object sizes and alignment requirements */
659 while (c = *text++) {
660 size = txt2int(&text);
663 if (size != (arith)0)
666 case 'p': /* pointer */
667 if (size != (arith)0)
671 if (size != (arith)0)
675 fatal("-V: bad type indicator %c\n", c);
687 /* the integer pointed to by *tp is read, while increasing
688 *tp; the resulting value is yielded.
690 register int val = 0, ch;
692 while (ch = **tp, ch >= '0' && ch <= '9') {
693 val = val * 10 + ch - '0';
699 LLmessage(tk) register tk;
704 repeat_token(LLsymb);
705 warning("syntax error: %s expected (inserted)", tokenname(tk, 1));
708 warning("syntax error: bad token %s (deleted)", tokenname(LLsymb, 0));
710 warning("syntax error: garbage at end of program");
712 if (++errors==MAXERRORS) {
713 fprint(STDERR, "Too many insert/delete errors. Compiler ends.\n");
714 err=1; trailer(); exit(1);
718 static void nonconst(siz) char *siz;
720 report("%s should be a constant", siz);
723 static void nonpositive(siz) char *siz;
725 report("%s must be positive", siz);
728 static void rep_cleanup(e1, e2) struct expr *e1, *e2;
735 static void check_assoc(prev_op, op) register prev_op, op;
741 case BA: case BO: case BX:
742 if (prev_op==op) break;
744 strcpy(prev, tokenname(prev_op, 0));
746 warning("Operators %s and %s don't associate",
747 prev, tokenname(op, 0)
755 fatal("out of memory");