コード例 #1
0
        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;
        }
コード例 #2
0
        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;
        }
コード例 #3
0
        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;
        }
コード例 #4
0
        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);
        }
コード例 #5
0
ファイル: TType.cs プロジェクト: soshimozi/PascalCompiler
        //--------------------------------------------------------------
        //  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;
        }
コード例 #6
0
 private void ParseFieldDeclarations(TType pRecordType, int offset)
 {
     ParseVarOrFieldDecls(null, pRecordType, offset);
 }
コード例 #7
0
ファイル: TType.cs プロジェクト: soshimozi/PascalCompiler
 private static void RemoveType(ref TType pType)
 {
     if (pType != null && (--pType.refCount == 0))
     {
         pType = null;
     }
 }
コード例 #8
0
        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);
        }
コード例 #9
0
ファイル: TType.cs プロジェクト: soshimozi/PascalCompiler
        //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;
        }
コード例 #10
0
ファイル: TType.cs プロジェクト: soshimozi/PascalCompiler
        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;
        }
コード例 #11
0
ファイル: TType.cs プロジェクト: soshimozi/PascalCompiler
        public static TType SetType(ref TType pTargetType, TType pSourceType)
        {
            ++pSourceType.refCount;
            pTargetType = pSourceType;

            return pSourceType;
        }
コード例 #12
0
ファイル: TType.cs プロジェクト: soshimozi/PascalCompiler
        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));
        }
コード例 #13
0
ファイル: TType.cs プロジェクト: soshimozi/PascalCompiler
        public static bool IntegerOperands(TType firstOperandType, TType secondOperandType)
        {
            firstOperandType = firstOperandType.Base;
            secondOperandType = secondOperandType.Base;

            return (firstOperandType == pIntegerType) && (secondOperandType == pIntegerType);
        }
コード例 #14
0
        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;
        }
コード例 #15
0
        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;
        }
コード例 #16
0
        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;
            }
        }
コード例 #17
0
        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;
            }
        }
コード例 #18
0
        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;
        }
コード例 #19
0
ファイル: TType.cs プロジェクト: soshimozi/PascalCompiler
 public static bool CheckBoolean(TType firstOperandType, TType secondOperandType)
 {
     if ((firstOperandType.Base != pBooleanType)
     || (secondOperandType != null && (secondOperandType.Base != pBooleanType)))
     {
         return false;
     }
     else
     {
         return true;
     }
 }