コード例 #1
0
        // reads a construction component of a complex value
        private IStonConstruction ReadConstruction(StonTokenReader reader)
        {
            reader.ExpectAndSkip(StonChartype.ConstructionOpen);

            var positionalParameters = new List <IStonEntity>();
            var namedParameters      = new List <KeyValuePair <string, IStonEntity> >();

            while (!reader.TryAndSkip(StonChartype.ConstructionClose))
            {
                // trying to read a positional parameter, or the first named parameter
                if (namedParameters.Count == 0)
                {
                    // value prompt right at the beginning clearly indicates a positional parameter
                    if (reader.TryAndSkip(StonChartype.ValuePrompt))
                    {
                        positionalParameters.Add(ReadEntity(reader));
                    }
                    // string literal might be an entity or a named parameter name
                    else if (reader.Peek().HasChartype(StonChartype.TextDelimiter))
                    {
                        var builder = new StringBuilder();

                        reader.ReadString(builder, false);

                        // if it's a single string literal followed by a value prompt, it means it is the first named parameter
                        if (reader.TryAndSkip(StonChartype.ValuePrompt))
                        {
                            namedParameters.Add(new KeyValuePair <string, IStonEntity>(builder.ToString(), ReadEntity(reader)));
                        }
                        // if no value prompt follows, it is assumed to be a string-valued entity
                        else
                        {
                            while (reader.Peek().HasChartype(StonChartype.StringChainContinue))
                            {
                                if (reader.ReadAndSkip().HasChartype(StonChartype.StringChainOpen))
                                {
                                    builder.Append('\n');
                                }
                                reader.ReadString(builder, false);
                            }
                            positionalParameters.Add(ElementFactory.CreateSimpleEntity(ElementFactory.CreateSimpleValue(StonDataType.Text, builder.ToString())));
                        }
                    }
                    else
                    {
                        var entity = ReadEntity(reader);
                        if (reader.Peek().HasChartype(StonChartype.ValuePrompt))
                        {
                            // if value prompt follows after the read entity, it means the read entity must be a typeless, non-identified CANUN named value
                            // serving as the parameter name
                            if (!(entity is IStonSimpleEntity))
                            {
                                throw reader.MakeUnexpectedCharacterException(StonChartype.SequenceSeparator | StonChartype.ConstructionClose);
                            }
                            var simpleEntity = entity as IStonSimpleEntity;
                            if (simpleEntity.GlobalIdentifier != null || simpleEntity.Type != null || simpleEntity.Value.DataType != StonDataType.Named || simpleEntity.Value.Content.Contains('.'))
                            {
                                throw reader.MakeUnexpectedCharacterException(StonChartype.SequenceSeparator | StonChartype.ConstructionClose);
                            }
                            reader.ReadAndSkip();
                            namedParameters.Add(new KeyValuePair <string, IStonEntity>(simpleEntity.Value.Content, ReadEntity(reader)));
                        }
                        else
                        {
                            positionalParameters.Add(entity);
                        }
                    }
                }
                // reading remaining named parameters
                else
                {
                    string name;
                    if (reader.Peek().HasChartype(StonChartype.TextDelimiter))
                    {
                        name = reader.ReadString();
                    }
                    else if (reader.Peek().HasChartype(StonChartype.CanunBegin))
                    {
                        name = reader.ReadCanun();
                    }
                    else
                    {
                        throw reader.MakeUnexpectedCharacterException(StonChartype.TextDelimiter | StonChartype.CanunBegin);
                    }

                    reader.ExpectAndSkip(StonChartype.ValuePrompt);
                    IStonEntity value = ReadEntity(reader);

                    namedParameters.Add(new KeyValuePair <string, IStonEntity>(name, value));
                }

                if (reader.TryAndSkip(StonChartype.SequenceSeparator))
                {
                    continue;
                }
                else if (!reader.Peek().HasChartype(StonChartype.ConstructionClose))
                {
                    throw reader.MakeUnexpectedCharacterException(StonChartype.SequenceSeparator | StonChartype.ConstructionClose);
                }
            }

            return(ElementFactory.CreateConstruction(positionalParameters, namedParameters));
        }