Exemplo n.º 1
0
void constDefinitions (void) {

	//-------------------------------------------------------
	// Loop to process definitions separated by semicolons...
	while (curToken == TKN_IDENTIFIER) {
		SymTableNodePtr constantIdPtr;
		searchAndEnterLocalSymTable(constantIdPtr);
		constantIdPtr->defn.key = DFN_CONST;
		constantIdPtr->library = CurLibrary;

		getToken();
		ifTokenGetElseError(TKN_EQUAL, ABL_ERR_SYNTAX_MISSING_EQUAL);

		doConst(constantIdPtr);
		analyzeConstDefn(constantIdPtr);

		//---------------------------------
		// Error synchronize: should be a ;
		synchronize(followDeclarationList, declarationStartList, statementStartList);
		if (curToken == TKN_SEMICOLON)
			getToken();
		else if (tokenIn(declarationStartList) || tokenIn(statementStartList))
			syntaxError(ABL_ERR_SYNTAX_MISSING_SEMICOLON);
	}
}
Exemplo n.º 2
0
void typeDefinitions (void) {

	while (curToken == TKN_IDENTIFIER) {
		SymTableNodePtr typeIdPtr;
		searchAndEnterLocalSymTable(typeIdPtr);
		typeIdPtr->defn.key = DFN_TYPE;
		typeIdPtr->library = CurLibrary;

		getToken();
		ifTokenGetElseError(TKN_EQUAL, ABL_ERR_SYNTAX_MISSING_EQUAL);

		//----------------------------------
		// Process the type specification...
		typeIdPtr->typePtr = doType();
		if (typeIdPtr->typePtr->typeIdPtr == NULL)
			typeIdPtr->typePtr->typeIdPtr = typeIdPtr;

		analyzeTypeDefn(typeIdPtr);

		//---------------
		// Error synch...
		synchronize(followDeclarationList, declarationStartList, statementStartList);
		if (curToken == TKN_SEMICOLON)
			getToken();
		else if (tokenIn(declarationStartList) || tokenIn(statementStartList))
			syntaxError(ABL_ERR_SYNTAX_MISSING_SEMICOLON);
	}
}
Exemplo n.º 3
0
void declarations (SymTableNodePtr routineIdPtr, bool allowFunctions) {

	if (curToken == TKN_CONST) {
		getToken();
		constDefinitions();
	}

	if (curToken == TKN_TYPE) {
		getToken();
		typeDefinitions();
	}

	if (curToken == TKN_VAR) {
		getToken();
		varDeclarations(routineIdPtr);
	}

	//---------------------------------------------------
	// Loop to process all of the function definitions...
	if (allowFunctions)
		while ((curToken == TKN_FUNCTION) || (curToken == TKN_ORDER) || (curToken == TKN_STATE)){
			routine();

			//---------------------
			// Error synchronize...
			synchronize(followRoutineList, declarationStartList, statementStartList);
			if (curToken == TKN_SEMICOLON)
				getToken();
			else if (tokenIn(declarationStartList) || tokenIn(statementStartList))
				syntaxError(ABL_ERR_SYNTAX_MISSING_SEMICOLON);
		}
	else if ((curToken == TKN_FUNCTION) || (curToken == TKN_ORDER) || (curToken == TKN_STATE))
		syntaxError(ABL_ERR_SYNTAX_NO_FUNCTION_NESTING);
}
Exemplo n.º 4
0
void caseBranch (CaseItemPtr& caseItemHead, CaseItemPtr& caseItemTail, long& caseLabelCount, TypePtr expressionType) {

	//static CaseItemPtr oldCaseItemTail = NULL;
	CaseItemPtr oldCaseItemTail = caseItemTail;

	bool anotherLabel;
	do {
		TypePtr labelType = caseLabel(caseItemHead, caseItemTail, caseLabelCount);
		if (expressionType != labelType)
			syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);

		getToken();
		if (curToken == TKN_COMMA) {
			getToken();
			if (tokenIn(CaseLabelStartList))
				anotherLabel = true;
			else {
				syntaxError(ABL_ERR_SYNTAX_MISSING_CONSTANT);
				anotherLabel = false;
			}
			}
		else
			anotherLabel = false;
	} while (anotherLabel);

	//--------------
	// Error sync...
	synchronize(FollowCaseLabelList, statementStartList, NULL);
	ifTokenGetElseError(TKN_COLON, ABL_ERR_SYNTAX_MISSING_COLON);

	//-----------------------------------------------------------------
	// Fill in the branch location for each CaseItem for this branch...
	CaseItemPtr caseItem = (!oldCaseItemTail ? caseItemHead : oldCaseItemTail->next);
	//oldCaseItemTail = CaseItemTail;
	while (caseItem) {
		caseItem->branchLocation = codeBufferPtr;
		caseItem = caseItem->next;
	}

	if (curToken != TKN_END_CASE)
		do {
			statement();
			while (curToken == TKN_SEMICOLON)
				getToken();
			if (curToken == TKN_END_CASE)
				break;
		} while (tokenIn(statementStartList));

	ifTokenGetElseError(TKN_END_CASE, ABL_ERR_SYNTAX_MISSING_END_CASE);
	ifTokenGetElseError(TKN_SEMICOLON, ABL_ERR_SYNTAX_MISSING_SEMICOLON);
}
Exemplo n.º 5
0
TypePtr arraySubscriptList (TypePtr typePtr) {

	TypePtr indexTypePtr = NULL;
	TypePtr elementTypePtr = NULL;
	TypePtr subscriptTypePtr = NULL;

	do {
		if (typePtr->form == FRM_ARRAY) {
			indexTypePtr = typePtr->info.array.indexTypePtr;
			elementTypePtr = typePtr->info.array.elementTypePtr;

			getToken();
			subscriptTypePtr = expression();

			//-------------------------------------------------------------
			// If the subscript expression isn't assignment type compatible
			// with its corresponding subscript type, we're screwed...
			if (!isAssignTypeCompatible(indexTypePtr, subscriptTypePtr))
				syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);

			typePtr = elementTypePtr;
			}
		else {
			syntaxError(ABL_ERR_SYNTAX_TOO_MANY_SUBSCRIPTS);
			while ((curToken != TKN_RBRACKET) && !tokenIn(statementEndList))
				getToken();
		}
	} while (curToken == TKN_COMMA);

	ifTokenGetElseError(TKN_RBRACKET, ABL_ERR_SYNTAX_MISSING_RBRACKET);
	return(typePtr);
}
Exemplo n.º 6
0
void whileStatement (void) {

	// NEW STYLE, using endwhile keyword...
	getToken();
	char* loopEndLocation = crunchAddressMarker(NULL);
	
	TypePtr exprType = expression();
	if (exprType != BooleanTypePtr)
		syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);

	//---------------------------------------
	// Let's not use a DO keyword, for now...
	ifTokenGetElseError(TKN_DO, ABL_ERR_SYNTAX_MISSING_DO);

	if (curToken != TKN_END_WHILE)
		do {
			statement();
			while (curToken == TKN_SEMICOLON)
				getToken();
			if (curToken == TKN_END_WHILE)
				break;
		} while (tokenIn(statementStartList));
	
	ifTokenGetElseError(TKN_END_WHILE, ABL_ERR_SYNTAX_MISSING_END_WHILE);

	fixupAddressMarker(loopEndLocation);
}
Exemplo n.º 7
0
void forStatement (void) {

	getToken();
	char* loopEndLocation = crunchAddressMarker(NULL);
	
	TypePtr forType = NULL;
	if (curToken == TKN_IDENTIFIER) {
		SymTableNodePtr forIdPtr = NULL;
		searchAndFindAllSymTables(forIdPtr);
		crunchSymTableNodePtr(forIdPtr);
		if (/*(forIdPtr->level != level) ||*/ (forIdPtr->defn.key != DFN_VAR))
			syntaxError(ABL_ERR_SYNTAX_INVALID_FOR_CONTROL);
		
		forType = forIdPtr->typePtr;
		getToken();
		
		//------------------------------------------------------------------
		// If we end up adding a CHAR type, this line needs to be changed...
		if ((forType != IntegerTypePtr) && /*(forType != CharTypePtr) &&*/ (forType->form != FRM_ENUM))
			syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
	
		}
	else {
		syntaxError(ABL_ERR_SYNTAX_MISSING_IDENTIFIER);
		forType = &DummyType;
	}
	
	ifTokenGetElseError(TKN_EQUAL, ABL_ERR_SYNTAX_MISSING_EQUAL);
	
	TypePtr exprType = expression();
	if (!isAssignTypeCompatible(forType, exprType))
		syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
		
	if (curToken == TKN_TO)
		getToken();
	else
		syntaxError(ABL_ERR_SYNTAX_MISSING_TO);

	exprType = expression();
	if (!isAssignTypeCompatible(forType, exprType))
		syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);

	//-----------------------------------------
	// For now, let's use the DO keyword...
	ifTokenGetElseError(TKN_DO, ABL_ERR_SYNTAX_MISSING_DO);		

	if (curToken != TKN_END_FOR)
		do {
			statement();
			while (curToken == TKN_SEMICOLON)
				getToken();
			if (curToken == TKN_END_FOR)
				break;
		} while (tokenIn(statementStartList));

	ifTokenGetElseError(TKN_END_FOR, ABL_ERR_SYNTAX_MISSING_END_FOR);

	fixupAddressMarker(loopEndLocation);
}
Exemplo n.º 8
0
void ifStatement (void) {

	getToken();
	char* falseLocation = crunchAddressMarker(NULL);
	
	TypePtr exprType = expression();
	if (exprType != BooleanTypePtr)
		syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
		
	ifTokenGetElseError(TKN_THEN, ABL_ERR_SYNTAX_MISSING_THEN);

	if ((curToken != TKN_END_IF) && (curToken != TKN_ELSE))
		do {
			statement();
			while (curToken == TKN_SEMICOLON)
				getToken();
			if ((curToken == TKN_END_IF) || (curToken == TKN_ELSE))
				break;
		} while (tokenIn(statementStartList));
	
	fixupAddressMarker(falseLocation);
	
	//-----------------------------
	// ELSE branch, if necessary...
	if (curToken == TKN_ELSE) {
		getToken();
		char* ifEndLocation = crunchAddressMarker(NULL);

		if (curToken != TKN_END_IF)
			do {
				statement();
				while (curToken == TKN_SEMICOLON)
					getToken();
				if (curToken == TKN_END_IF)
					break;
			} while (tokenIn(statementStartList));
		
		fixupAddressMarker(ifEndLocation);
	}

	ifTokenGetElseError(TKN_END_IF, ABL_ERR_SYNTAX_MISSING_END_IF);
}
Exemplo n.º 9
0
TypePtr simpleExpression (void) {

	bool usedUnaryOp = false;
	TokenCodeType unaryOp = TKN_PLUS;
	
	if ((curToken == TKN_PLUS) || (curToken == TKN_MINUS)) {
		unaryOp = curToken;
		usedUnaryOp = true;
		getToken();
	}
	
	//------------------------------------------------
	// Grab the first term in the simple expression...
	TypePtr resultType = term();
	
	if (usedUnaryOp && (resultType != IntegerTypePtr) && (resultType != RealTypePtr))
		syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
		
	//---------------------------------------------------
	// Continue to process all terms in the expression...
	while (tokenIn(addOperatorList)) {
		TokenCodeType op = curToken;
		
		getToken();
		TypePtr secondType = term();
		
		switch (op) {
			case TKN_PLUS:
			case TKN_MINUS:
				if (integerOperands(resultType, secondType)) {
					//---------------------------------------------------
					// Both operands are integer, so result is integer...
					resultType = IntegerTypePtr;
					}
				else if (realOperands(resultType, secondType)) {
					//----------------------------------------------------
					// Both real operands, or mixed (real and integer)...
					resultType = RealTypePtr;
					}
				else {
					syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
					resultType = &DummyType;
				}
				break;
			case TKN_OR:
				if (!booleanOperands(resultType, secondType))
					syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
				resultType = BooleanTypePtr;
				break;
		}
	}
	return(resultType);
}				
Exemplo n.º 10
0
TypePtr expression (void) {

	//------------------------------------
	// Grab the first simple expression...
	TypePtr resultType = simpleExpression();

	if (tokenIn(relationalOperatorList)) {
		//---------------------------------------
		// Snatch the second simple expression...
		getToken();
		TypePtr secondType = simpleExpression();

		checkRelationalOpTypes(resultType, secondType);
		resultType = BooleanTypePtr;
	}
	return(resultType);
}
Exemplo n.º 11
0
void synchronize(TokenCodeType* tokenList1, TokenCodeType* tokenList2, TokenCodeType* tokenList3)
{
	bool badLists = (!tokenIn(tokenList1) && !tokenIn(tokenList2) && !tokenIn(tokenList3));
	if (badLists)
	{
		syntaxError((curToken == TKN_EOF) ? ABL_ERR_SYNTAX_UNEXPECTED_EOF
										  : ABL_ERR_SYNTAX_UNEXPECTED_TOKEN);
		//----------------------------------------------
		// Now, we need to re-sync by skipping tokens...
		while (!tokenIn(tokenList1) && !tokenIn(tokenList2) && !tokenIn(tokenList3) &&
			(curToken != TKN_EOF))
			getToken();
	}
}
Exemplo n.º 12
0
void repeatStatement (void) {

	getToken();
	
	if (curToken != TKN_UNTIL) {
		do {
			statement();
			while (curToken == TKN_SEMICOLON)
				getToken();
			if (curToken == TKN_UNTIL)
				break;
		} while (tokenIn(statementStartList));
	}
	
	ifTokenGetElseError(TKN_UNTIL, ABL_ERR_SYNTAX_MISSING_UNTIL);
	
	TypePtr exprType = expression();
	if (exprType != BooleanTypePtr)
		syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
}
Exemplo n.º 13
0
TypePtr term (void) {

	//-------------------------
	// Grab the first factor...
	TypePtr resultType = factor();
	
	//------------------------------------------------------------------
	// Now, continue grabbing factors separated by multiply operators...
	while (tokenIn(multiplyOperatorList)) {
		TokenCodeType op = curToken;
		
		getToken();
		TypePtr secondType = factor();
		
		switch (op) {
			case TKN_STAR:
				if (integerOperands(resultType, secondType)) {
					//---------------------------------------------------
					// Both operands are integer, so result is integer...
					resultType = IntegerTypePtr;
					}
				else if (realOperands(resultType, secondType)) {
					//----------------------------------------------------
					// Both real operands, or mixed (real and integer)...
					resultType = RealTypePtr;
					}
				else {
					syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
					resultType = &DummyType;
				}
				break;
			case TKN_FSLASH:
				if (integerOperands(resultType, secondType)) {
					//---------------------------------------------------
					// Both operands are integer, so result is integer...
					resultType = IntegerTypePtr;
					}
				else if (realOperands(resultType, secondType)) {
					//----------------------------------------------------
					// Both real operands, or mixed (real and integer)...
					resultType = RealTypePtr;
					}
				else {
					syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
					resultType = &DummyType;
				}
				break;
			case TKN_DIV:
			case TKN_MOD:
				//----------------------------------------------------------
				// Both operands should be integer, and result is integer...
				if (!integerOperands(resultType, secondType))
					syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
				resultType = IntegerTypePtr;
				break;
			case TKN_AND:
				if (!booleanOperands(resultType, secondType))
					syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
				resultType = BooleanTypePtr;								
				break;
		}
	}
	return(resultType);
}
Exemplo n.º 14
0
TypePtr doType (void) {

	switch (curToken) {
		case TKN_IDENTIFIER: {
			SymTableNodePtr idPtr;
			searchAllSymTables(idPtr);

			if (!idPtr) {
				syntaxError(ABL_ERR_SYNTAX_UNDEFINED_IDENTIFIER);
				return(NULL);
				}
			else if (idPtr->defn.key == DFN_TYPE) {
				//----------------------------------------------------------
				// NOTE: Array types should be parsed in this case if a left
				// bracket follows the type identifier.
				TypePtr elementType = setType(identifierType(idPtr));
				if (curToken == TKN_LBRACKET) {
					//--------------
					// Array type...
					TypePtr typePtr = createType();
					if (!typePtr)
						ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc array type ");
					TypePtr elementTypePtr = typePtr;
					do {
						getToken();
						if (tokenIn(indexTypeStartList)) {
							elementTypePtr->form = FRM_ARRAY;
							elementTypePtr->size = 0;
							elementTypePtr->typeIdPtr = NULL;
							//----------------------------------------------
							// All array indices must be integer, for now...
							elementTypePtr->info.array.indexTypePtr = setType(IntegerTypePtr);

							//------------------------
							// Read the index count...
							switch (curToken) {
								case TKN_NUMBER:
									if (curLiteral.type == LIT_INTEGER)
										elementTypePtr->info.array.elementCount = curLiteral.value.integer;
									else {
										elementTypePtr->form = FRM_NONE;
										elementTypePtr->size = 0;
										elementTypePtr->typeIdPtr = NULL;
										elementTypePtr->info.array.indexTypePtr = NULL;
										syntaxError(ABL_ERR_SYNTAX_INVALID_INDEX_TYPE);
									}
									getToken();
									break;
								case TKN_IDENTIFIER: {
									SymTableNodePtr idPtr;
									searchAllSymTables(idPtr);
									if (idPtr == NULL)
										syntaxError(ABL_ERR_SYNTAX_UNDEFINED_IDENTIFIER);
									else if (idPtr->defn.key == DFN_CONST) {
										if (idPtr->typePtr == IntegerTypePtr)
											elementTypePtr->info.array.elementCount = idPtr->defn.info.constant.value.integer;
										else {
											elementTypePtr->form = FRM_NONE;
											elementTypePtr->size = 0;
											elementTypePtr->typeIdPtr = NULL;
											elementTypePtr->info.array.indexTypePtr = NULL;
											syntaxError(ABL_ERR_SYNTAX_INVALID_INDEX_TYPE);
										}
										}
									else {
										elementTypePtr->form = FRM_NONE;
										elementTypePtr->size = 0;
										elementTypePtr->typeIdPtr = NULL;
										elementTypePtr->info.array.indexTypePtr = NULL;
										syntaxError(ABL_ERR_SYNTAX_INVALID_INDEX_TYPE);
									}
									getToken();
									}
									break;
								default:
									elementTypePtr->form = FRM_NONE;
									elementTypePtr->size = 0;
									elementTypePtr->typeIdPtr = NULL;
									elementTypePtr->info.array.indexTypePtr = NULL;
									syntaxError(ABL_ERR_SYNTAX_INVALID_INDEX_TYPE);
									getToken();
							}
							}
						else {
							elementTypePtr->form = FRM_NONE;
							elementTypePtr->size = 0;
							elementTypePtr->typeIdPtr = NULL;
							elementTypePtr->info.array.indexTypePtr = NULL;
							syntaxError(ABL_ERR_SYNTAX_INVALID_INDEX_TYPE);
							getToken();
						}

						synchronize(followDimensionList, NULL, NULL);

						//--------------------------------
						// Create an array element type...
						if (curToken == TKN_COMMA) {
							elementTypePtr = elementTypePtr->info.array.elementTypePtr = createType();
							if (!elementTypePtr)
								ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc array element Type ");
						}
					} while (curToken == TKN_COMMA);

					ifTokenGetElseError(TKN_RBRACKET, ABL_ERR_SYNTAX_MISSING_RBRACKET);

					elementTypePtr->info.array.elementTypePtr = elementType;

					typePtr->size = arraySize(typePtr);

					elementType = typePtr;
				}
				return(elementType);
				}
			else {
				syntaxError(ABL_ERR_SYNTAX_NOT_A_TYPE_IDENTIFIER);
				return(NULL);
			}

			}
			break;
		case TKN_LPAREN:
			return(enumerationType());
		default:
			syntaxError(ABL_ERR_SYNTAX_INVALID_TYPE);
			return(NULL);
	}
}
Exemplo n.º 15
0
void statement (void) {

	//-------------------------------------------------------------------
	// NOTE: Since we currently don't support generic BEGIN/END (compound
	// statement) blocks...
	if ((curToken != TKN_CODE) /*&& (curToken != TKN_BEGIN)*/)
			crunchStatementMarker();
	
	switch (curToken) {
		case TKN_IDENTIFIER: {
			SymTableNodePtr IdPtr = NULL;
			
			//--------------------------------------------------------------
			// First, do we have an assignment statement or a function call?		
			searchAndFindAllSymTables(IdPtr);
		
			if ((IdPtr->defn.key == DFN_FUNCTION)/* || (IdPtr->defn.key == DFN_MODULE)*/) {
				RoutineKey key = IdPtr->defn.info.routine.key;
				if ((key == RTN_ASSERT) || (key == RTN_PRINT) || (key == RTN_CONCAT)) {
					bool uncrunch = ((key == RTN_ASSERT) && !AssertEnabled) ||
									((key == RTN_PRINT) && !PrintEnabled) ||
									((key == RTN_CONCAT) && !StringFunctionsEnabled);
					if (uncrunch) {
						uncrunchStatementMarker();
						Crunch = false;
					}
				}
				crunchSymTableNodePtr(IdPtr);
				if (IdPtr->defn.info.routine.flags & ROUTINE_FLAG_ORDER) {
					if (NumOrderCalls == MAX_ORDERS)
						syntaxError(ABL_ERR_SYNTAX_TOO_MANY_ORDERS);
					crunchByte((unsigned char)(NumOrderCalls / 32));
					crunchByte((unsigned char)(NumOrderCalls % 32));
					NumOrderCalls++;
				}
				getToken();
				SymTableNodePtr thisRoutineIdPtr = CurRoutineIdPtr;
				routineCall(IdPtr, 1);
				CurRoutineIdPtr = thisRoutineIdPtr;
				Crunch = true;
				}
			else
				assignmentStatement(IdPtr);
			}
			break;
		case TKN_REPEAT:
			repeatStatement();
			break;
		case TKN_WHILE:
			whileStatement();
			break;
		case TKN_IF:
			ifStatement();
			break;
		case TKN_FOR:
			forStatement();
			break;
		case TKN_SWITCH:
			switchStatement();
			break;
		case TKN_TRANS:
			transStatement();
			break;
		case TKN_TRANS_BACK:
			transBackStatement();
			break;
	}

	//---------------------------------------------------------------------
	// Now, make sure the statement is closed off with the proper block end
	// statement, if necessary (which is usually the case :).
	synchronize(statementEndList, NULL, NULL);
	if (tokenIn(statementStartList))
		syntaxError(ABL_ERR_SYNTAX_MISSING_SEMICOLON);
}
Exemplo n.º 16
0
void switchStatement (void) {

	//-------------------------
	// Init the branch table...
	getToken();
	char* branchTableLocation = crunchAddressMarker(NULL);

CaseItemPtr	caseItemHead = NULL;
CaseItemPtr	caseItemTail = NULL;
long caseLabelCount = 0;
	
//CaseItemHead = CaseItemTail = NULL;
//CaseLabelCount = 0;

	TypePtr expressionType = expression();

	//-----------------------------------------------------------------------------
	// NOTE: If we have subranges in ABL, we'll have to check in the following line
	// for a subrange, as well...
	if (((expressionType->form != FRM_SCALAR) && (expressionType->form != FRM_ENUM)) || (expressionType == RealTypePtr))
		syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);

	synchronize(FollowSwitchExpressionList, NULL, NULL);

	//----------------------------
	// Process each CASE branch...
	bool moreBranches = (curToken == TKN_CASE);
	char* caseEndChain = NULL;
	while (moreBranches) {
		getToken();
		if (tokenIn(CaseLabelStartList))
			caseBranch(caseItemHead, caseItemTail, caseLabelCount, expressionType);

		//---------------------------------------------------
		// Link another address marker at the end of the CASE
		// branch to point to the end of the CASE block...
		caseEndChain = crunchAddressMarker(caseEndChain);

		moreBranches = (curToken == TKN_CASE);
	}

	//if (curToken == TKN_DEFAULT) {
	//}

	//-------------------------
	// Emit the branch table...
	fixupAddressMarker(branchTableLocation);
	crunchInteger(caseLabelCount);
	CaseItemPtr caseItem = caseItemHead;
	while (caseItem) {
		crunchInteger(caseItem->labelValue);
		crunchOffset(caseItem->branchLocation);
		CaseItemPtr nextCaseItem = caseItem->next;
		ABLStackFreeCallback(caseItem);
		caseItem = nextCaseItem;
	}

	ifTokenGetElseError(TKN_END_SWITCH, ABL_ERR_SYNTAX_MISSING_END_SWITCH);

	//--------------------------------------------
	// Patch up the case branch address markers...
	while (caseEndChain)
		caseEndChain = fixupAddressMarker(caseEndChain);

}
Exemplo n.º 17
0
void varOrFieldDeclarations (SymTableNodePtr routineIdPtr, long offset) {

	bool varFlag = (routineIdPtr != NULL);
	SymTableNodePtr idPtr = NULL;
	SymTableNodePtr firstIdPtr = NULL;
	SymTableNodePtr lastIdPtr = NULL;
	SymTableNodePtr prevLastIdPtr = NULL;
	
	long totalSize = 0;
	while ((curToken == TKN_IDENTIFIER) || (curToken == TKN_ETERNAL) || (curToken == TKN_STATIC)) {

		VariableType varType = VAR_TYPE_NORMAL;
		if ((curToken == TKN_ETERNAL) || (curToken == TKN_STATIC)) {
			if (curToken == TKN_ETERNAL)
				varType = VAR_TYPE_ETERNAL;
			else
				varType = VAR_TYPE_STATIC;
			getToken();
			if (curToken != TKN_IDENTIFIER)
				syntaxError(ABL_ERR_SYNTAX_MISSING_IDENTIFIER);
		}

		firstIdPtr = NULL;

		//------------------------------
		// Process the variable type...
		TypePtr typePtr = doType();
		//------------------------------------------------------------------
		// Since we haven't really assigned it here, decrement its
		// numInstances. Every variable in this list will set it properly...
		typePtr->numInstances--;

		long size = typePtr->size;

		//-------------------------------------------------------
		// Now that we've read the type, read in the variable (or
		// possibly list of variables) declared of this type.
		// Loop to process every variable (and field, if records
		// are being implemented:) in sublist...
		while (curToken == TKN_IDENTIFIER) {
			if (varFlag) {
				//---------------------------------------------
				// We're working with a variable declaration...
				if (varType == VAR_TYPE_ETERNAL) {
					long curLevel = level;
					level = 0;
					searchAndEnterThisTable (idPtr, SymTableDisplay[0]);
					level = curLevel;
					}
				else
					searchAndEnterLocalSymTable(idPtr);
				idPtr->library = CurLibrary;
				idPtr->defn.key = DFN_VAR;
				}
			else
				syntaxError(ABL_ERR_SYNTAX_NO_RECORD_TYPES);
			idPtr->labelIndex = 0;

			//------------------------------------------
			// Now, link Id's together into a sublist...
			if (!firstIdPtr) {
				firstIdPtr = lastIdPtr = idPtr;
				if (varFlag && (varType != VAR_TYPE_ETERNAL) && (routineIdPtr->defn.info.routine.locals == NULL))
					routineIdPtr->defn.info.routine.locals = idPtr;
				}
			else {
				lastIdPtr->next = idPtr;
				lastIdPtr = idPtr;
			}

			getToken();
			ifTokenGet(TKN_COMMA);
		}

		//--------------------------------------------------------------------------
		// Assign the offset and the type to all variable or field Ids in sublist...
		for (idPtr = firstIdPtr; idPtr != NULL; idPtr = idPtr->next) {
			idPtr->typePtr = setType(typePtr);

			if (varFlag) {
				idPtr->defn.info.data.varType = varType;
				switch (varType) {
					case VAR_TYPE_NORMAL:
						totalSize += size;
						idPtr->defn.info.data.offset = offset++;
						break;
					case VAR_TYPE_ETERNAL: {
						idPtr->defn.info.data.offset = eternalOffset;
						//-----------------------------------
						// Initialize the variable to zero...
						StackItemPtr dataPtr = (StackItemPtr)stack + eternalOffset;
						if (typePtr->form == FRM_ARRAY) {
							dataPtr->address = (Address)ABLStackMallocCallback((size_t)size);
							if (!dataPtr->address)
								ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc eternal array ");
							memset(dataPtr->address, 0, size);
							EternalVariablesSizes[eternalOffset] = size;
							}
						else {
							dataPtr->integer = 0;
							EternalVariablesSizes[eternalOffset] = 0;
						}
						eternalOffset++;
						}
						break;
					case VAR_TYPE_STATIC: {
						if (NumStaticVariables == MaxStaticVariables)
							syntaxError(ABL_ERR_SYNTAX_TOO_MANY_STATIC_VARS);
						idPtr->defn.info.data.offset = NumStaticVariables;
						if (typePtr->form == FRM_ARRAY)
							StaticVariablesSizes[NumStaticVariables] = size;
						else
							StaticVariablesSizes[NumStaticVariables] = 0;
						NumStaticVariables++;
						}
						break;
				}
				analyzeVarDecl(idPtr);
				}
			else {
				//----------------
				// record field...
				idPtr->defn.info.data.varType = VAR_TYPE_NORMAL;
				idPtr->defn.info.data.offset = offset;
				offset += size;
			}
		}

		//--------------------------------------------------
		// Now, link this sublist to the previous sublist...
		if (varType != VAR_TYPE_ETERNAL) {
			if (prevLastIdPtr != NULL)
				prevLastIdPtr->next = firstIdPtr;
			prevLastIdPtr = lastIdPtr;
		}

		//---------------------
		// Error synchronize...
		if (varFlag)
			synchronize(followVariablesList, declarationStartList, statementStartList);
		if (curToken == TKN_SEMICOLON)
			getToken();
		else if (varFlag && (tokenIn(declarationStartList) || tokenIn(statementStartList)))
			syntaxError(ABL_ERR_SYNTAX_MISSING_SEMICOLON);
	}

	synchronize(followVarBlockList, NULL, NULL);

	if (varFlag) {
		//----------------------------------------------------------------
		// If the following error occurs too frequently, simply make the
		// totalLocalSize field an unsigned long instead, and dramatically
		// increase the totalSize limit here...
		if (totalSize > 32000)
			syntaxError(ABL_ERR_SYNTAX_TOO_MANY_LOCAL_VARIABLES);
		routineIdPtr->defn.info.routine.totalLocalSize = (unsigned short)totalSize;
	}
}