private TType ParseRecordType() { TType pType = new TType(TFormCode.fcRecord, 0, null); symtabStack.EnterScope(); pType.record.pSymtab = symtabStack.CurrentSymtab; GetToken(); ParseFieldDeclarations(pType, 0); CondGetToken(TTokenCode.End, TErrorCode.MissingEND); return pType; }
private TType ParseSubrangeType(SymtabNode pMinId) { TType pType = new TType(TFormCode.fcSubrange, 0, null); TType.SetType(ref pType.SubRange.BaseType, ParseSubrangeLimit(pMinId, ref pType.SubRange.min)); Resync(tlSubrangeLimitFollow, tlDeclarationStart); CondGetToken(TTokenCode.DotDot, TErrorCode.MissingDotDot); TType pMaxType = ParseSubrangeLimit(null, ref pType.SubRange.max); if (pMaxType != pType.SubRange.BaseType) { OnError(TErrorCode.IncompatibleTypes); pType.SubRange.max = pType.SubRange.min; } else if (pType.SubRange.min > pType.SubRange.max) { OnError(TErrorCode.MinGtMax); int temp = pType.SubRange.min; pType.SubRange.min = pType.SubRange.max; pType.SubRange.max = temp; } pType.size = pType.SubRange.BaseType.size; return pType; }
private SymtabNode ParseIdSublist(SymtabNode pRoutineId, TType pRecordType, out SymtabNode pLastId) { SymtabNode pId; SymtabNode pFirstId = null; pLastId = null; // -- Loop to parse each identifier in the sublist. while (token == TTokenCode.Identifier) { // -- Variable: Enter into local symbol table. // -- Field: Enter into record symbol table. pId = pRoutineId != null ? EnterNewLocal(pToken.TokenString) : pRecordType.record.pSymtab.EnterNew(pToken.TokenString); // -- Link newly-declared identifier nodes together // -- into a sublist. if (pId.defn.how == TDefnCode.dcUndefined) { pId.defn.how = pRoutineId != null ? TDefnCode.dcVariable : TDefnCode.dcField; if (pFirstId == null) pFirstId = pLastId = pId; else { pLastId.Next = pId; pLastId = pId; } } // -- , GetToken(); Resync(tlIdentifierFollow); if (token == TTokenCode.Comma) { // -- Saw comma. // -- Skip extra commas and look for an identifier do { GetToken(); Resync(tlIdentifierStart, tlIdentifierFollow); if (token == TTokenCode.Comma) OnError(TErrorCode.MissingIdentifier); } while (token == TTokenCode.Comma); } } return pFirstId; }
private void ParseIndexType(TType pArrayType) { if (TokenIn(token, tlIndexStart)) { TType pIndexType = ParseTypeSpec(); TType.SetType(ref pArrayType.array.pIndexType, pIndexType); switch (pIndexType.Form) { case TFormCode.fcSubrange: pArrayType.array.elmtCount = pIndexType.SubRange.max - pIndexType.SubRange.min + 1; pArrayType.array.minIndex = pIndexType.SubRange.min; pArrayType.array.maxIndex = pIndexType.SubRange.max; return; case TFormCode.fcArray: pArrayType.array.elmtCount = pIndexType.Enumeration.max + 1; pArrayType.array.minIndex = 0; pArrayType.array.maxIndex = pIndexType.Enumeration.max; return; } } TType.SetType(ref pArrayType.array.pIndexType, TType.pDummyType); pArrayType.array.elmtCount = 0; pArrayType.array.minIndex = pArrayType.array.maxIndex = 0; OnError(TErrorCode.InvalidIndexType); }
//-------------------------------------------------------------- // CheckRelOpOperands Check that the types of the two operands // of a relational operator are compatible. // Flag an incompatible type error if not. // // pType1 : ptr to the first operand's type object // pType2 : ptr to the second operand's type object //-------------------------------------------------------------- /// <summary> ///-------------------------------------------------------------- /// CheckRelOpOperands Check that the types of the two operands /// of a relational operator are compatible. /// Flag an incompatible type error if not. /// /// pType1 : ptr to the first operand's type object /// pType2 : ptr to the second operand's type object ///-------------------------------------------------------------- /// </summary> /// <param name="firstOperandType">The first operand's type object.</param> /// <param name="secondOperandType">The second operand's type object.</param> /// <returns></returns> public static bool CheckRelOpOperands(TType firstOperandType, TType secondOperandType) { firstOperandType = firstOperandType.Base; secondOperandType = secondOperandType.Base; //--Two identical scalar or enumeration types. if ((firstOperandType == secondOperandType) && ((firstOperandType.Form == TFormCode.fcScalar) || (firstOperandType.Form == TFormCode.fcEnum))) { return true; } //--One integer operand and one real operand. if (((firstOperandType == pIntegerType) && (secondOperandType == pRealType)) || ((secondOperandType == pIntegerType) && (firstOperandType == pRealType))) { return true; } //--Two strings of the same length. if ((firstOperandType.Form == TFormCode.fcArray) && (secondOperandType.Form == TFormCode.fcArray) && (firstOperandType.array.pElmtType == pCharType) && (secondOperandType.array.pElmtType == pCharType) && (firstOperandType.array.elmtCount == secondOperandType.array.elmtCount)) { return true; } return false; }
private void ParseFieldDeclarations(TType pRecordType, int offset) { ParseVarOrFieldDecls(null, pRecordType, offset); }
private static void RemoveType(ref TType pType) { if (pType != null && (--pType.refCount == 0)) { pType = null; } }
private int ArraySize(TType pArrayType) { if (pArrayType.array.pElmtType.size == 0) { pArrayType.array.pElmtType.size = ArraySize(pArrayType.array.pElmtType); } return (pArrayType.array.elmtCount * pArrayType.array.pElmtType.size); }
//TType Base //{ // get { return Form == TFormCode.fcSubrange ? SubRange.BaseType : this; } //} internal static bool CheckAssignmentTypeCompatible(TType pTargetType, TType pValueType) { pTargetType = pTargetType.Base; pValueType = pValueType.Base; //--Two identical types. if (pTargetType == pValueType) return true; //--real := integer if ((pTargetType == pRealType) && (pValueType == pIntegerType)) return true; //--Two strings of the same length. if ((pTargetType.Form == TFormCode.fcArray) && (pValueType.Form == TFormCode.fcArray) && (pTargetType.array.pElmtType == TType.pCharType) && (pValueType.array.pElmtType == TType.pCharType) && (pTargetType.array.elmtCount == pValueType.array.elmtCount)) { return true; } return false; }
internal static bool CheckIntegerOrReal(TType operandType1, TType operandType2 = null) { operandType2 = operandType2.Base; if ((operandType2 != pIntegerType) && (operandType2 != pRealType)) { return false; } if (operandType2 != null) { operandType2 = operandType2.Base; if ((operandType2 != pIntegerType) && (operandType2 != pRealType)) { return false; } } return true; }
public static TType SetType(ref TType pTargetType, TType pSourceType) { ++pSourceType.refCount; pTargetType = pSourceType; return pSourceType; }
public static bool RealOperands(TType firstOperandType, TType secondOperandType) { firstOperandType = firstOperandType.Base; secondOperandType = secondOperandType.Base; return ((firstOperandType == pRealType) && (secondOperandType == pRealType)) || ((firstOperandType == pRealType) && (secondOperandType == pIntegerType)) || ((secondOperandType == pRealType) && (firstOperandType == pIntegerType)); }
public static bool IntegerOperands(TType firstOperandType, TType secondOperandType) { firstOperandType = firstOperandType.Base; secondOperandType = secondOperandType.Base; return (firstOperandType == pIntegerType) && (secondOperandType == pIntegerType); }
private TType ParseSubscripts(TType pType) { //--Loop to parse a list of subscripts separated by commas. do { //-- [ (first) or , (subsequent) GetTokenAppend(); //-- The current variable is an array type. if (pType.Form == TFormCode.fcArray) { //--The subscript expression must be assignment type //--compatible with the corresponding subscript type. if (!TType.CheckAssignmentTypeCompatible(pType.array.pIndexType, ParseExpression())) { OnError(TErrorCode.IncompatibleTypes); } //--Update the variable's type. pType = pType.array.pElmtType; } //--No longer an array type, so too many subscripts. //--Parse the extra subscripts anyway for error recovery. else { OnError(TErrorCode.TooManySubscripts); ParseExpression(); } } while (token == TTokenCode.Comma); //-- ] CondGetTokenAppend(TTokenCode.RBracket, TErrorCode.MissingRightBracket); return pType; }
private TType ParseEnumerationType() { TType pType = new TType(TFormCode.fcEnum, sizeof(int), null); SymtabNode pLastId = null; int constValue = -1; GetToken(); Resync(tlEnumConstStart); while (token == TTokenCode.Identifier) { SymtabNode pConstId = EnterNewLocal(pToken.TokenString); ++constValue; if (pConstId.defn.how == TDefnCode.dcUndefined) { pConstId.defn.how = TDefnCode.dcConstant; pConstId.defn.constantValue.integerValue = constValue; TType.SetType(ref pConstId.pType, pType); if (pLastId == null) { pType.Enumeration.ConstIds = pLastId = pConstId; } else { pLastId.Next = pConstId; pLastId = pConstId; } } GetToken(); Resync(tlEnumConstFollow); if (token == TTokenCode.Comma) { do { GetToken(); Resync(tlEnumConstStart, tlEnumConstFollow); if (token == TTokenCode.Comma) OnError(TErrorCode.MissingIdentifier); } while (token == TTokenCode.Comma); if (token != TTokenCode.Identifier) OnError(TErrorCode.MissingComma); } else if (token == TTokenCode.Identifier) OnError(TErrorCode.MissingComma); } CondGetToken(TTokenCode.RParen, TErrorCode.MissingRightParen); pType.Enumeration.max = constValue; return pType; }
private void ParseVarOrFieldDecls(SymtabNode pRoutineId, TType pRecordType, int offset) { SymtabNode pId, pFirstId, pLastId; // ptrs to symtab nodes SymtabNode pPrevSublistLastId = null; // ptr to last node of // previous sublist int totalSize = 0; // local variables // -- Loop to parse a list of variable or field declarations // -- separated by semicolons. while (token == TTokenCode.Identifier) { // -- <id-sublist> pFirstId = ParseIdSublist(pRoutineId, pRecordType, out pLastId); // -- : Resync(tlSublistFollow, tlDeclarationFollow); CondGetToken(TTokenCode.Colon, TErrorCode.MissingColon); // -- <type> TType pType = ParseTypeSpec(); // -- Now loop to assign the type and offset to each // -- identifier in the sublist for (pId = pFirstId; pId != null; pId = pId.Next) { TType.SetType(ref pId.pType, pType); if (pRoutineId != null) { // -- Variables pId.defn.dataOffset = offset++; totalSize += pType.size; } else { // -- Record fields pId.defn.dataOffset = offset; offset += pType.size; } } if (pFirstId != null) { // -- Set the first sublist into the routine id's symtab node. if (pRoutineId != null && (pRoutineId.defn.routine.locals.pVariableIds == null)) { pRoutineId.defn.routine.locals.pVariableIds = pFirstId; } // -- Link this list to the previous sublist if (pPrevSublistLastId != null) pPrevSublistLastId.Next = pFirstId; pPrevSublistLastId = pLastId; } // -- ; for variable and record field declaraion, or // -- END for field declaration if (pRoutineId != null) { Resync(tlDeclarationFollow, tlDeclarationStart); CondGetToken(TTokenCode.Semicolon, TErrorCode.MissingSemicolon); // -- Skip extra semicolons while (token == TTokenCode.Semicolon) GetToken(); Resync(tlDeclarationFollow, tlDeclarationStart, tlStatementStart); } else { Resync(tlFieldDeclFollow); if (token != TTokenCode.End) { CondGetToken(TTokenCode.Semicolon, TErrorCode.MissingSemicolon); // -- Skip extra semicolons while (token == TTokenCode.Semicolon) GetToken(); Resync(tlFieldDeclFollow, tlDeclarationStart, tlStatementStart); } } } // -- Set the routine identifier node or the record type object. if (pRoutineId != null) { pRoutineId.defn.routine.totalLocalSize = totalSize; } else { pRecordType.size = offset; } }
private TType ParseField(TType pType) { GetTokenAppend(); if ((token == TTokenCode.Identifier) && (pType.Form == TFormCode.fcRecord)) { SymtabNode pFieldId = pType.record.pSymtab.Search(pToken.TokenString); if (pFieldId == null) OnError(TErrorCode.InvalidField); icode.Put(pFieldId); GetTokenAppend(); return pFieldId != null ? pFieldId.pType : TType.pDummyType; } else { OnError(TErrorCode.InvalidField); GetTokenAppend(); return TType.pDummyType; } }
private TType ParseArrayType() { TType pArrayType = new TType(TFormCode.fcArray, 0, null); TType pElmtType = pArrayType; bool indexFlag; GetToken(); CondGetToken(TTokenCode.LBracket, TErrorCode.MissingLeftBracket); do { ParseIndexType(pElmtType); Resync(tlIndexFollow, tlIndexStart); if (token == TTokenCode.Comma || TokenIn(token, tlIndexStart)) { pElmtType = TType.SetType(ref pElmtType.array.pElmtType, new TType(TFormCode.fcArray, 0, null)); CondGetToken(TTokenCode.Comma, TErrorCode.MissingComma); indexFlag = true; } else indexFlag = false; } while (indexFlag); CondGetToken(TTokenCode.RBracket, TErrorCode.MissingRightBracket); Resync(tlIndexListFolow, tlDeclarationStart, tlStatementStart); CondGetToken(TTokenCode.Of, TErrorCode.MissingOF); TType.SetType(ref pElmtType.array.pElmtType, ParseTypeSpec()); if (pArrayType.Form != TFormCode.fcNone) { pArrayType.size = ArraySize(pArrayType); } return pArrayType; }
public static bool CheckBoolean(TType firstOperandType, TType secondOperandType) { if ((firstOperandType.Base != pBooleanType) || (secondOperandType != null && (secondOperandType.Base != pBooleanType))) { return false; } else { return true; } }