1987-04-29 10:22:07 +00:00
|
|
|
/*
|
|
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
|
|
*
|
|
|
|
* Author: Ceriel J.H. Jacobs
|
|
|
|
*/
|
|
|
|
|
1986-03-26 15:11:02 +00:00
|
|
|
/* D E C L A R A T I O N S */
|
1986-03-20 14:52:03 +00:00
|
|
|
|
1994-06-24 14:02:31 +00:00
|
|
|
/* $Id$ */
|
1987-04-29 10:22:07 +00:00
|
|
|
|
1986-03-26 15:11:02 +00:00
|
|
|
{
|
2019-03-01 17:39:25 +00:00
|
|
|
#include "parameters.h"
|
1986-05-01 19:06:53 +00:00
|
|
|
#include "debug.h"
|
1986-03-20 14:52:03 +00:00
|
|
|
|
1986-03-26 22:46:48 +00:00
|
|
|
#include <assert.h>
|
2019-03-01 17:39:25 +00:00
|
|
|
#include "em_arith.h"
|
|
|
|
#include "em_label.h"
|
|
|
|
#include "alloc.h"
|
1986-04-22 22:36:16 +00:00
|
|
|
|
1986-03-26 15:11:02 +00:00
|
|
|
#include "idf.h"
|
|
|
|
#include "LLlex.h"
|
|
|
|
#include "def.h"
|
|
|
|
#include "type.h"
|
|
|
|
#include "scope.h"
|
1986-04-06 17:42:56 +00:00
|
|
|
#include "node.h"
|
2019-03-01 17:39:25 +00:00
|
|
|
#include "enter.h"
|
|
|
|
#include "error.h"
|
1986-04-06 17:42:56 +00:00
|
|
|
#include "misc.h"
|
1986-04-18 17:53:47 +00:00
|
|
|
#include "main.h"
|
2019-03-01 17:39:25 +00:00
|
|
|
#include "typequiv.h"
|
1986-06-26 09:39:36 +00:00
|
|
|
#include "chk_expr.h"
|
1986-11-05 14:33:00 +00:00
|
|
|
#include "warning.h"
|
1986-04-15 17:51:53 +00:00
|
|
|
|
1986-06-20 14:36:49 +00:00
|
|
|
int proclevel = 0; /* nesting level of procedures */
|
1986-10-06 20:36:30 +00:00
|
|
|
int return_occurred; /* set if a return occurs in a block */
|
1987-04-29 10:22:07 +00:00
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
extern struct node *EmptyStatement;
|
1987-09-24 13:07:31 +00:00
|
|
|
|
1987-04-29 10:22:07 +00:00
|
|
|
#define needs_static_link() (proclevel > 1)
|
1986-03-26 15:11:02 +00:00
|
|
|
}
|
1986-03-20 14:52:03 +00:00
|
|
|
|
1987-06-18 17:42:47 +00:00
|
|
|
/* inline in declaration: need space
|
1987-09-24 13:07:31 +00:00
|
|
|
* ProcedureDeclaration
|
|
|
|
* {
|
2019-05-10 17:09:03 +00:00
|
|
|
* struct def *df;
|
1987-09-24 13:07:31 +00:00
|
|
|
* } :
|
|
|
|
* { ++proclevel; }
|
|
|
|
* ProcedureHeading(&df, D_PROCEDURE)
|
|
|
|
* ';' block(&(df->prc_body))
|
|
|
|
* IDENT
|
|
|
|
* { EndProc(df, dot.TOK_IDF);
|
|
|
|
* --proclevel;
|
|
|
|
* }
|
|
|
|
* ;
|
1987-06-18 17:42:47 +00:00
|
|
|
*/
|
1986-03-26 15:11:02 +00:00
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
ProcedureHeading(struct def **pdf; int type;)
|
1986-03-26 15:11:02 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct type *tp = 0;
|
1987-09-24 13:07:31 +00:00
|
|
|
arith parmaddr = needs_static_link() ? pointer_size : 0;
|
2019-05-10 17:09:03 +00:00
|
|
|
struct paramlist *pr = 0;
|
1986-03-26 15:11:02 +00:00
|
|
|
} :
|
|
|
|
PROCEDURE IDENT
|
1986-10-06 20:36:30 +00:00
|
|
|
{ *pdf = DeclProc(type, dot.TOK_IDF); }
|
1987-06-18 17:42:47 +00:00
|
|
|
[
|
|
|
|
'('
|
|
|
|
[
|
|
|
|
FPSection(&pr, &parmaddr)
|
|
|
|
[
|
|
|
|
';' FPSection(&pr, &parmaddr)
|
|
|
|
]*
|
1988-02-10 14:06:34 +00:00
|
|
|
|
|
|
|
|
]
|
1987-06-18 17:42:47 +00:00
|
|
|
')'
|
|
|
|
[ ':' qualtype(&tp)
|
1988-02-10 14:06:34 +00:00
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
]
|
1986-12-09 17:41:06 +00:00
|
|
|
{ CheckWithDef(*pdf, proc_type(tp, pr, parmaddr));
|
1987-11-09 16:11:04 +00:00
|
|
|
#ifndef NOSTRICT
|
1986-12-09 17:41:06 +00:00
|
|
|
if (tp && IsConstructed(tp)) {
|
|
|
|
warning(W_STRICT, "procedure \"%s\" has a constructed result type",
|
|
|
|
(*pdf)->df_idf->id_text);
|
|
|
|
}
|
1987-11-09 10:17:20 +00:00
|
|
|
#endif
|
1986-12-09 17:41:06 +00:00
|
|
|
}
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
block(struct node **pnd;) :
|
1986-11-17 11:41:28 +00:00
|
|
|
[ %persistent
|
|
|
|
declaration
|
|
|
|
]*
|
1987-08-10 21:43:47 +00:00
|
|
|
{ return_occurred = 0; }
|
|
|
|
[ %default
|
1986-04-17 09:28:09 +00:00
|
|
|
BEGIN
|
|
|
|
StatementSequence(pnd)
|
1987-08-10 21:43:47 +00:00
|
|
|
|
|
|
|
|
{ *pnd = EmptyStatement; }
|
|
|
|
]
|
1986-04-17 09:28:09 +00:00
|
|
|
END
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
1987-06-18 17:42:47 +00:00
|
|
|
declaration
|
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct def *df;
|
1987-06-18 17:42:47 +00:00
|
|
|
} :
|
1987-04-29 10:22:07 +00:00
|
|
|
CONST [ ConstantDeclaration ';' ]*
|
1986-03-20 14:52:03 +00:00
|
|
|
|
|
1987-04-29 10:22:07 +00:00
|
|
|
TYPE [ TypeDeclaration ';' ]*
|
1986-03-20 14:52:03 +00:00
|
|
|
|
|
1987-04-29 10:22:07 +00:00
|
|
|
VAR [ VariableDeclaration ';' ]*
|
1986-03-20 14:52:03 +00:00
|
|
|
|
|
1987-06-18 17:42:47 +00:00
|
|
|
{ ++proclevel; }
|
|
|
|
ProcedureHeading(&df, D_PROCEDURE)
|
1991-02-18 17:18:36 +00:00
|
|
|
{
|
|
|
|
}
|
1987-06-18 17:42:47 +00:00
|
|
|
';'
|
|
|
|
block(&(df->prc_body))
|
|
|
|
IDENT
|
1991-02-18 17:18:36 +00:00
|
|
|
{
|
1990-07-30 15:56:25 +00:00
|
|
|
EndProc(df, dot.TOK_IDF);
|
1987-06-18 17:42:47 +00:00
|
|
|
--proclevel;
|
|
|
|
}
|
|
|
|
';'
|
1986-03-20 14:52:03 +00:00
|
|
|
|
|
|
|
|
ModuleDeclaration ';'
|
|
|
|
;
|
|
|
|
|
1987-06-18 17:42:47 +00:00
|
|
|
/* inline in procedureheading: need space
|
2019-05-10 17:09:03 +00:00
|
|
|
* FormalParameters(struct paramlist **ppr; arith *parmaddr; struct type **ptp;):
|
1987-09-24 13:07:31 +00:00
|
|
|
* '('
|
|
|
|
* [
|
|
|
|
* FPSection(ppr, parmaddr)
|
|
|
|
* [
|
|
|
|
* ';' FPSection(ppr, parmaddr)
|
|
|
|
* ]*
|
1988-02-10 14:06:34 +00:00
|
|
|
* |
|
|
|
|
* ]
|
1987-09-24 13:07:31 +00:00
|
|
|
* ')'
|
|
|
|
* [ ':' qualtype(ptp)
|
1988-02-10 14:06:34 +00:00
|
|
|
* |
|
|
|
|
* ]
|
1987-09-24 13:07:31 +00:00
|
|
|
* ;
|
1987-06-18 17:42:47 +00:00
|
|
|
*/
|
1986-03-20 14:52:03 +00:00
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
FPSection(struct paramlist **ppr; arith *parmaddr;)
|
1986-03-20 14:52:03 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct node *FPList;
|
|
|
|
struct type *tp;
|
1987-09-24 13:07:31 +00:00
|
|
|
int VARp;
|
1986-03-20 14:52:03 +00:00
|
|
|
} :
|
1986-08-26 14:33:24 +00:00
|
|
|
var(&VARp) IdentList(&FPList) ':' FormalType(&tp)
|
|
|
|
{ EnterParamList(ppr, FPList, tp, VARp, parmaddr); }
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
FormalType(struct type **ptp;)
|
1990-03-06 13:22:30 +00:00
|
|
|
/* index type of conformant array is "CARDINAL".
|
|
|
|
Recognize a conformant array by size 0.
|
|
|
|
*/
|
2019-05-10 17:09:03 +00:00
|
|
|
{ register struct type *tp;
|
1990-03-06 13:22:30 +00:00
|
|
|
} :
|
|
|
|
ARRAY OF
|
|
|
|
{ tp = construct_type(T_ARRAY, card_type); }
|
|
|
|
qualtype(&(tp->arr_elem))
|
|
|
|
{ ArrayElSize(tp);
|
1986-10-06 20:36:30 +00:00
|
|
|
*ptp = tp;
|
1986-04-21 17:27:06 +00:00
|
|
|
}
|
1986-08-26 14:33:24 +00:00
|
|
|
|
|
1988-03-21 17:06:20 +00:00
|
|
|
qualtype(ptp)
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
1986-03-26 15:11:02 +00:00
|
|
|
TypeDeclaration
|
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct def *df;
|
|
|
|
struct type *tp;
|
|
|
|
register struct node *nd;
|
1986-03-26 15:11:02 +00:00
|
|
|
}:
|
1986-12-01 10:06:53 +00:00
|
|
|
IDENT { df = define(dot.TOK_IDF, CurrentScope, D_TYPE);
|
1987-08-10 21:43:47 +00:00
|
|
|
nd = dot2leaf(Name);
|
1986-12-01 10:06:53 +00:00
|
|
|
}
|
1986-03-27 17:37:41 +00:00
|
|
|
'=' type(&tp)
|
1986-12-01 10:06:53 +00:00
|
|
|
{ DeclareType(nd, df, tp);
|
1987-09-23 16:39:43 +00:00
|
|
|
FreeNode(nd);
|
1986-12-01 10:06:53 +00:00
|
|
|
}
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
type(register struct type **ptp;):
|
1986-08-26 14:33:24 +00:00
|
|
|
%default SimpleType(ptp)
|
1986-03-20 14:52:03 +00:00
|
|
|
|
|
1986-03-27 17:37:41 +00:00
|
|
|
ArrayType(ptp)
|
1986-03-20 14:52:03 +00:00
|
|
|
|
|
1986-03-27 17:37:41 +00:00
|
|
|
RecordType(ptp)
|
1986-03-20 14:52:03 +00:00
|
|
|
|
|
1986-03-27 17:37:41 +00:00
|
|
|
SetType(ptp)
|
1986-03-20 14:52:03 +00:00
|
|
|
|
|
1986-03-27 17:37:41 +00:00
|
|
|
PointerType(ptp)
|
1986-03-20 14:52:03 +00:00
|
|
|
|
|
1986-03-27 17:37:41 +00:00
|
|
|
ProcedureType(ptp)
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
SimpleType(register struct type **ptp;) :
|
1986-07-08 14:59:02 +00:00
|
|
|
qualtype(ptp)
|
1986-03-20 14:52:03 +00:00
|
|
|
[
|
1986-03-29 01:04:49 +00:00
|
|
|
/* nothing */
|
1986-03-20 14:52:03 +00:00
|
|
|
|
|
1988-10-21 17:24:34 +00:00
|
|
|
SubrangeType(ptp)
|
1986-03-29 01:04:49 +00:00
|
|
|
/* The subrange type is given a base type by the
|
|
|
|
qualident (this is new modula-2).
|
|
|
|
*/
|
1986-03-20 14:52:03 +00:00
|
|
|
]
|
|
|
|
|
|
1986-03-27 17:37:41 +00:00
|
|
|
enumeration(ptp)
|
1990-03-06 13:22:30 +00:00
|
|
|
| { *ptp = 0; /* no qualification */ }
|
1986-03-27 17:37:41 +00:00
|
|
|
SubrangeType(ptp)
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
enumeration(struct type **ptp;)
|
1986-03-20 14:52:03 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct node *EnumList;
|
1986-03-20 14:52:03 +00:00
|
|
|
} :
|
|
|
|
'(' IdentList(&EnumList) ')'
|
1987-04-29 10:22:07 +00:00
|
|
|
{ *ptp = enum_type(EnumList); }
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
IdentList(struct node **p;)
|
1986-03-20 14:52:03 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
register struct node *q;
|
1986-03-20 14:52:03 +00:00
|
|
|
} :
|
1991-03-12 16:52:00 +00:00
|
|
|
IDENT { *p = q = dot2leaf(Select); }
|
1986-08-26 14:33:24 +00:00
|
|
|
[ %persistent
|
1986-04-06 17:42:56 +00:00
|
|
|
',' IDENT
|
1991-03-12 16:52:00 +00:00
|
|
|
{ q->nd_NEXT = dot2leaf(Select);
|
|
|
|
q = q->nd_NEXT;
|
1986-04-06 17:42:56 +00:00
|
|
|
}
|
1986-03-20 14:52:03 +00:00
|
|
|
]*
|
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
SubrangeType(struct type **ptp;)
|
1986-03-27 17:37:41 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct node *nd1, *nd2;
|
1986-03-27 17:37:41 +00:00
|
|
|
}:
|
1986-03-20 14:52:03 +00:00
|
|
|
/*
|
|
|
|
This is not exactly the rule in the new report, but see
|
|
|
|
the rule for "SimpleType".
|
|
|
|
*/
|
1986-04-06 17:42:56 +00:00
|
|
|
'[' ConstExpression(&nd1)
|
|
|
|
UPTO ConstExpression(&nd2)
|
1986-03-27 17:37:41 +00:00
|
|
|
']'
|
1988-10-21 17:24:34 +00:00
|
|
|
{ *ptp = subr_type(nd1, nd2, *ptp);
|
1987-09-23 16:39:43 +00:00
|
|
|
FreeNode(nd1);
|
|
|
|
FreeNode(nd2);
|
1986-10-06 20:36:30 +00:00
|
|
|
}
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
ArrayType(struct type **ptp;)
|
1986-03-27 17:37:41 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct type *tp;
|
|
|
|
register struct type *tp1, *tp2;
|
1986-03-27 17:37:41 +00:00
|
|
|
} :
|
|
|
|
ARRAY SimpleType(&tp)
|
1990-03-06 13:22:30 +00:00
|
|
|
{ tp1 = tp2 = construct_type(T_ARRAY, tp); }
|
1986-03-27 17:37:41 +00:00
|
|
|
[
|
|
|
|
',' SimpleType(&tp)
|
1986-05-28 18:36:51 +00:00
|
|
|
{ tp2->arr_elem = construct_type(T_ARRAY, tp);
|
|
|
|
tp2 = tp2->arr_elem;
|
1986-03-27 17:37:41 +00:00
|
|
|
}
|
|
|
|
]* OF type(&tp)
|
1986-04-15 17:51:53 +00:00
|
|
|
{ tp2->arr_elem = tp;
|
1990-03-06 13:22:30 +00:00
|
|
|
ArraySizes(tp1);
|
|
|
|
*ptp = tp1;
|
1986-04-15 17:51:53 +00:00
|
|
|
}
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
RecordType(struct type **ptp;)
|
1986-03-27 17:37:41 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
register struct scope *scope;
|
1986-10-22 15:38:24 +00:00
|
|
|
arith size = 0;
|
1986-04-17 09:28:09 +00:00
|
|
|
int xalign = struct_align;
|
1986-03-27 17:37:41 +00:00
|
|
|
}
|
|
|
|
:
|
|
|
|
RECORD
|
1987-04-29 10:22:07 +00:00
|
|
|
{ scope = open_and_close_scope(OPENSCOPE); }
|
1986-10-06 20:36:30 +00:00
|
|
|
FieldListSequence(scope, &size, &xalign)
|
1986-12-01 10:06:53 +00:00
|
|
|
{ if (size == 0) {
|
|
|
|
warning(W_ORDINARY, "empty record declaration");
|
|
|
|
size = 1;
|
|
|
|
}
|
1988-03-21 17:06:20 +00:00
|
|
|
*ptp = standard_type(T_RECORD, xalign, align(size, xalign));
|
1986-04-15 17:51:53 +00:00
|
|
|
(*ptp)->rec_scope = scope;
|
1990-07-30 15:56:25 +00:00
|
|
|
Reverse(&(scope->sc_def));
|
1986-04-10 01:08:49 +00:00
|
|
|
}
|
1986-03-27 17:37:41 +00:00
|
|
|
END
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
FieldListSequence(struct scope *scope; arith *cnt; int *palign;):
|
1986-04-15 17:51:53 +00:00
|
|
|
FieldList(scope, cnt, palign)
|
1986-03-27 17:37:41 +00:00
|
|
|
[
|
1986-04-15 17:51:53 +00:00
|
|
|
';' FieldList(scope, cnt, palign)
|
1986-03-27 17:37:41 +00:00
|
|
|
]*
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
FieldList(struct scope *scope; arith *cnt; int *palign;)
|
1986-03-20 14:52:03 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct node *FldList;
|
|
|
|
struct type *tp;
|
|
|
|
struct node *nd;
|
|
|
|
register struct def *df;
|
1986-04-15 17:51:53 +00:00
|
|
|
arith tcnt, max;
|
1986-03-20 14:52:03 +00:00
|
|
|
} :
|
|
|
|
[
|
1986-03-27 17:37:41 +00:00
|
|
|
IdentList(&FldList) ':' type(&tp)
|
1987-04-29 10:22:07 +00:00
|
|
|
{
|
|
|
|
*palign = lcm(*palign, tp->tp_align);
|
1986-06-10 13:18:52 +00:00
|
|
|
EnterFieldList(FldList, tp, scope, cnt);
|
1986-04-04 13:47:04 +00:00
|
|
|
}
|
1986-03-20 14:52:03 +00:00
|
|
|
|
|
1986-03-27 17:37:41 +00:00
|
|
|
CASE
|
1986-10-06 20:36:30 +00:00
|
|
|
/* Also accept old fashioned Modula-2 syntax, but give a warning.
|
|
|
|
Sorry for the complicated code.
|
1986-04-11 11:57:19 +00:00
|
|
|
*/
|
1987-04-29 10:22:07 +00:00
|
|
|
[ qualident(&nd)
|
1986-10-06 20:36:30 +00:00
|
|
|
[ ':' qualtype(&tp)
|
1986-07-08 14:59:02 +00:00
|
|
|
/* This is correct, in both kinds of Modula-2, if
|
1986-10-06 20:36:30 +00:00
|
|
|
the first qualident is a single identifier.
|
1986-04-11 11:57:19 +00:00
|
|
|
*/
|
1986-10-06 20:36:30 +00:00
|
|
|
{ if (nd->nd_class != Name) {
|
|
|
|
error("illegal variant tag");
|
|
|
|
}
|
1987-05-18 15:57:33 +00:00
|
|
|
else {
|
|
|
|
df = define(nd->nd_IDF, scope, D_FIELD);
|
|
|
|
*palign = lcm(*palign, tp->tp_align);
|
|
|
|
if (!(tp->tp_fund & T_DISCRETE)) {
|
|
|
|
error("illegal type in variant");
|
|
|
|
}
|
|
|
|
df->df_type = tp;
|
|
|
|
df->fld_off = align(*cnt, tp->tp_align);
|
|
|
|
*cnt = df->fld_off + tp->tp_size;
|
|
|
|
df->df_flags |= D_QEXPORTED;
|
|
|
|
}
|
1986-10-06 20:36:30 +00:00
|
|
|
FreeNode(nd);
|
|
|
|
}
|
|
|
|
| /* Old fashioned! the first qualident now represents
|
1986-04-11 11:57:19 +00:00
|
|
|
the type
|
|
|
|
*/
|
1987-10-19 11:28:37 +00:00
|
|
|
{
|
|
|
|
#ifndef STRICT_3RD_ED
|
|
|
|
if (! options['3']) warning(W_OLDFASHIONED,
|
1987-04-29 10:22:07 +00:00
|
|
|
"old fashioned Modula-2 syntax; ':' missing");
|
1987-10-19 11:28:37 +00:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
error("':' missing");
|
1991-03-12 16:52:00 +00:00
|
|
|
tp = qualified_type(&nd);
|
1986-10-06 20:36:30 +00:00
|
|
|
}
|
|
|
|
]
|
|
|
|
| ':' qualtype(&tp)
|
|
|
|
/* Aha, third edition. Well done! */
|
1986-04-11 11:57:19 +00:00
|
|
|
]
|
1987-05-18 15:57:33 +00:00
|
|
|
{ tcnt = *cnt; }
|
1986-04-15 17:51:53 +00:00
|
|
|
OF variant(scope, &tcnt, tp, palign)
|
1986-10-06 20:36:30 +00:00
|
|
|
{ max = tcnt; tcnt = *cnt; }
|
1986-03-27 17:37:41 +00:00
|
|
|
[
|
1986-10-06 20:36:30 +00:00
|
|
|
'|' variant(scope, &tcnt, tp, palign)
|
|
|
|
{ if (tcnt > max) max = tcnt; tcnt = *cnt; }
|
1986-03-27 17:37:41 +00:00
|
|
|
]*
|
1986-04-15 17:51:53 +00:00
|
|
|
[ ELSE FieldListSequence(scope, &tcnt, palign)
|
1986-10-06 20:36:30 +00:00
|
|
|
{ if (tcnt > max) max = tcnt; }
|
1988-02-10 14:06:34 +00:00
|
|
|
|
|
|
|
|
]
|
1986-03-20 14:52:03 +00:00
|
|
|
END
|
1986-10-06 20:36:30 +00:00
|
|
|
{ *cnt = max; }
|
1988-02-10 14:06:34 +00:00
|
|
|
|
|
|
|
|
]
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
variant(struct scope *scope; arith *cnt; struct type *tp; int *palign;)
|
1986-04-15 17:51:53 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct node *nd;
|
1986-04-15 17:51:53 +00:00
|
|
|
} :
|
|
|
|
[
|
1986-10-06 20:36:30 +00:00
|
|
|
CaseLabelList(&tp, &nd)
|
|
|
|
{ /* Ignore the cases for the time being.
|
|
|
|
Maybe a checking version will be supplied
|
1987-04-29 10:22:07 +00:00
|
|
|
later ???
|
1986-10-06 20:36:30 +00:00
|
|
|
*/
|
|
|
|
FreeNode(nd);
|
|
|
|
}
|
1986-04-17 09:28:09 +00:00
|
|
|
':' FieldListSequence(scope, cnt, palign)
|
1988-02-10 14:06:34 +00:00
|
|
|
|
|
|
|
|
]
|
1986-10-06 20:36:30 +00:00
|
|
|
/* Changed rule in new modula-2 */
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
CaseLabelList(struct type **ptp; struct node **pnd;):
|
1986-04-17 09:28:09 +00:00
|
|
|
CaseLabels(ptp, pnd)
|
|
|
|
[
|
1987-08-10 21:43:47 +00:00
|
|
|
{ *pnd = dot2node(Link, *pnd, NULLNODE); }
|
1991-03-12 16:52:00 +00:00
|
|
|
',' CaseLabels(ptp, &((*pnd)->nd_RIGHT))
|
|
|
|
{ pnd = &((*pnd)->nd_RIGHT); }
|
1986-04-17 09:28:09 +00:00
|
|
|
]*
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
CaseLabels(struct type **ptp; register struct node **pnd;)
|
1986-04-06 17:42:56 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
register struct node *nd;
|
1986-04-06 17:42:56 +00:00
|
|
|
}:
|
1986-10-06 20:36:30 +00:00
|
|
|
ConstExpression(pnd)
|
1987-07-30 13:37:39 +00:00
|
|
|
{
|
1988-11-29 13:13:03 +00:00
|
|
|
if (*ptp != 0) {
|
2019-05-10 17:09:03 +00:00
|
|
|
struct type *tp = intorcard(*ptp,
|
1989-03-20 13:32:06 +00:00
|
|
|
BaseType((*pnd)->nd_type));
|
1988-11-29 13:13:03 +00:00
|
|
|
if (tp) *ptp = tp;
|
|
|
|
ChkCompat(pnd, *ptp, "case label");
|
1987-07-30 13:37:39 +00:00
|
|
|
}
|
|
|
|
nd = *pnd;
|
1988-04-29 09:16:51 +00:00
|
|
|
nd->nd_type = BaseType(nd->nd_type); /* ??? */
|
1987-11-26 14:15:24 +00:00
|
|
|
if (! (nd->nd_type->tp_fund & T_DISCRETE) ||
|
|
|
|
nd->nd_type->tp_size > word_size) {
|
1987-11-24 13:22:04 +00:00
|
|
|
node_error(nd, "illegal type in case label");
|
|
|
|
}
|
1987-07-30 13:37:39 +00:00
|
|
|
}
|
1986-04-15 17:51:53 +00:00
|
|
|
[
|
1987-10-28 11:10:30 +00:00
|
|
|
UPTO { *pnd = nd = dot2node(Link,nd,NULLNODE);
|
1991-03-12 16:52:00 +00:00
|
|
|
nd->nd_type = nd->nd_LEFT->nd_type;
|
1987-10-28 11:10:30 +00:00
|
|
|
}
|
1991-03-12 16:52:00 +00:00
|
|
|
ConstExpression(&(*pnd)->nd_RIGHT)
|
|
|
|
{ if (!ChkCompat(&((*pnd)->nd_RIGHT), nd->nd_type,
|
1987-07-30 13:37:39 +00:00
|
|
|
"case label")) {
|
1987-05-18 15:57:33 +00:00
|
|
|
nd->nd_type = error_type;
|
1986-10-06 20:36:30 +00:00
|
|
|
}
|
1991-03-12 16:52:00 +00:00
|
|
|
else if (! chk_bounds(nd->nd_LEFT->nd_INT,
|
|
|
|
nd->nd_RIGHT->nd_INT,
|
1988-04-29 09:16:51 +00:00
|
|
|
nd->nd_type->tp_fund)) {
|
1987-10-28 11:10:30 +00:00
|
|
|
node_error(nd,
|
|
|
|
"lower bound exceeds upper bound in case label range");
|
|
|
|
}
|
|
|
|
|
1986-10-06 20:36:30 +00:00
|
|
|
}
|
1988-02-10 14:06:34 +00:00
|
|
|
|
|
|
|
|
]
|
1987-07-30 13:37:39 +00:00
|
|
|
{
|
1987-05-18 15:57:33 +00:00
|
|
|
*ptp = nd->nd_type;
|
1986-10-06 20:36:30 +00:00
|
|
|
}
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
SetType(struct type **ptp;)
|
|
|
|
{ struct type *tp;
|
1990-03-06 13:22:30 +00:00
|
|
|
} :
|
|
|
|
SET OF SimpleType(&tp)
|
|
|
|
{ *ptp = set_type(tp); }
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
1986-03-29 01:04:49 +00:00
|
|
|
/* In a pointer type definition, the type pointed at does not
|
|
|
|
have to be declared yet, so be careful about identifying
|
1990-03-06 13:22:30 +00:00
|
|
|
type-identifiers.
|
1986-03-29 01:04:49 +00:00
|
|
|
*/
|
2019-05-10 17:09:03 +00:00
|
|
|
PointerType(register struct type **ptp;)
|
|
|
|
{ register struct type *tp;
|
1990-03-06 13:22:30 +00:00
|
|
|
} :
|
|
|
|
{ tp = construct_type(T_POINTER, NULLTYPE); }
|
1986-03-27 17:37:41 +00:00
|
|
|
POINTER TO
|
1990-03-06 13:22:30 +00:00
|
|
|
[ %if (type_or_forward(tp))
|
|
|
|
type(&(tp->tp_next))
|
1986-03-27 17:37:41 +00:00
|
|
|
|
|
1987-04-29 10:22:07 +00:00
|
|
|
IDENT
|
1986-03-27 17:37:41 +00:00
|
|
|
]
|
1990-03-06 13:22:30 +00:00
|
|
|
{ *ptp = tp; }
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
qualtype(struct type **ptp;)
|
1986-07-08 14:59:02 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct node *nd;
|
1986-07-08 14:59:02 +00:00
|
|
|
} :
|
1987-04-29 10:22:07 +00:00
|
|
|
qualident(&nd)
|
1991-03-12 16:52:00 +00:00
|
|
|
{ *ptp = qualified_type(&nd); }
|
1986-11-17 11:41:28 +00:00
|
|
|
;
|
1986-07-08 14:59:02 +00:00
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
ProcedureType(struct type **ptp;)
|
1990-03-06 13:22:30 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct paramlist *pr = 0;
|
1990-03-06 13:22:30 +00:00
|
|
|
arith parmaddr = 0;
|
2019-05-10 17:09:03 +00:00
|
|
|
struct type *tp = 0;
|
1990-03-06 13:22:30 +00:00
|
|
|
} :
|
1986-10-06 20:36:30 +00:00
|
|
|
PROCEDURE
|
|
|
|
[
|
1990-03-06 13:22:30 +00:00
|
|
|
FormalTypeList(&pr, &parmaddr, &tp)
|
1987-07-13 10:30:37 +00:00
|
|
|
|
|
|
|
|
]
|
1990-03-06 13:22:30 +00:00
|
|
|
{ *ptp = proc_type(tp, pr, parmaddr); }
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
FormalTypeList(struct paramlist **ppr; arith *pparmaddr; struct type **ptp;) :
|
1986-10-06 20:36:30 +00:00
|
|
|
'('
|
1986-03-29 01:04:49 +00:00
|
|
|
[
|
1990-03-06 13:22:30 +00:00
|
|
|
VarFormalType(ppr, pparmaddr)
|
1986-03-29 01:04:49 +00:00
|
|
|
[
|
1990-03-06 13:22:30 +00:00
|
|
|
',' VarFormalType(ppr, pparmaddr)
|
1986-03-29 01:04:49 +00:00
|
|
|
]*
|
1988-02-10 14:06:34 +00:00
|
|
|
|
|
|
|
|
]
|
1986-03-29 01:04:49 +00:00
|
|
|
')'
|
1986-07-08 14:59:02 +00:00
|
|
|
[ ':' qualtype(ptp)
|
1990-03-06 13:22:30 +00:00
|
|
|
|
|
1987-08-03 09:09:07 +00:00
|
|
|
]
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
VarFormalType(struct paramlist **ppr; arith *pparmaddr;)
|
1987-05-18 15:57:33 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct type *tp;
|
1987-05-18 15:57:33 +00:00
|
|
|
int isvar;
|
|
|
|
} :
|
|
|
|
var(&isvar)
|
|
|
|
FormalType(&tp)
|
1990-03-06 13:22:30 +00:00
|
|
|
{ EnterParamList(ppr,NULLNODE,tp,isvar,pparmaddr); }
|
1987-05-18 15:57:33 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
var(int *VARp;) :
|
|
|
|
[
|
|
|
|
VAR { *VARp = D_VARPAR; }
|
|
|
|
|
|
|
|
|
/* empty */ { *VARp = D_VALPAR; }
|
|
|
|
]
|
1986-07-08 14:59:02 +00:00
|
|
|
;
|
|
|
|
|
1986-03-26 15:11:02 +00:00
|
|
|
ConstantDeclaration
|
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct idf *id;
|
|
|
|
struct node *nd;
|
|
|
|
register struct def *df;
|
1986-03-26 15:11:02 +00:00
|
|
|
}:
|
1986-07-08 14:59:02 +00:00
|
|
|
IDENT { id = dot.TOK_IDF; }
|
|
|
|
'=' ConstExpression(&nd)
|
1987-07-30 13:37:39 +00:00
|
|
|
{ df = define(id,CurrentScope,D_CONST);
|
|
|
|
df->con_const = nd->nd_token;
|
|
|
|
df->df_type = nd->nd_type;
|
|
|
|
FreeNode(nd);
|
|
|
|
}
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
VariableDeclaration
|
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
struct node *VarList;
|
|
|
|
register struct node *nd;
|
|
|
|
struct type *tp;
|
1986-03-20 14:52:03 +00:00
|
|
|
} :
|
1986-06-06 02:22:09 +00:00
|
|
|
IdentAddr(&VarList)
|
|
|
|
{ nd = VarList; }
|
1986-08-26 14:33:24 +00:00
|
|
|
[ %persistent
|
1991-03-12 16:52:00 +00:00
|
|
|
',' IdentAddr(&(nd->nd_RIGHT))
|
|
|
|
{ nd = nd->nd_RIGHT; }
|
1986-06-06 02:22:09 +00:00
|
|
|
]*
|
1986-03-27 17:37:41 +00:00
|
|
|
':' type(&tp)
|
1986-06-10 13:18:52 +00:00
|
|
|
{ EnterVarList(VarList, tp, proclevel > 0); }
|
1986-03-20 14:52:03 +00:00
|
|
|
;
|
1986-04-15 17:51:53 +00:00
|
|
|
|
2019-05-10 17:09:03 +00:00
|
|
|
IdentAddr(struct node **pnd;)
|
1987-07-30 13:37:39 +00:00
|
|
|
{
|
2019-05-10 17:09:03 +00:00
|
|
|
register struct node *nd;
|
1987-07-30 13:37:39 +00:00
|
|
|
} :
|
1991-03-12 16:52:00 +00:00
|
|
|
IDENT { nd = dot2leaf(Name);
|
|
|
|
*pnd = dot2node(Link, nd, NULLNODE);
|
|
|
|
}
|
1986-11-28 11:59:08 +00:00
|
|
|
[ '['
|
1991-03-12 16:52:00 +00:00
|
|
|
ConstExpression(&(nd->nd_NEXT))
|
1986-11-28 11:59:08 +00:00
|
|
|
']'
|
1988-02-10 14:06:34 +00:00
|
|
|
|
|
|
|
|
]
|
1986-04-15 17:51:53 +00:00
|
|
|
;
|