/* * (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 */ extern t_node *EmptyStatement; } statement(register t_node **pnd;) { register t_node *nd; extern int return_occurred; } : /* * This part is not in the reference grammar. The reference grammar * states : assignment | ProcedureCall | ... * but this gives LL(1) conflicts */ designator(pnd) [ { nd = dot2node(Stat, *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 t_node **pnd;) { t_node *nd; register t_node *nd1; } : statement(pnd) [ %persistent ';' statement(&nd) { if (nd != EmptyStatement) { nd1 = dot2node(Link, *pnd, nd); *pnd = nd1; nd1->nd_symb = ';'; pnd = &(nd1->nd_right); } } ]* ; IfStatement(t_node **pnd;) { register t_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(t_node **pnd;) { register t_node *nd; t_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(t_node **pnd; t_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(t_node **pnd;) { register t_node *nd; }: WHILE { *pnd = nd = dot2leaf(Stat); } expression(&(nd->nd_left)) DO StatementSequence(&(nd->nd_right)) END ; RepeatStatement(t_node **pnd;) { register t_node *nd; }: REPEAT { *pnd = nd = dot2leaf(Stat); } StatementSequence(&(nd->nd_left)) UNTIL expression(&(nd->nd_right)) ; */ ForStatement(t_node **pnd;) { register t_node *nd, *nd1; t_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(t_node **pnd;): LOOP { *pnd = dot2leaf(Stat); } StatementSequence(&((*pnd)->nd_right)) END ; */ WithStatement(t_node **pnd;) { register t_node *nd; }: WITH { *pnd = nd = dot2leaf(Stat); } designator(&(nd->nd_left)) DO StatementSequence(&(nd->nd_right)) END ; ReturnStatement(t_node **pnd;) { register t_def *df = CurrentScope->sc_definedby; register t_node *nd; } : RETURN { *pnd = nd = dot2leaf(Stat); } [ expression(&(nd->nd_right)) { if (scopeclosed(CurrentScope)) { error("a module body cannot return a value"); } else if (! ResultType(df->df_type)) { error("procedure \"%s\" is not a function, so cannot return a value", df->df_idf->id_text); } } | { if (ResultType(df->df_type)) { error("function procedure \"%s\" must return a value", df->df_idf->id_text); } } ] ;