ack/lang/m2/comp/statement.g

296 lines
5.5 KiB
Plaintext
Raw Normal View History

/*
* (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
/* S T A T E M E N T S */
/* $Header$ */
1986-03-20 14:52:03 +00:00
{
1986-06-26 09:39:36 +00:00
#include <assert.h>
1986-04-06 17:42:56 +00:00
#include <em_arith.h>
1986-04-17 09:28:09 +00:00
#include <em_label.h>
1986-04-28 18:06:58 +00:00
1986-04-22 22:36:16 +00:00
#include "idf.h"
1986-04-06 17:42:56 +00:00
#include "LLlex.h"
1986-04-22 22:36:16 +00:00
#include "scope.h"
#include "def.h"
1986-04-17 09:28:09 +00:00
#include "type.h"
1986-04-06 17:42:56 +00:00
#include "node.h"
1986-04-15 17:51:53 +00:00
static int loopcount = 0; /* Count nested loops */
int Roption;
extern char options[];
extern struct node *EmptyStatement;
1986-03-20 14:52:03 +00:00
}
1986-06-04 09:01:48 +00:00
statement(register struct node **pnd;)
1986-04-06 17:42:56 +00:00
{
1986-04-17 09:28:09 +00:00
register struct node *nd;
1986-10-06 20:36:30 +00:00
extern int return_occurred;
1986-04-06 17:42:56 +00:00
} :
/* We need some method for making sure lookahead is done, so ...
*/
[ PROGRAM
/* LLlex never returns this */
| %default
{ if (options['R'] != Roption) {
Roption = options['R'];
nd = dot2leaf(Option);
nd->nd_symb = 'R';
1987-08-20 13:12:43 +00:00
nd->nd_INT = Roption;
*pnd = nd =
dot2node(Link, nd, NULLNODE);
nd->nd_symb = ';';
pnd = &(nd->nd_right);
}
}
]
[
1986-03-20 14:52:03 +00:00
/*
* This part is not in the reference grammar. The reference grammar
* states : assignment | ProcedureCall | ...
* but this gives LL(1) conflicts
*/
1986-04-17 09:28:09 +00:00
designator(pnd)
[ { nd = dot2node(Call, *pnd, NULLNODE);
1986-04-17 09:28:09 +00:00
nd->nd_symb = '(';
1986-04-09 18:14:49 +00:00
}
1986-04-17 09:28:09 +00:00
ActualParameters(&(nd->nd_right))?
1986-03-20 14:52:03 +00:00
|
[ BECOMES
| '=' { error("':=' expected instead of '='");
DOT = BECOMES;
}
]
{ nd = dot2node(Stat, *pnd, NULLNODE); }
1986-04-17 09:28:09 +00:00
expression(&(nd->nd_right))
1986-03-20 14:52:03 +00:00
]
1986-04-17 09:28:09 +00:00
{ *pnd = nd; }
1986-03-20 14:52:03 +00:00
/*
* end of changed part
*/
|
1986-04-15 17:51:53 +00:00
IfStatement(pnd)
1986-03-20 14:52:03 +00:00
|
1986-04-15 17:51:53 +00:00
CaseStatement(pnd)
1986-03-20 14:52:03 +00:00
|
WHILE { *pnd = nd = dot2leaf(Stat); }
1987-08-03 18:20:55 +00:00
expression(&(nd->nd_left))
DO
StatementSequence(&(nd->nd_right))
END
1986-03-20 14:52:03 +00:00
|
REPEAT { *pnd = nd = dot2leaf(Stat); }
1987-08-03 18:20:55 +00:00
StatementSequence(&(nd->nd_left))
UNTIL
expression(&(nd->nd_right))
1986-03-20 14:52:03 +00:00
|
1986-04-15 17:51:53 +00:00
{ loopcount++; }
LOOP { *pnd = nd = dot2leaf(Stat); }
1987-08-03 18:20:55 +00:00
StatementSequence(&((*pnd)->nd_right))
END
1986-04-15 17:51:53 +00:00
{ loopcount--; }
1986-03-20 14:52:03 +00:00
|
1986-04-15 17:51:53 +00:00
ForStatement(pnd)
1986-03-20 14:52:03 +00:00
|
1986-04-15 17:51:53 +00:00
WithStatement(pnd)
1986-03-20 14:52:03 +00:00
|
EXIT
1986-05-30 18:48:00 +00:00
{ if (!loopcount) error("EXIT not in a LOOP");
*pnd = dot2leaf(Stat);
1986-04-15 17:51:53 +00:00
}
1986-03-20 14:52:03 +00:00
|
1986-05-30 18:48:00 +00:00
ReturnStatement(pnd)
1986-10-06 20:36:30 +00:00
{ return_occurred = 1; }
1986-06-04 09:01:48 +00:00
|
/* empty */ { *pnd = EmptyStatement; }
]
1986-03-20 14:52:03 +00:00
;
/*
* The next two rules in-line in "Statement", because of an LL(1) conflict
assignment:
designator BECOMES expression
;
ProcedureCall:
designator ActualParameters?
;
*/
1986-06-04 09:01:48 +00:00
StatementSequence(register struct node **pnd;)
{
1986-06-17 12:04:05 +00:00
struct node *nd;
register struct node *nd1;
1986-06-04 09:01:48 +00:00
} :
1986-04-15 17:51:53 +00:00
statement(pnd)
1986-09-25 19:39:06 +00:00
[ %persistent
';'
statement(&nd)
{ nd1 = dot2node(Link, *pnd, nd);
*pnd = nd1;
nd1->nd_symb = ';';
pnd = &(nd1->nd_right);
1986-04-15 17:51:53 +00:00
}
]*
1986-03-20 14:52:03 +00:00
;
1986-04-15 17:51:53 +00:00
IfStatement(struct node **pnd;)
1986-04-06 17:42:56 +00:00
{
1986-04-15 17:51:53 +00:00
register struct node *nd;
1986-04-06 17:42:56 +00:00
} :
IF { nd = dot2leaf(Stat);
1986-04-15 17:51:53 +00:00
*pnd = nd;
}
expression(&(nd->nd_left))
THEN { nd->nd_right = dot2leaf(Link);
1986-06-04 09:01:48 +00:00
nd = nd->nd_right;
1986-04-15 17:51:53 +00:00
}
StatementSequence(&(nd->nd_left))
[
ELSIF { nd->nd_right = dot2leaf(Stat);
1986-04-15 17:51:53 +00:00
nd = nd->nd_right;
nd->nd_symb = IF;
}
expression(&(nd->nd_left))
THEN { nd->nd_right = dot2leaf(Link);
1986-04-15 17:51:53 +00:00
nd = nd->nd_right;
}
StatementSequence(&(nd->nd_left))
]*
[
ELSE
StatementSequence(&(nd->nd_right))
]?
1986-03-20 14:52:03 +00:00
END
;
1986-04-15 17:51:53 +00:00
CaseStatement(struct node **pnd;)
1986-04-06 17:42:56 +00:00
{
1986-04-15 17:51:53 +00:00
register struct node *nd;
struct type *tp = 0;
1986-04-06 17:42:56 +00:00
} :
CASE { *pnd = nd = dot2leaf(Stat); }
1986-04-15 17:51:53 +00:00
expression(&(nd->nd_left))
OF
case(&(nd->nd_right), &tp)
{ nd = nd->nd_right; }
[
'|'
case(&(nd->nd_right), &tp)
{ nd = nd->nd_right; }
]*
[ ELSE StatementSequence(&(nd->nd_right))
]?
1986-03-20 14:52:03 +00:00
END
;
1986-04-15 17:51:53 +00:00
case(struct node **pnd; struct type **ptp;) :
1986-04-17 09:28:09 +00:00
[ CaseLabelList(ptp, pnd)
':' { *pnd = dot2node(Link, *pnd, NULLNODE); }
1986-04-15 17:51:53 +00:00
StatementSequence(&((*pnd)->nd_right))
]?
{ *pnd = dot2node(Link, *pnd, NULLNODE);
1986-04-15 17:51:53 +00:00
(*pnd)->nd_symb = '|';
}
1986-03-20 14:52:03 +00:00
;
1987-08-03 18:20:55 +00:00
/* inline in statement; lack of space
1986-04-15 17:51:53 +00:00
WhileStatement(struct node **pnd;)
1986-04-06 17:42:56 +00:00
{
1986-04-15 17:51:53 +00:00
register struct node *nd;
1986-04-06 17:42:56 +00:00
}:
WHILE { *pnd = nd = dot2leaf(Stat); }
1986-04-15 17:51:53 +00:00
expression(&(nd->nd_left))
DO
StatementSequence(&(nd->nd_right))
END
1986-03-20 14:52:03 +00:00
;
1986-04-15 17:51:53 +00:00
RepeatStatement(struct node **pnd;)
1986-04-06 17:42:56 +00:00
{
1986-04-15 17:51:53 +00:00
register struct node *nd;
1986-04-06 17:42:56 +00:00
}:
REPEAT { *pnd = nd = dot2leaf(Stat); }
1986-04-15 17:51:53 +00:00
StatementSequence(&(nd->nd_left))
UNTIL
expression(&(nd->nd_right))
1986-03-20 14:52:03 +00:00
;
1987-08-03 18:20:55 +00:00
*/
1986-03-20 14:52:03 +00:00
1986-04-15 17:51:53 +00:00
ForStatement(struct node **pnd;)
1986-04-06 17:42:56 +00:00
{
1986-10-06 20:36:30 +00:00
register struct node *nd, *nd1;
1986-05-30 18:48:00 +00:00
struct node *dummy;
1986-04-06 17:42:56 +00:00
}:
FOR { *pnd = nd = dot2leaf(Stat); }
1986-06-04 09:01:48 +00:00
IDENT { nd->nd_IDF = dot.TOK_IDF; }
BECOMES { nd->nd_left = nd1 = dot2leaf(Stat); }
1986-10-06 20:36:30 +00:00
expression(&(nd1->nd_left))
1986-05-30 18:48:00 +00:00
TO
1986-10-06 20:36:30 +00:00
expression(&(nd1->nd_right))
1986-04-15 17:51:53 +00:00
[
1986-05-30 18:48:00 +00:00
BY
ConstExpression(&dummy)
1986-07-08 14:59:02 +00:00
{ if (!(dummy->nd_type->tp_fund & T_INTORCARD)) {
1986-05-30 18:48:00 +00:00
error("illegal type in BY clause");
}
1986-10-06 20:36:30 +00:00
nd1->nd_INT = dummy->nd_INT;
1986-05-30 18:48:00 +00:00
FreeNode(dummy);
1986-04-15 17:51:53 +00:00
}
|
1986-10-06 20:36:30 +00:00
{ nd1->nd_INT = 1; }
1986-04-15 17:51:53 +00:00
]
DO
1986-10-06 20:36:30 +00:00
StatementSequence(&(nd->nd_right))
1986-04-15 17:51:53 +00:00
END
1986-03-20 14:52:03 +00:00
;
1987-08-03 18:20:55 +00:00
/* inline in Statement; lack of space
1986-04-15 17:51:53 +00:00
LoopStatement(struct node **pnd;):
LOOP { *pnd = dot2leaf(Stat); }
1986-04-15 17:51:53 +00:00
StatementSequence(&((*pnd)->nd_right))
END
1986-03-20 14:52:03 +00:00
;
1987-08-03 18:20:55 +00:00
*/
1986-03-20 14:52:03 +00:00
1986-04-15 17:51:53 +00:00
WithStatement(struct node **pnd;)
1986-04-06 17:42:56 +00:00
{
1986-04-15 17:51:53 +00:00
register struct node *nd;
1986-04-06 17:42:56 +00:00
}:
WITH { *pnd = nd = dot2leaf(Stat); }
1986-04-15 17:51:53 +00:00
designator(&(nd->nd_left))
DO
StatementSequence(&(nd->nd_right))
END
1986-03-20 14:52:03 +00:00
;
1986-05-30 18:48:00 +00:00
ReturnStatement(struct node **pnd;)
{
register struct def *df = CurrentScope->sc_definedby;
register struct node *nd;
} :
RETURN { *pnd = nd = dot2leaf(Stat); }
1986-05-30 18:48:00 +00:00
[
expression(&(nd->nd_right))
{ if (scopeclosed(CurrentScope)) {
error("a module body has no result value");
}
1986-06-26 09:39:36 +00:00
else if (! ResultType(df->df_type)) {
1986-05-30 18:48:00 +00:00
error("procedure \"%s\" has no result value", df->df_idf->id_text);
}
}
|
1986-06-26 09:39:36 +00:00
{ if (ResultType(df->df_type)) {
1986-05-30 18:48:00 +00:00
error("procedure \"%s\" must return a value", df->df_idf->id_text);
}
}
]
;