Exemplo n.º 1
0
        private static TomlTable CreateStandardTable(TomlTable.RootTable root, StandardTableNode table, IHasComments comments)
        {
            var      keySegments = table.Key.SyntaxNode().GetSegments();
            KeyChain chain       = KeyChain.FromSegments(keySegments);

            if (chain.IsEmpty)
            {
                throw new InvalidOperationException("Empty TOML key is not allowed.");
            }

            TomlTable  owner    = FindOrCreateOwnerTableForTable(root, chain, out TomlKey last);
            TomlObject existing = owner.TryGetValue(last);

            if (existing != null)
            {
                throw new InvalidOperationException($"Cannot define table with key '{chain}' as the owner already " +
                                                    $"contains a row for key '{last}' of type '{existing.ReadableTypeName}'.");
            }
            else
            {
                TomlTable newTable = new TomlTable(root);
                owner.AddRow(last, newTable);
                newTable.AddComments(comments);
                return(newTable);
            }
        }
Exemplo n.º 2
0
        private static TomlTable CreateTableArray(TomlTable.RootTable root, TableArrayNode tableArray, IHasComments comments)
        {
            System.Collections.Generic.IEnumerable <TerminalNode> keySegments = tableArray.Key.SyntaxNode().GetSegments();
            KeyChain chain = KeyChain.FromSegments(keySegments);

            if (chain.IsEmpty)
            {
                throw new InvalidOperationException("Empty TOML key is not allowed.");
            }

            TomlTable  owner    = FindOrCreateOwnerTableForTableArray(root, chain, out TomlKey last);
            TomlObject existing = owner.TryGetValue(last);

            if (existing != null && existing is TomlTableArray existingArray)
            {
                TomlTable newTable = new TomlTable(root);
                existingArray.Add(newTable);
                newTable.AddComments(comments);
                return(newTable);
            }
            else if (existing == null)
            {
                TomlTableArray newTableArray = new TomlTableArray(root);
                owner.AddRow(last, newTableArray);
                TomlTable newTable = new TomlTable(root);
                newTable.AddComments(comments);
                newTableArray.Add(newTable);
                return(newTable);
            }
            else
            {
                throw new InvalidOperationException($"Cannot define table array '{last}' as an object of type "
                                                    + $"'{existing.ReadableTypeName}' exists already.");
            }
        }
Exemplo n.º 3
0
        private static TomlObject ToTomlValue(ITomlRoot root, ValueNode node)
        {
            switch (node.Value.SyntaxNode())
            {
            case TerminalNode tn: return(CreateValueFromTerminal(tn.Terminal));

            case ArrayNode an: return(CreateArrayOrTableArray(an));

            case InlineTableNode it: return(CreateInlineTable(it));

            default: throw new Exception($"Cannot create TomlValue from node with type '{node.GetType()}'.");
            }

            TomlValue CreateValueFromTerminal(Token terminal)
            {
                switch (terminal.Type)
                {
                case TokenType.Integer: return(new TomlInt(root, Convert.ToInt64(Cleanup(terminal.Value, 0)), TomlInt.IntTypes.Decimal));

                case TokenType.HexInteger: return(new TomlInt(root, Convert.ToInt64(Cleanup(terminal.Value, 2), 16), TomlInt.IntTypes.Hex));

                case TokenType.BinaryInteger: return(new TomlInt(root, Convert.ToInt64(Cleanup(terminal.Value, 2), 2), TomlInt.IntTypes.Binary));

                case TokenType.OctalInteger: return(new TomlInt(root, Convert.ToInt64(Cleanup(terminal.Value, 2), 8), TomlInt.IntTypes.Octal));

                case TokenType.Bool: return(new TomlBool(root, Convert.ToBoolean(terminal.Value)));

                case TokenType.String: return(new TomlString(root, terminal.Value.Unescape(terminal)));

                case TokenType.LiteralString: return(new TomlString(root, terminal.Value, TomlString.TypeOfString.Literal));

                case TokenType.MultilineLiteralString: return(new TomlString(root, terminal.Value, TomlString.TypeOfString.MultilineLiteral));

                case TokenType.MultilineString: return(new TomlString(root, terminal.Value, TomlString.TypeOfString.Multiline));

                case TokenType.Float: return(TomlFloat.FromTerminal(root, terminal));

                case TokenType.OffsetDateTime: return(TomlOffsetDateTime.Parse(root, terminal.Value));

                case TokenType.LocalTime: return(TomlLocalTime.Parse(root, terminal.Value));

                case TokenType.Duration: return(TomlDuration.Parse(root, terminal.Value));

                case TokenType.LocalDate: return(TomlLocalDate.Parse(root, terminal.Value));

                case TokenType.LocalDateTime: return(TomlLocalDateTime.Parse(root, terminal.Value));

                default: throw new NotSupportedException();
                }

                string Cleanup(string s, int sub)
                => s.Substring(sub).Replace("_", string.Empty);
            }

            TomlObject CreateArrayOrTableArray(ArrayNode array)
            {
                var values = CreateValues(array.GetValues()).ToList();
                var tables = values.OfType <TomlTable>().ToList();

                if (tables.Count > 0 && tables.Count == values.Count)
                {
                    var ta = new TomlTableArray(root, tables);
                    ta.AddComments(array);
                    return(ta);
                }
                else if (tables.Count == 0)
                {
                    var arr = new TomlArray(root, values.Cast <TomlValue>().ToArray());
                    arr.AddComments(array);
                    return(arr);
                }
                else
                {
                    throw new InvalidOperationException("Array is a mixture of a value array and a TOML table array.");
                }

                IEnumerable <TomlObject> CreateValues(IEnumerable <ValueNode> nodes)
                {
                    var linked       = nodes.Select(n => Tuple.Create(n, ToTomlValue(root, n))).ToList();
                    var expectedType = linked.DistinctBy(n => n.Item2.GetType()).FirstOrDefault();
                    var wrongType    = linked.DistinctBy(n => n.Item2.GetType()).Skip(1).FirstOrDefault();

                    if (wrongType != null)
                    {
                        string msg = $"Expected array value of type '{expectedType.Item2.ReadableTypeName}' " +
                                     $"but value of type '{wrongType.Item2.ReadableTypeName}' was found.'";

                        throw ParseException.MessageForNode(wrongType.Item1, msg);
                    }

                    return(linked.Select(l => l.Item2));
                }
            }

            TomlTable CreateInlineTable(InlineTableNode it)
            {
                TomlTable table = new TomlTable(root, TomlTable.TableTypes.Inline);

                table.AddComments(it);

                System.Collections.Generic.IEnumerable <KeyValueExpressionNode> expressions = it.GetExpressions();

                foreach (KeyValueExpressionNode e in expressions)
                {
                    table.AddRow(e.Key.SyntaxNode().ExpressionKey(), ToTomlValue(root, e.Value.SyntaxNode()));
                }

                return(table);
            }
        }
Exemplo n.º 4
0
        public static TomlTable TryApply(TomlTable current, TomlTable.RootTable root, TokenBuffer tokens)
        {
            tokens.ConsumeAllNewlines();

            var preComments     = CommentProduction.TryParsePreExpressionCommenst(tokens);
            var expressionToken = tokens.Peek();

            tokens.ConsumeAllNewlines();

            var arrayKeyChain = TomlArrayTableProduction.TryApply(tokens);

            if (arrayKeyChain != null)
            {
                var addTo = GetTargetTable(root, arrayKeyChain, CreateImplicitelyType.Table);
                var arr   = GetExistingOrCreateAndAdd(addTo, arrayKeyChain.Last(), errorPosition: expressionToken);

                arr.AddComments(preComments);
                arr.AddComments(CommentProduction.TryParseAppendExpressionComments(expressionToken, tokens));

                var newArrayEntry = new TomlTable(root);
                arr.Add(newArrayEntry);
                return(newArrayEntry);
            }

            var tableKeyChain = TomlTableProduction.TryApply(tokens);

            if (tableKeyChain != null)
            {
                var newTable = new TomlTable(root)
                {
                    IsDefined = true
                };
                newTable.AddComments(preComments);
                newTable.AddComments(CommentProduction.TryParseAppendExpressionComments(expressionToken, tokens));

                var addTo = GetTargetTable(root, tableKeyChain, CreateImplicitelyType.Table);

                var key         = tableKeyChain.Last();
                var existingRow = addTo.TryGetValue(key);
                if (existingRow == null)
                {
                    addTo.AddRow(key, newTable);
                }
                else
                {
                    var tbl = existingRow as TomlTable;
                    if (tbl.IsDefined)
                    {
                        throw new Exception($"Failed to add new table because the target table already contains a row with the key '{key}' of type '{existingRow.ReadableTypeName}'.");
                    }
                    else
                    {
                        tbl.IsDefined = true;
                        return(tbl);
                    }
                }

                return(newTable);
            }

            if (!tokens.End)
            {
                var kvp = KeyValuePairProduction.Apply(root, tokens);
                if (kvp != null)
                {
                    kvp.Item2.AddComments(preComments);
                    kvp.Item2.AddComments(CommentProduction.TryParseAppendExpressionComments(expressionToken, tokens));

                    current.AddRow(kvp.Item1, kvp.Item2);
                    return(current);
                }
            }

            root.AddComments(preComments);

            return(null);
        }