475 lines
		
	
	
	
		
			9 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			475 lines
		
	
	
	
		
			9 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| /* S T A T E M E N T S */
 | |
| {
 | |
| #include	<alloc.h>
 | |
| #include	<em.h>
 | |
| #include	<stb.h>
 | |
| 
 | |
| #include	"LLlex.h"
 | |
| #include	"chk_expr.h"
 | |
| #include	"def.h"
 | |
| #include	"desig.h"
 | |
| #include	"f_info.h"
 | |
| #include	"idf.h"
 | |
| #include	"main.h"
 | |
| #include	"misc.h"
 | |
| #include	"node.h"
 | |
| #include	"scope.h"
 | |
| #include	"type.h"
 | |
| #include	"dbsymtab.h"
 | |
| 
 | |
| int slevel = 0;		/* nesting level of statements */
 | |
| }
 | |
| 
 | |
| 
 | |
| /* ISO section 6.8.3.2, p. 128 */
 | |
| CompoundStatement:
 | |
| 	BEGIN StatementSequence END
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.3.1, p. 128 */
 | |
| StatementSequence:
 | |
| 	Statement
 | |
| 	[ %persistent
 | |
| 		';' Statement
 | |
| 	]*
 | |
| 					{ chk_labels(slevel + 1); }
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.1, p. 126 */
 | |
| Statement
 | |
| {
 | |
| 	struct node *nd;
 | |
| } :
 | |
| 					{
 | |
| 					  slevel++;
 | |
| 					}
 | |
| 	[ Label(&nd) ':'
 | |
| 					{ if( nd ) DefLabel(nd, slevel); }
 | |
| 	]?
 | |
| 					{ if( !options['L'] )
 | |
| 						C_lin((arith) dot.tk_lineno);
 | |
| #ifdef DBSYMTAB
 | |
| 					  if (options['g']) {
 | |
| 					    static int ms_lineno;
 | |
| 
 | |
| 					    if (ms_lineno != dot.tk_lineno) {
 | |
| 						C_ms_std((char *) 0, N_SLINE, (int) dot.tk_lineno);
 | |
| 						ms_lineno = dot.tk_lineno;
 | |
| 					    }
 | |
| 					  }
 | |
| #endif /* DBSYMTAB */
 | |
| 					}
 | |
| 	[
 | |
| 		SimpleStatement
 | |
| 	|
 | |
| 		StructuredStatement
 | |
| 	]
 | |
| 					{ slevel--; }
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.2.1, p. 126 */
 | |
| SimpleStatement
 | |
| {
 | |
| 	struct node *pnd, *expp;
 | |
| 	unsigned short line;
 | |
| } :
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference is not LL(1), and this gives conflicts.
 | |
| 	 * Note : the grammar states : AssignmentStatement |
 | |
| 	 *				ProcedureStatement | ...
 | |
| 	 * In order to add assertions, there is an extra entry, which gives
 | |
| 	 * a conflict. This conflict is then resolved using an %if clause.
 | |
| 	 */
 | |
| 	EmptyStatement
 | |
| |
 | |
| 	GotoStatement
 | |
| |
 | |
| 	/* Evidently this is the beginning of the changed part
 | |
| 	 */
 | |
| 	%if( !options['s'] && !strcmp(dot.TOK_IDF->id_text, "assert") )
 | |
| 	IDENT			{ line = LineNumber; }
 | |
| 		Expression(&expp)
 | |
| 				{ AssertStat(expp, line);
 | |
| 				  FreeNode(expp);
 | |
| 				}
 | |
| |
 | |
| 	IDENT			{ pnd = MkLeaf(Name, &dot); }
 | |
| 	[	%default
 | |
| 
 | |
| 		/* At this point the IDENT can be a FunctionIdentifier in
 | |
| 		 * which case the VariableAccessTail must be empty.
 | |
| 		 */
 | |
| 		VariableAccessTail(&pnd)
 | |
| 		[
 | |
| 			%default
 | |
| 			BECOMES
 | |
| 		|
 | |
| 			'='	{ error("':=' expected instead of '='"); }
 | |
| 		]
 | |
| 		Expression(&expp)
 | |
| 				{ AssignStat(pnd, expp); }
 | |
| 	|
 | |
| 				{ pnd = MkNode(Call, pnd, NULLNODE, &dot); }
 | |
| 		ActualParameterList(&(pnd->nd_right))?
 | |
| 				{ ProcStat(pnd);
 | |
| 
 | |
| 				  if( !err_occurred )
 | |
| 					CodeCall(pnd);
 | |
| 
 | |
| 				  FreeNode(pnd);
 | |
| 				}
 | |
| 
 | |
| 	]
 | |
| |
 | |
| 	InputOutputStatement
 | |
| 	/* end of changed part
 | |
| 	 */
 | |
| ;
 | |
| 
 | |
| InputOutputStatement
 | |
| {
 | |
| 	struct node *nd = NULLNODE;
 | |
| } :
 | |
| 	/* This is a new rule because the grammar specified by the standard
 | |
| 	 * is not exactly LL(1) (see SimpleStatement).
 | |
| 	 */
 | |
| 	[
 | |
| 		READ ReadParameterList(&nd)		{ ChkRead(nd); }
 | |
| 	|
 | |
| 		READLN ReadParameterList(&nd)?		{ ChkReadln(nd); }
 | |
| 	|
 | |
| 		WRITE WriteParameterList(&nd)		{ ChkWrite(nd); }
 | |
| 	|
 | |
| 		WRITELN WriteParameterList(&nd)?	{ ChkWriteln(nd); }
 | |
| 	]
 | |
| 							{ FreeNode(nd); }
 | |
| ;
 | |
| 
 | |
| EmptyStatement:
 | |
| 	/* empty */
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.3.1, p. 128 */
 | |
| StructuredStatement:
 | |
| 	CompoundStatement
 | |
| |
 | |
| 	ConditionalStatement
 | |
| |
 | |
| 	RepetitiveStatement
 | |
| |
 | |
| 	WithStatement
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.2.4, p. 127 */
 | |
| GotoStatement
 | |
| {
 | |
| 	struct node *nd;
 | |
| } :
 | |
| 	GOTO Label(&nd)
 | |
| 					{ if( nd ) TstLabel(nd, slevel); }
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.3.3, p. 128 */
 | |
| ConditionalStatement:
 | |
| 	%default
 | |
| 	CaseStatement
 | |
| |
 | |
| 	IfStatement
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.3.6, p. 129 */
 | |
| RepetitiveStatement:
 | |
| 	RepeatStatement
 | |
| |
 | |
| 	WhileStatement
 | |
| |
 | |
| 	ForStatement
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.3.10, p. 132 */
 | |
| WithStatement
 | |
| {
 | |
| 	struct scopelist *Save = CurrVis;
 | |
| 	struct node *nd;
 | |
| } :
 | |
| 	WITH
 | |
| 	RecordVariableList(&nd)
 | |
| 	DO
 | |
| 	Statement	{ EndWith(Save, nd);
 | |
| 			  chk_labels(slevel + 1);
 | |
| 			}
 | |
| ;
 | |
| 
 | |
| RecordVariableList(register struct node **pnd;)
 | |
| {
 | |
| 	struct node *nd;
 | |
| } :
 | |
| 	RecordVariable(&nd)
 | |
| 				{ *pnd = nd = MkNode(Link, nd, NULLNODE, &dot);
 | |
| 				  nd->nd_symb = ',';
 | |
| 				}
 | |
| 	[ %persistent
 | |
| 		','		{ nd->nd_right = MkLeaf(Link, &dot);
 | |
| 				  nd = nd->nd_right;
 | |
| 				}
 | |
| 		RecordVariable(&(nd->nd_left))
 | |
| 	]*
 | |
| ;
 | |
| 
 | |
| RecordVariable(register struct node **pnd;):
 | |
| 	VariableAccess(pnd)
 | |
| 				{ WithStat(*pnd); }
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.3.4, p. 128 */
 | |
| IfStatement
 | |
| {
 | |
| 	struct node *nd;
 | |
| 	label l1 = ++text_label;
 | |
| 	label l2 = ++text_label;
 | |
| } :
 | |
| 	IF
 | |
| 	BooleanExpression(&nd)
 | |
| 					{ struct desig ds;
 | |
| 					
 | |
| 					  ds = InitDesig;
 | |
| 					  if( !err_occurred )
 | |
| 						CodeExpr(nd, &ds, l1);
 | |
| 					  FreeNode(nd);
 | |
| 					}
 | |
| 	THEN
 | |
| 	Statement			{ chk_labels(slevel + 1); }
 | |
| 	[ %prefer	/* closest matching */
 | |
| 		ELSE
 | |
| 					{ C_bra(l2);
 | |
| 					  C_df_ilb(l1);
 | |
| 					}
 | |
| 		Statement
 | |
| 					{ C_df_ilb(l2);
 | |
| 					  chk_labels(slevel + 1);
 | |
| 					}
 | |
| 	|
 | |
| 		/* empty */
 | |
| 					{ C_df_ilb(l1); }
 | |
| 	]
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.3.5, p. 128 */
 | |
| CaseStatement
 | |
| {
 | |
| 	struct node *casend, *nd;
 | |
| 	label exit_label;
 | |
| } :
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference states that a semicolon is optional before END,
 | |
| 	 * and this is not LL(1).
 | |
| 	 */
 | |
| 	CASE				{ casend = nd = MkLeaf(Link, &dot);
 | |
| 					  casend->nd_lab = ++text_label;
 | |
| 					  exit_label = ++text_label;
 | |
| 					}
 | |
| 	Expression(&(nd->nd_left))
 | |
| 					{ CaseExpr(casend); }
 | |
| 	OF
 | |
| 	CaseListElement(&(nd->nd_right), exit_label)
 | |
| 					{ nd = nd->nd_right; }
 | |
| 	CaseListElementTail(&(nd->nd_right), exit_label)
 | |
| 	END
 | |
| 					{ CaseEnd(casend, exit_label); }
 | |
| ;
 | |
| 
 | |
| CaseListElementTail(register struct node **pnd; label exit_label;):
 | |
| 	/* This is a new rule, all because of a silly semicolon
 | |
| 	 */
 | |
| 	/* empty */
 | |
| |
 | |
| %default
 | |
| 	';'
 | |
| 	[
 | |
| 		/* empty */
 | |
| 	|
 | |
| 		CaseListElement(pnd, exit_label)
 | |
| 		CaseListElementTail(&((*pnd)->nd_right), exit_label)
 | |
| 	]
 | |
| ;
 | |
| 
 | |
| CaseListElement(register struct node **pnd; label exit_label;):
 | |
| 	CaseConstantList(pnd)
 | |
| 	':'
 | |
| 				{ *pnd = MkNode(Link, *pnd, NULLNODE, &dot);
 | |
| 				  (*pnd)->nd_lab = ++text_label;
 | |
| 				  C_df_ilb(text_label);
 | |
| 				}
 | |
| 	Statement		{ C_bra(exit_label);
 | |
| 				  chk_labels(slevel + 1);
 | |
| 				}
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.3.7, p. 129 */
 | |
| RepeatStatement
 | |
| {
 | |
| 	struct node *nd;
 | |
| 	label repeatlb = ++text_label;
 | |
| } :
 | |
| 	REPEAT
 | |
| 					{ C_df_ilb(repeatlb); }
 | |
| 	StatementSequence
 | |
| 	UNTIL
 | |
| 	BooleanExpression(&nd)
 | |
| 					{ struct desig ds;
 | |
| 
 | |
| 					  ds = InitDesig;
 | |
| 					  if( !err_occurred )
 | |
| 						CodeExpr(nd, &ds, repeatlb);
 | |
| 					  FreeNode(nd);
 | |
| 					}
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.3.8, p. 129 */
 | |
| WhileStatement
 | |
| {
 | |
| 	struct node *nd;
 | |
| 	label whilelb = ++text_label;
 | |
| 	label exitlb = ++text_label;
 | |
| 
 | |
| } :
 | |
| 	WHILE
 | |
| 					{ C_df_ilb(whilelb); }
 | |
| 	BooleanExpression(&nd)
 | |
| 					{ struct desig ds;
 | |
| 
 | |
| 					  ds = InitDesig;
 | |
| 					  if( !err_occurred )
 | |
| 						CodeExpr(nd, &ds, exitlb);
 | |
| 					  FreeNode(nd);
 | |
| 					}
 | |
| 	DO
 | |
| 	Statement
 | |
| 					{ C_bra(whilelb);
 | |
| 					  C_df_ilb(exitlb);
 | |
| 					  chk_labels(slevel + 1);
 | |
| 					}
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.8.3.9, p. 130 */
 | |
| ForStatement
 | |
| {
 | |
| 	register struct node *nd;
 | |
| 	int stepsize;
 | |
| 	label l1 = ++text_label;
 | |
| 	label l2 = ++text_label;
 | |
| 	arith tmp2 = (arith) 0;
 | |
| } :
 | |
| 	FOR
 | |
| 	/* ControlVariable must be an EntireVariable */
 | |
| 	IDENT			{ nd = MkLeaf(Name, &dot); }
 | |
| 	BECOMES
 | |
| 	Expression(&(nd->nd_left))
 | |
| 	[
 | |
| 		TO		{ stepsize = 1; }
 | |
| 	|
 | |
| 		DOWNTO		{ stepsize = -1; }
 | |
| 	]
 | |
| 	Expression(&(nd->nd_right))
 | |
| 				{ ChkForStat(nd);
 | |
| 				  if( !err_occurred )	{
 | |
| 					CodePExpr(nd->nd_left);
 | |
| 					C_dup(int_size);
 | |
| 					tmp2 = CodeInitFor(nd->nd_right, 2);
 | |
| 				  	CodeFor(nd, stepsize, l1, l2);
 | |
| 				  }
 | |
| 				}
 | |
| 	DO
 | |
| 	Statement
 | |
| 				{ if( !err_occurred )
 | |
| 				       CodeEndFor(nd, stepsize, l1, l2, tmp2);
 | |
| 				  EndForStat(nd);
 | |
| 				  chk_labels(slevel + 1);
 | |
| 				  FreeNode(nd);
 | |
| 				  if( tmp2 ) FreeInt(tmp2);
 | |
| 				}
 | |
| ;
 | |
| 
 | |
| /* SPECIALSPECIALSPECIALSPECIALSPECIALSPECIALSPECIALSPECIALSPECIALSPECIAL */
 | |
| /* ISO section 6.9, p. 132-136 */
 | |
| ReadParameterList(register struct node **pnd;)
 | |
| {
 | |
| 	register struct node *nd;
 | |
| } :
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference is not LL(1), and this gives conflicts.
 | |
| 	 */
 | |
| 	'('
 | |
| 		VariableAccess(pnd)	/* possibly a FileVariable */
 | |
| 					{ *pnd = nd =
 | |
| 					     MkNode(Link, *pnd, NULLNODE, &dot);
 | |
| 					  nd->nd_symb = ',';
 | |
| 					}
 | |
| 		[ %persistent
 | |
| 			',' 		{ nd->nd_right = MkLeaf(Link, &dot);
 | |
| 					  nd = nd->nd_right;
 | |
| 					}
 | |
| 			VariableAccess(&(nd->nd_left))
 | |
| 		]*
 | |
| 	')'
 | |
| ;
 | |
| 
 | |
| WriteParameterList(register struct node **pnd;)
 | |
| {
 | |
| 	register struct node *nd;
 | |
| } :
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference is not LL(1), and this gives conflicts.
 | |
| 	 */
 | |
| 	'('
 | |
| 		/* Only the first WriteParameter can be a FileVariable !!
 | |
| 		 */
 | |
| 		WriteParameter(pnd)
 | |
| 					{ *pnd = nd =
 | |
| 					     MkNode(Link, *pnd, NULLNODE, &dot);
 | |
| 					  nd->nd_symb = ',';
 | |
| 					}
 | |
| 		[ %persistent
 | |
| 			',' 		{ nd->nd_right = MkLeaf(Link, &dot);
 | |
| 					  nd = nd->nd_right;
 | |
| 					}
 | |
| 			WriteParameter(&(nd->nd_left))
 | |
| 		]*
 | |
| 	')'
 | |
| ;
 | |
| 
 | |
| WriteParameter(register struct node **pnd;)
 | |
| {
 | |
| 	register struct node *nd;
 | |
| } :
 | |
| 	Expression(pnd)
 | |
| 					{ if( !ChkExpression(*pnd) )
 | |
| 						(*pnd)->nd_type = error_type;
 | |
| 					  MarkUsed(*pnd);
 | |
| 					  *pnd = nd =
 | |
| 					     MkNode(Link, *pnd, NULLNODE, &dot);
 | |
| 					  nd->nd_symb = ':';
 | |
| 					}
 | |
| 	[
 | |
| 	/* Here the first Expression can't be a FileVariable
 | |
| 	 */
 | |
| 		':'			{ nd->nd_right = MkLeaf(Link, &dot);
 | |
| 					  nd = nd->nd_right;
 | |
| 					}
 | |
| 		Expression(&(nd->nd_left))
 | |
| 					{ if( !ChkExpression(nd->nd_left) )
 | |
| 					      nd->nd_left->nd_type = error_type;
 | |
| 					  MarkUsed(nd->nd_left);
 | |
| 					}
 | |
| 		[
 | |
| 			':'		{ nd->nd_right = MkLeaf(Link, &dot);
 | |
| 					  nd = nd->nd_right;
 | |
| 					}
 | |
| 			Expression(&(nd->nd_left))
 | |
| 					{ if( !ChkExpression(nd->nd_left) )
 | |
| 					      nd->nd_left->nd_type = error_type;
 | |
| 					  MarkUsed(nd->nd_left);
 | |
| 					}
 | |
| 		]?
 | |
| 	]?
 | |
| ;
 |