/* * (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 */ /* S T A T E M E N T S */ /* $Header$ */ { #include #include #include #include "idf.h" #include "LLlex.h" #include "scope.h" #include "def.h" #include "type.h" #include "node.h" static int loopcount = 0; /* Count nested loops */ int Roption; extern char options[]; extern struct node *EmptyStatement; } statement(register struct node **pnd;) { register struct node *nd; extern int return_occurred; } : /* 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'; nd->nd_INT = Roption; *pnd = nd = dot2node(Link, nd, NULLNODE); nd->nd_symb = ';'; pnd = &(nd->nd_right); } } ] [ /* * This part is not in the reference grammar. The reference grammar * states : assignment | ProcedureCall | ... * but this gives LL(1) conflicts */ designator(pnd) [ { nd = dot2node(Call, *pnd, NULLNODE); nd->nd_symb = '('; } ActualParameters(&(nd->nd_right))? | [ BECOMES | '=' { error("':=' expected instead of '='"); DOT = BECOMES; } ] { nd = dot2node(Stat, *pnd, NULLNODE); } expression(&(nd->nd_right)) ] { *pnd = nd; } /* * end of changed part */ | IfStatement(pnd) | CaseStatement(pnd) | WHILE { *pnd = nd = dot2leaf(Stat); } expression(&(nd->nd_left)) DO StatementSequence(&(nd->nd_right)) END | REPEAT { *pnd = nd = dot2leaf(Stat); } StatementSequence(&(nd->nd_left)) UNTIL expression(&(nd->nd_right)) | { loopcount++; } LOOP { *pnd = nd = dot2leaf(Stat); } StatementSequence(&((*pnd)->nd_right)) END { loopcount--; } | ForStatement(pnd) | WithStatement(pnd) | EXIT { if (!loopcount) error("EXIT not in a LOOP"); *pnd = dot2leaf(Stat); } | ReturnStatement(pnd) { return_occurred = 1; } | /* empty */ { *pnd = EmptyStatement; } ] ; /* * The next two rules in-line in "Statement", because of an LL(1) conflict assignment: designator BECOMES expression ; ProcedureCall: designator ActualParameters? ; */ StatementSequence(register struct node **pnd;) { struct node *nd; register struct node *nd1; } : statement(pnd) [ %persistent ';' statement(&nd) { nd1 = dot2node(Link, *pnd, nd); *pnd = nd1; nd1->nd_symb = ';'; pnd = &(nd1->nd_right); } ]* ; IfStatement(struct node **pnd;) { register struct node *nd; } : IF { nd = dot2leaf(Stat); *pnd = nd; } expression(&(nd->nd_left)) THEN { nd->nd_right = dot2leaf(Link); nd = nd->nd_right; } StatementSequence(&(nd->nd_left)) [ ELSIF { nd->nd_right = dot2leaf(Stat); nd = nd->nd_right; nd->nd_symb = IF; } expression(&(nd->nd_left)) THEN { nd->nd_right = dot2leaf(Link); nd = nd->nd_right; } StatementSequence(&(nd->nd_left)) ]* [ ELSE StatementSequence(&(nd->nd_right)) ]? END ; CaseStatement(struct node **pnd;) { register struct node *nd; struct type *tp = 0; } : CASE { *pnd = nd = dot2leaf(Stat); } 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)) ]? END ; case(struct node **pnd; struct type **ptp;) : [ CaseLabelList(ptp, pnd) ':' { *pnd = dot2node(Link, *pnd, NULLNODE); } StatementSequence(&((*pnd)->nd_right)) ]? { *pnd = dot2node(Link, *pnd, NULLNODE); (*pnd)->nd_symb = '|'; } ; /* inline in statement; lack of space WhileStatement(struct node **pnd;) { register struct node *nd; }: WHILE { *pnd = nd = dot2leaf(Stat); } expression(&(nd->nd_left)) DO StatementSequence(&(nd->nd_right)) END ; RepeatStatement(struct node **pnd;) { register struct node *nd; }: REPEAT { *pnd = nd = dot2leaf(Stat); } StatementSequence(&(nd->nd_left)) UNTIL expression(&(nd->nd_right)) ; */ ForStatement(struct node **pnd;) { register struct node *nd, *nd1; struct node *dummy; }: FOR { *pnd = nd = dot2leaf(Stat); } IDENT { nd->nd_IDF = dot.TOK_IDF; } BECOMES { nd->nd_left = nd1 = dot2leaf(Stat); } expression(&(nd1->nd_left)) TO expression(&(nd1->nd_right)) [ BY ConstExpression(&dummy) { if (!(dummy->nd_type->tp_fund & T_INTORCARD)) { error("illegal type in BY clause"); } nd1->nd_INT = dummy->nd_INT; FreeNode(dummy); } | { nd1->nd_INT = 1; } ] DO StatementSequence(&(nd->nd_right)) END ; /* inline in Statement; lack of space LoopStatement(struct node **pnd;): LOOP { *pnd = dot2leaf(Stat); } StatementSequence(&((*pnd)->nd_right)) END ; */ WithStatement(struct node **pnd;) { register struct node *nd; }: WITH { *pnd = nd = dot2leaf(Stat); } designator(&(nd->nd_left)) DO StatementSequence(&(nd->nd_right)) END ; ReturnStatement(struct node **pnd;) { register struct def *df = CurrentScope->sc_definedby; register struct node *nd; } : RETURN { *pnd = nd = dot2leaf(Stat); } [ expression(&(nd->nd_right)) { if (scopeclosed(CurrentScope)) { error("a module body has no result value"); } else if (! ResultType(df->df_type)) { error("procedure \"%s\" has no result value", df->df_idf->id_text); } } | { if (ResultType(df->df_type)) { error("procedure \"%s\" must return a value", df->df_idf->id_text); } } ] ;