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); }
TypePtr stdConcat (void) { // PRINT function: // // PARAMS: char array // // integer, real or char array // // RETURN: integer (resulting length, not including NULL) if (curToken == TKN_LPAREN) getToken(); else syntaxError(ABL_ERR_SYNTAX_WRONG_NUMBER_OF_PARAMS); TypePtr paramType = expression(); if ((paramType->form != FRM_ARRAY) || (paramType->info.array.elementTypePtr != CharTypePtr)) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); ifTokenGetElseError(TKN_COMMA, ABL_ERR_SYNTAX_MISSING_COMMA); paramType = expression(); if ((paramType != IntegerTypePtr) && (paramType != RealTypePtr) && (paramType != CharTypePtr) && (paramType != BooleanTypePtr) && ((paramType->form != FRM_ARRAY) || (paramType->info.array.elementTypePtr != CharTypePtr))) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); ifTokenGetElseError(TKN_RPAREN, ABL_ERR_SYNTAX_MISSING_RPAREN); return(IntegerTypePtr); }
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); }
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); }
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); } }
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); } }
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); }
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); }
void transStatement (void) { getToken(); ifTokenGetElseError(TKN_IDENTIFIER, ABL_ERR_MISSING_STATE_IDENTIFIER); SymTableNodePtr IdPtr = searchSymTableForState(wordString, SymTableDisplay[1]); if (!IdPtr) { // New symbol, so let's assume it's a state defined later. We'll make it IdPtr = forwardState(wordString); } if (!IdPtr || (IdPtr->defn.key != DFN_FUNCTION) || ((IdPtr->defn.info.routine.flags & ROUTINE_FLAG_STATE) == 0)) syntaxError(ABL_ERR_MISSING_STATE_IDENTIFIER); crunchSymTableNodePtr(IdPtr); // getToken(); }
void assignmentStatement (SymTableNodePtr varIdPtr) { //----------------------------------- // Grab the variable we're setting... TypePtr varType = variable(varIdPtr); ifTokenGetElseError(TKN_EQUAL, ABL_ERR_SYNTAX_MISSING_EQUAL); //--------------------------------------------------------- // Now, get the expression we're setting the variable to... TypePtr exprType = expression(); //---------------------------------------- // They better be assignment compatible... if (!isAssignTypeCompatible(varType, exprType)) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_ASSIGNMENT); }
TypePtr stdGetStateHandle (void) { if (curToken == TKN_LPAREN) getToken(); else syntaxError(ABL_ERR_SYNTAX_WRONG_NUMBER_OF_PARAMS); EnterStateSymbol = true; TypePtr paramType = expression(); EnterStateSymbol = false; if ((paramType->form != FRM_ARRAY) || (paramType->info.array.elementTypePtr != CharTypePtr)) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); ifTokenGetElseError(TKN_RPAREN, ABL_ERR_SYNTAX_MISSING_RPAREN); return(IntegerTypePtr); }
void stdReturn (void) { // RETURN function // // PARAMS: <same as function return type> // // RETURN: NONE if (curToken == TKN_LPAREN) { getToken(); TypePtr paramType = expression(); if (paramType != CurRoutineIdPtr->typePtr) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); ifTokenGetElseError(TKN_RPAREN, ABL_ERR_SYNTAX_MISSING_RPAREN); } else if (CurRoutineIdPtr->typePtr != NULL) syntaxError(ABL_ERR_SYNTAX_WRONG_NUMBER_OF_PARAMS); }
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); }
void stdPrint (void) { // PRINT function: // // PARAMS: integer or real or string // // RETURN: NONE if (curToken == TKN_LPAREN) getToken(); else syntaxError(ABL_ERR_SYNTAX_WRONG_NUMBER_OF_PARAMS); TypePtr paramType = expression(); if ((paramType != IntegerTypePtr) && (paramType != RealTypePtr) && (paramType != CharTypePtr) && ((paramType->form != FRM_ARRAY) || (paramType->info.array.elementTypePtr != CharTypePtr))) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); ifTokenGetElseError(TKN_RPAREN, ABL_ERR_SYNTAX_MISSING_RPAREN); }
TypePtr enumerationType (void) { SymTableNodePtr constantIdPtr = NULL; SymTableNodePtr lastIdPtr = NULL; TypePtr typePtr = createType(); if (!typePtr) ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc enumeration type "); long constantValue = -1; typePtr->form = FRM_ENUM; typePtr->size = sizeof(long); typePtr->typeIdPtr = NULL; getToken(); //------------------------------------------------------------ // Process list of identifiers in this new enumeration type... while (curToken == TKN_IDENTIFIER) { searchAndEnterLocalSymTable(constantIdPtr); constantIdPtr->defn.key = DFN_CONST; constantIdPtr->defn.info.constant.value.integer = ++constantValue; constantIdPtr->typePtr = typePtr; constantIdPtr->library = CurLibrary; if (lastIdPtr == NULL) typePtr->info.enumeration.constIdPtr = lastIdPtr = constantIdPtr; else { lastIdPtr->next = constantIdPtr; lastIdPtr = constantIdPtr; } getToken(); ifTokenGet(TKN_COMMA); } ifTokenGetElseError(TKN_RPAREN, ABL_ERR_SYNTAX_MISSING_RPAREN); typePtr->info.enumeration.max = constantValue; return(typePtr); }
TypePtr standardRoutineCall (SymTableNodePtr routineIdPtr) { long key = routineIdPtr->defn.info.routine.key; long numParams = FunctionInfoTable[key].numParams; switch (key) { case RTN_RETURN: stdReturn(); return(NULL); case RTN_PRINT: stdPrint(); return(NULL); case RTN_CONCAT: return(stdConcat()); case RTN_GET_STATE_HANDLE: return(stdGetStateHandle()); default: if (key >= NumStandardFunctions) syntaxError(ABL_ERR_SYNTAX_UNEXPECTED_TOKEN); if (numParams == 0) { if (curToken == TKN_LPAREN) syntaxError(ABL_ERR_SYNTAX_WRONG_NUMBER_OF_PARAMS); } else { if (curToken == TKN_LPAREN) getToken(); else syntaxError(ABL_ERR_SYNTAX_WRONG_NUMBER_OF_PARAMS); for (long i = 0; i < numParams; i++) { TypePtr paramType = expression(); switch (FunctionInfoTable[key].params[i]) { case PARAM_TYPE_ANYTHING: break; case PARAM_TYPE_CHAR: if (paramType != CharTypePtr) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); break; case PARAM_TYPE_INTEGER: if (paramType != IntegerTypePtr) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); break; case PARAM_TYPE_REAL: if (paramType != RealTypePtr) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); break; case PARAM_TYPE_BOOLEAN: if (paramType != BooleanTypePtr) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); break; case PARAM_TYPE_INTEGER_REAL: if ((paramType != IntegerTypePtr) && (paramType != RealTypePtr)) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); break; case PARAM_TYPE_CHAR_ARRAY: if ((paramType->form != FRM_ARRAY) || (paramType->info.array.elementTypePtr != CharTypePtr)) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); break; case PARAM_TYPE_INTEGER_ARRAY: if ((paramType->form != FRM_ARRAY) || (paramType->info.array.elementTypePtr != IntegerTypePtr)) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); break; case PARAM_TYPE_REAL_ARRAY: if ((paramType->form != FRM_ARRAY) || (paramType->info.array.elementTypePtr != RealTypePtr)) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); break; case PARAM_TYPE_BOOLEAN_ARRAY: if ((paramType->form != FRM_ARRAY) || (paramType->info.array.elementTypePtr != BooleanTypePtr)) syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES); break; } if (i == (numParams - 1)) ifTokenGetElseError(TKN_RPAREN, ABL_ERR_SYNTAX_MISSING_RPAREN); else ifTokenGetElseError(TKN_COMMA, ABL_ERR_SYNTAX_MISSING_COMMA); } } switch (FunctionInfoTable[key].returnType) { case RETURN_TYPE_NONE: return(NULL); case RETURN_TYPE_INTEGER: return(IntegerTypePtr); case RETURN_TYPE_REAL: return(RealTypePtr); case RETURN_TYPE_BOOLEAN: return(BooleanTypePtr); } } return(NULL); }
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); } }
TypePtr factor (void) { TypePtr thisType = NULL; switch (curToken) { case TKN_IDENTIFIER: { SymTableNodePtr IdPtr = NULL; searchAndFindAllSymTables(IdPtr); switch (IdPtr->defn.key) { case DFN_FUNCTION: crunchSymTableNodePtr(IdPtr); getToken(); thisType = routineCall(IdPtr, 1); break; case DFN_CONST: crunchSymTableNodePtr(IdPtr); getToken(); thisType = (TypePtr)(IdPtr->typePtr); break; default: thisType = (TypePtr)variable(IdPtr); break; } } break; case TKN_NUMBER: { SymTableNodePtr thisNode = searchSymTable(tokenString, SymTableDisplay[1]); if (!thisNode) thisNode = enterSymTable(tokenString, &SymTableDisplay[1]); if (curLiteral.type == LIT_INTEGER) { thisNode->typePtr = IntegerTypePtr; thisType = (TypePtr)(thisNode->typePtr); thisNode->defn.info.constant.value.integer = curLiteral.value.integer; } else { thisNode->typePtr = RealTypePtr; thisType = (TypePtr)(thisNode->typePtr); thisNode->defn.info.constant.value.real = curLiteral.value.real; } crunchSymTableNodePtr(thisNode); getToken(); } break; case TKN_STRING: { long length = strlen(curLiteral.value.string); if (EnterStateSymbol) { SymTableNodePtr stateSymbol = searchSymTableForState(curLiteral.value.string, SymTableDisplay[1]); if (!stateSymbol) forwardState(curLiteral.value.string); } SymTableNodePtr thisNode = searchSymTableForString(tokenString, SymTableDisplay[1]); if (!thisNode)// { thisNode = enterSymTable(tokenString, &SymTableDisplay[1]); if (length == 1) { thisNode->defn.info.constant.value.character = curLiteral.value.string[0]; thisType = CharTypePtr; } else { thisNode->typePtr = thisType = makeStringType(length); thisNode->info = (char*)ABLSymbolMallocCallback(length + 1); if (!thisNode->info) ABL_Fatal(0, " ABL: Unable to AblSymTableHeap->malloc string literal "); strcpy(thisNode->info, curLiteral.value.string); } //} crunchSymTableNodePtr(thisNode); getToken(); } break; case TKN_NOT: getToken(); thisType = factor(); break; case TKN_LPAREN: getToken(); thisType = expression(); ifTokenGetElseError(TKN_RPAREN, ABL_ERR_SYNTAX_MISSING_RPAREN); break; default: syntaxError(ABL_ERR_SYNTAX_INVALID_EXPRESSION); thisType = &DummyType; break; } return(thisType); }
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); }