/* S T A T E M E N T S */ { #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 */ } statement(register struct node **pnd;) { register struct 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 = MkNode(Call, *pnd, NULLNODE, &dot); nd->nd_symb = '('; } ActualParameters(&(nd->nd_right))? | BECOMES { nd = MkNode(Stat, *pnd, NULLNODE, &dot); } expression(&(nd->nd_right)) ] { *pnd = nd; } /* * end of changed part */ | IfStatement(pnd) | CaseStatement(pnd) | WhileStatement(pnd) | RepeatStatement(pnd) | { loopcount++; } LoopStatement(pnd) { loopcount--; } | ForStatement(pnd) | WithStatement(pnd) | EXIT { if (!loopcount) error("EXIT not in a LOOP"); *pnd = MkLeaf(Stat, &dot); } | ReturnStatement(pnd) { return_occurred = 1; } | /* empty */ { *pnd = 0; } ; /* * 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; } : statement(pnd) [ %persistent ';' statement(&nd) { if (nd) { register struct node *nd1 = MkNode(Link, *pnd, nd, &dot); *pnd = nd1; nd1->nd_symb = ';'; pnd = &(nd1->nd_right); } } ]* ; IfStatement(struct node **pnd;) { register struct node *nd; } : IF { nd = MkLeaf(Stat, &dot); *pnd = nd; } expression(&(nd->nd_left)) THEN { nd->nd_right = MkLeaf(Link, &dot); nd = nd->nd_right; } StatementSequence(&(nd->nd_left)) [ ELSIF { nd->nd_right = MkLeaf(Stat, &dot); nd = nd->nd_right; nd->nd_symb = IF; } expression(&(nd->nd_left)) THEN { nd->nd_right = MkLeaf(Link, &dot); 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 = MkLeaf(Stat, &dot); } 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 = MkNode(Link, *pnd, NULLNODE, &dot); } StatementSequence(&((*pnd)->nd_right)) ]? { *pnd = MkNode(Link, *pnd, NULLNODE, &dot); (*pnd)->nd_symb = '|'; } ; WhileStatement(struct node **pnd;) { register struct node *nd; }: WHILE { *pnd = nd = MkLeaf(Stat, &dot); } expression(&(nd->nd_left)) DO StatementSequence(&(nd->nd_right)) END ; RepeatStatement(struct node **pnd;) { register struct node *nd; }: REPEAT { *pnd = nd = MkLeaf(Stat, &dot); } StatementSequence(&(nd->nd_left)) UNTIL expression(&(nd->nd_right)) ; ForStatement(struct node **pnd;) { register struct node *nd, *nd1; struct node *dummy; }: FOR { *pnd = nd = MkLeaf(Stat, &dot); } IDENT { nd->nd_IDF = dot.TOK_IDF; } BECOMES { nd->nd_left = nd1 = MkLeaf(Stat, &dot); } 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 ; LoopStatement(struct node **pnd;): LOOP { *pnd = MkLeaf(Stat, &dot); } StatementSequence(&((*pnd)->nd_right)) END ; WithStatement(struct node **pnd;) { register struct node *nd; }: WITH { *pnd = nd = MkLeaf(Stat, &dot); } 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 = MkLeaf(Stat, &dot); } [ 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); } } ] ;