Пример #1
0
        // reads a bare collection type expression
        // which might represent a bare named type expression
        // or an indefinitely nested collection of element type, represented as bare named type expression
        private IStonType ReadBareCollection(StonTokenReader reader, string preread, ref bool collectionStarted)
        {
            IStonType result = ReadBareNamedType(reader, preread);

            if (result == null)
            {
                return(null);
            }

            // each collection suffix adds one more nesting of collection
            while (reader.Peek().HasChartype(StonChartype.CollectionSuffixBegin))
            {
                if (!reader.ReadCollectionTypeSuffix(true))
                {
                    collectionStarted = true;
                    break;
                }
                else
                {
                    result = ElementFactory.CreateCollectionType(result);
                }
            }

            return(result);
        }
Пример #2
0
 /// <summary>
 /// Determines whether two types are equivalent.
 /// </summary>
 /// <param name="x">The first type to compare.</param>
 /// <param name="y">The second type to compare.</param>
 /// <returns>True when types are equivalent, false otherwise.</returns>
 public bool Equals(IStonType x, IStonType y)
 {
     if (x == y)
     {
         return(true);
     }
     else if (x == null || y == null)
     {
         return(false);
     }
     else if (x is IStonNamedType && y is IStonNamedType)
     {
         return(Equals(x as IStonNamedType, y as IStonNamedType));
     }
     else if (x is IStonCollectionType && y is IStonCollectionType)
     {
         return(Equals(x as IStonCollectionType, y as IStonCollectionType));
     }
     else if (x is IStonUnionType && y is IStonUnionType)
     {
         return(Equals(x as IStonUnionType, y as IStonUnionType));
     }
     else
     {
         return(false);
     }
 }
Пример #3
0
 /// <summary>
 /// Creates a new STON collection type, with a given collection element type.
 /// </summary>
 /// <param name="elementType">The type of the collection elements.</param>
 public StonCollectionType(IStonType elementType)
 {
     if (elementType == null)
     {
         throw new ArgumentNullException("elementType");
     }
     ElementType = StonType.Copy(elementType);
 }
Пример #4
0
        public AComplexEntity(IStonConstruction construction = null, IStonMemberInit memberInit = null, IStonCollectionInit collectionInit = null, IStonType type = null, string globalIdentifier = null)
        {
            GlobalIdentifier = globalIdentifier;
            Type             = type;

            Construction   = construction;
            MemberInit     = memberInit;
            CollectionInit = collectionInit;
        }
Пример #5
0
 // writes a wrapped type definition for a given type
 private void WriteTypeDefinition(StonTokenWriter writer, IStonType type)
 {
     if (type == null)
     {
         return;
     }
     writer.Write('<');
     WriteType(writer, type);
     writer.Write('>');
 }
Пример #6
0
        /// <summary>
        /// Creates a new simple-valued entity, with a given value and optional declared type and global identifier.
        /// </summary>
        /// <param name="value">The value of the entity.</param>
        /// <param name="type">The declared type of the entity.</param>
        /// <param name="globalIdentifier">The global identifier of the entity.</param>
        public StonSimpleEntity(IStonSimpleValue value, IStonType type = null, string globalIdentifier = null)
            : base(type, globalIdentifier)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            Value = StonSimpleValue.Copy(value);

            Helpers.Validator.ValidateEntity(this);
        }
Пример #7
0
        // reads a wrapped collection type expression
        // which might represent a wrapped named type expression
        // or an indefinitely nested collection of element type, represented as wrapped named type expression
        private IStonType ReadWrappedCollection(StonTokenReader reader)
        {
            IStonType result = ReadWrappedNamedType(reader);

            // each collection suffix adds one more nesting of collection
            while (reader.Peek().HasChartype(StonChartype.CollectionSuffixBegin))
            {
                reader.ReadCollectionTypeSuffix(false);
                result = ElementFactory.CreateCollectionType(result);
            }

            return(result);
        }
Пример #8
0
 /// <summary>
 /// Creates a structurally equivalent type from a given type.
 /// </summary>
 /// <param name="type">The type to copy the structure of.</param>
 /// <returns>A structurally equivalent copy of the given type.</returns>
 public static IStonType Copy(IStonType type)
 {
     if (type == null)
     {
         throw new ArgumentNullException("type");
     }
     if (type is IStonNamedType)
     {
         return(StonNamedType.Copy(type as IStonNamedType));
     }
     if (type is IStonCollectionType)
     {
         return(StonCollectionType.Copy(type as IStonCollectionType));
     }
     if (type is IStonUnionType)
     {
         return(StonUnionType.Copy(type as IStonUnionType));
     }
     throw new StonImplementationException(type.GetType(), typeof(IStonType), typeof(IStonNamedType), typeof(IStonCollectionType), typeof(IStonUnionType));
 }
Пример #9
0
 /// <summary>
 /// Returns a hash code for a given type.
 /// </summary>
 /// <param name="obj">The type to get a hash code of.</param>
 /// <returns>The hash code for the type.</returns>
 public int GetHashCode(IStonType obj)
 {
     if (obj == null)
     {
         return(0);
     }
     else if (obj is IStonNamedType)
     {
         return(GetHashCode(obj as IStonNamedType));
     }
     else if (obj is IStonCollectionType)
     {
         return(GetHashCode(obj as IStonCollectionType));
     }
     else if (obj is IStonUnionType)
     {
         return(GetHashCode(obj as IStonUnionType));
     }
     else
     {
         return(0);
     }
 }
Пример #10
0
 /// <summary>
 /// Checks the validity of a given STON type.
 /// </summary>
 /// <param name="type">The type to check the validity of.</param>
 public static void ValidateType(IStonType type)
 {
     if (type == null)
     {
         throw new ArgumentNullException("type");
     }
     else if (type is IStonNamedType)
     {
         ValidateType(type as IStonNamedType);
     }
     else if (type is IStonCollectionType)
     {
         ValidateType(type as IStonCollectionType);
     }
     else if (type is IStonUnionType)
     {
         ValidateType(type as IStonUnionType);
     }
     else
     {
         throw new StonImplementationException(type.GetType(), typeof(IStonType), typeof(IStonNamedType), typeof(IStonCollectionType), typeof(IStonUnionType));
     }
 }
Пример #11
0
 // writes any type
 private void WriteType(StonTokenWriter writer, IStonType type)
 {
     if (type == null)
     {
         throw new StonException("A non-existing type has been found in the structure to be written.");
     }
     else if (type is IStonNamedType)
     {
         WriteType(writer, type as IStonNamedType);
     }
     else if (type is IStonCollectionType)
     {
         WriteType(writer, type as IStonCollectionType);
     }
     else if (type is IStonUnionType)
     {
         WriteType(writer, type as IStonUnionType);
     }
     else
     {
         throw new StonImplementationException(type.GetType(), typeof(IStonType), typeof(IStonNamedType), typeof(IStonCollectionType), typeof(IStonUnionType));
     }
 }
Пример #12
0
 /// <summary>
 /// Creates a new STON valued entity, with a given declared type and global identifier.
 /// </summary>
 /// <param name="type">The declared type or the entity.</param>
 /// <param name="globalIdentifier">The global identifier of the entity.</param>
 protected StonValuedEntity(IStonType type, string globalIdentifier)
     : base(globalIdentifier)
 {
     Type = type != null?StonType.Copy(type) : null;
 }
Пример #13
0
        /// <summary>
        /// Creates a new complex-valued entity, with a given value and optional declared type and global identifier.
        /// </summary>
        /// <param name="construction">The construction part of the complex value.</param>
        /// <param name="memberInit">The member initialization part of the complex value.</param>
        /// <param name="collectionInit">The collection initialization part of the complex value.</param>
        /// <param name="type">The declared type of the entity.</param>
        /// <param name="globalIdentifier">The global identifier of the entity.</param>
        public StonComplexEntity(IStonConstruction construction = null, IStonMemberInit memberInit = null, IStonCollectionInit collectionInit = null, IStonType type = null, string globalIdentifier = null)
            : base(type, globalIdentifier)
        {
            Construction = construction != null?StonConstruction.Copy(construction) : null;

            MemberInit = memberInit != null?StonMemberInit.Copy(memberInit) : null;

            CollectionInit = collectionInit != null?StonCollectionInit.Copy(collectionInit) : null;

            Helpers.Validator.ValidateEntity(this);
        }
Пример #14
0
 public ACollectionType(IStonType elementType)
 {
     ElementType = elementType;
 }
Пример #15
0
 public ASimpleEntity(IStonSimpleValue value, IStonType type = null, string globalIdentifier = null)
 {
     GlobalIdentifier = globalIdentifier;
     Type             = type;
     Value            = value;
 }
Пример #16
0
 /// <summary>
 /// Creates a new STON union type, with a given sequence of permitted types.
 /// </summary>
 /// <param name="permittedTypes">The sequence of permitted types.</param>
 /// <returns>The new STON type.</returns>
 public IStonCollectionType CreateCollectionType(IStonType elementType)
 => new StonCollectionType(elementType);
Пример #17
0
 /// <summary>
 /// Creates a new complex-valued entity, with a given value and optional declared type and global identifier.
 /// </summary>
 /// <param name="construction">The construction part of the complex value.</param>
 /// <param name="memberInit">The member initialization part of the complex value.</param>
 /// <param name="collectionInit">The collection initialization part of the complex value.</param>
 /// <param name="type">The declared type of the entity.</param>
 /// <param name="globalIdentifier">The global identifier of the entity.</param>
 /// <returns>The new STON entity.</returns>
 public IStonComplexEntity CreateComplexEntity(IStonConstruction construction = null, IStonMemberInit memberInit = null, IStonCollectionInit collectionInit = null, IStonType type = null, string globalIdentifier = null)
 => new StonComplexEntity(construction, memberInit, collectionInit, type, globalIdentifier);
Пример #18
0
 /// <summary>
 /// Creates a new simple-valued entity, with a given value and optional declared type and global identifier.
 /// </summary>
 /// <param name="value">The value of the entity.</param>
 /// <param name="type">The declared type of the entity.</param>
 /// <param name="globalIdentifier">The global identifier of the entity.</param>
 /// <returns>The new STON entity.</returns>
 public IStonSimpleEntity CreateSimpleEntity(IStonSimpleValue value, IStonType type = null, string globalIdentifier = null)
 => new StonSimpleEntity(value, type, globalIdentifier);
Пример #19
0
        // reads a STON entity, complete or address
        private IStonEntity _ReadEntity(StonTokenReader reader, bool isAddress)
        {
            // stores a CANUN identifier or path for later use until its purpose is known
            string storedWord = null;

            // determining the global identifier, if any
            string globalIdentifier = null;

            // the identifier is explicitly prepended with a global identifier sigil
            if (reader.Peek().HasChartype(StonChartype.IdentifierSigil))
            {
                if (isAddress)
                {
                    throw reader.MakeUnexpectedCharacterException(StonChartype.None);                   // identifiers are not allowed for index parameter entities
                }
                reader.ReadAndSkip();
                globalIdentifier = reader.ReadCanun();
                reader.ExpectAndSkip(StonChartype.IdentifierAssign);
            }
            // the entity begins with a CANUN name that might or might not be a global identifier
            else if (reader.Peek().HasChartype(StonChartype.CanunBegin))
            {
                storedWord = reader.ReadCanun();
                // if and only if the CANUN name is followed by a global identifier assignment token
                // the name is to be used as a global identifier
                if (reader.Peek().HasChartype(StonChartype.IdentifierAssign))
                {
                    if (isAddress)
                    {
                        throw reader.MakeUnexpectedCharacterException(StonChartype.None);               // once again, identifiers are not allowed for index parameter entities
                    }
                    reader.ReadAndSkip();
                    globalIdentifier = storedWord;
                    storedWord       = null;
                }
            }

            // finding the address, if any
            if (reader.Peek().HasChartype(StonChartype.AddressBegin))
            {
                // the reference entity cannot have a type declaration
                if (storedWord != null)
                {
                    throw reader.MakeUnexpectedCharacterException(StonChartype.None);
                }

                return(ElementFactory.CreateReferenceEntity(ReadAddress(reader), globalIdentifier));
            }

            // determining the type, if any
            IStonType type              = null;
            bool      isTypeFromWord    = false;
            bool      collectionStarted = false; // a variable indicating whether during reading type a collection initialization has been started or not

            // when bare type definitions are involved, a collection initialization might appear like a collection type suffix
            // so it's impossible to tell the two apart before reading the initial sign

            // no word is stored; either there was no word in the first place, or there was a global identifier before
            if (storedWord == null)
            {
                // storing a CANUN path, which might be a type or a named value
                if (reader.Peek().HasChartype(StonChartype.CanunBegin))
                {
                    storedWord = ReadCanunPath(reader);
                }
                // reading a type if the following token is characteristic for types
                else if (reader.Peek().HasChartype(StonChartype.Extension | StonChartype.TypeOpen))
                {
                    type = ReadBareUnion(reader, null, ref collectionStarted);
                }
            }
            else
            {
                // if a CANUN name is stored, it might be a part of a longer CANUN path
                // which itself might be a type or a named value
                if (reader.Peek().HasChartype(StonChartype.NameSeparator))
                {
                    storedWord = storedWord + (char)reader.ReadAndSkip() + ReadCanunPath(reader);
                }
            }

            // if a CANUN path is followed by a type opening, collection suffix or a union type separator
            // it means that path must be a type name
            if (storedWord != null && reader.Peek().HasChartype(StonChartype.TypeOpen | StonChartype.CollectionSuffixBegin | StonChartype.UnionTypeSeparator))
            {
                type       = ReadBareUnion(reader, storedWord, ref collectionStarted);
                storedWord = null;
            }
            if (storedWord != null)
            {
                type           = ElementFactory.CreateNamedType(storedWord);
                isTypeFromWord = true;
            }


            // finding the complex value, if any

            // when the collection initialization has been entered when reading a type definition
            // the rest of the collection initialization is read
            if (collectionStarted)
            {
                // a complex value is not allowed in an address index parameter
                if (isAddress)
                {
                    throw reader.MakeUnexpectedCharacterException(StonChartype.CollectionSuffixContinue);
                }

                // reading the rest of the collection initialization
                // and subsequent member initialization, if available
                IStonCollectionInit collectionInit = ReadCollectionInit(reader, true);
                IStonMemberInit     memberInit     = null;
                if (reader.Peek().HasChartype(StonChartype.MemberInitOpen))
                {
                    memberInit = ReadMemberInit(reader);
                }

                return(ElementFactory.CreateComplexEntity(null, memberInit, collectionInit, type, globalIdentifier));
            }

            // reading any valid combination of complex value components (construction, member initialization, collection initialization)
            if (reader.Peek().HasChartype(StonChartype.ConstructionOpen | StonChartype.MemberInitOpen | StonChartype.CollectionInitOpen))
            {
                // a complex value is not allowed in an address index parameter
                if (isAddress)
                {
                    throw reader.MakeUnexpectedCharacterException(StonChartype.None);
                }

                IStonConstruction   constructor    = null;
                IStonMemberInit     memberInit     = null;
                IStonCollectionInit collectionInit = null;

                if (reader.Peek().HasChartype(StonChartype.ConstructionOpen))
                {
                    constructor = ReadConstruction(reader);
                }
                if (reader.Peek().HasChartype(StonChartype.MemberInitOpen))
                {
                    memberInit = ReadMemberInit(reader);
                }
                if (reader.Peek().HasChartype(StonChartype.CollectionInitOpen))
                {
                    collectionInit = ReadCollectionInit(reader);
                    if (memberInit == null && reader.Peek().HasChartype(StonChartype.MemberInitOpen))
                    {
                        memberInit = ReadMemberInit(reader);
                    }
                }

                return(ElementFactory.CreateComplexEntity(constructor, memberInit, collectionInit, type, globalIdentifier));
            }

            // finding the string, binary or number simple value, if complex value is not present

            // reading a string literal or string literals chain
            if (reader.TryAndSkip(StonChartype.StringChainOpen))
            {
                if (!reader.Peek().HasChartype(StonChartype.TextDelimiter | StonChartype.CodeDelimiter))
                {
                    throw reader.MakeUnexpectedCharacterException(StonChartype.TextDelimiter | StonChartype.CodeDelimiter);
                }
            }
            if (reader.Peek().HasChartype(StonChartype.TextDelimiter | StonChartype.CodeDelimiter))
            {
                bool isCode = reader.Peek().HasChartype(StonChartype.CodeDelimiter);        // whether the value is a text or a code

                var builder = new StringBuilder();
                reader.ReadString(builder, isCode);
                while (reader.Peek().HasChartype(StonChartype.StringChainContinue))
                {
                    if (reader.ReadAndSkip().HasChartype(StonChartype.StringChainOpen))
                    {
                        builder.Append('\n');
                    }
                    reader.ReadString(builder, isCode);
                }

                return(ElementFactory.CreateSimpleEntity(ElementFactory.CreateSimpleValue(isCode ? StonDataType.Code : StonDataType.Text, builder.ToString()), type, globalIdentifier));
            }

            // reading a number of binary value
            bool minus = false;

            // reading the initial sign, if any
            if (reader.Peek().HasChartype(StonChartype.Sign))
            {
                if (reader.ReadAndSkip() == '-')
                {
                    minus = true;
                }
                // a digit must follow the sign
                if (!reader.Peek().HasChartype(StonChartype.Digit))
                {
                    throw reader.MakeUnexpectedCharacterException(StonChartype.Digit);
                }
            }
            // both number and binary literals might begin with a zero (excluding initial sign)
            // whichever it is, is decided by whether the zero is followed by a base identifier or not
            if (reader.TryAndSkip(StonChartype.ZeroDigit))
            {
                if (reader.Peek().HasChartype(StonChartype.BaseIdentifier))
                {
                    return(ElementFactory.CreateSimpleEntity(ElementFactory.CreateSimpleValue(StonDataType.Binary, reader.ReadBinaryContent(minus)), type, globalIdentifier));
                }
                else
                {
                    return(ElementFactory.CreateSimpleEntity(ElementFactory.CreateSimpleValue(StonDataType.Number, reader.ReadNumberContent(minus)), type, globalIdentifier));
                }
            }
            // only number literals might begin with a non-zero digit (aside from initial sign)
            else if (reader.Peek().HasChartype(StonChartype.NonZeroDigit))
            {
                return(ElementFactory.CreateSimpleEntity(ElementFactory.CreateSimpleValue(StonDataType.Number, reader.ReadNumberContent(minus)), type, globalIdentifier));
            }

            // finding the named or null value, if everything else fails

            string value;

            if (reader.Peek().HasChartype(StonChartype.CanunBegin))
            {
                value = ReadCanunPath(reader);
            }
            else if (isTypeFromWord)
            {
                value = (type as IStonNamedType).Name;
                type  = null;
            }
            else
            {
                throw reader.MakeUnexpectedCharacterException(StonChartype.None);       // there is no named value, and thus there's all the reason to panic
            }
            if (value == "null")
            {
                return(ElementFactory.CreateSimpleEntity(ElementFactory.CreateSimpleValue(StonDataType.Null, null), type, globalIdentifier));
            }
            else
            {
                return(ElementFactory.CreateSimpleEntity(ElementFactory.CreateSimpleValue(StonDataType.Named, value), type, globalIdentifier));
            }
        }