mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-10 12:41:57 -05:00
186 lines
6.0 KiB
C#
186 lines
6.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
|
|
namespace UniJSON
|
|
{
|
|
public static class TomlParser
|
|
{
|
|
static TomlValue ParseLHS(Utf8String segment, int parentIndex)
|
|
{
|
|
var it = segment.GetIterator();
|
|
while (it.MoveNext())
|
|
{
|
|
if (it.Current == '"')
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
else if (it.Current == '.')
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
else if (it.Current == ' ' || it.Current == '\t' || it.Current == '=')
|
|
{
|
|
return new TomlValue(segment.Subbytes(0, it.BytePosition),
|
|
TomlValueType.BareKey, parentIndex);
|
|
}
|
|
}
|
|
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
static TomlValue ParseRHS(Utf8String segment, int parentIndex)
|
|
{
|
|
switch ((char)segment[0])
|
|
{
|
|
case '+':
|
|
case '-':
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
if (segment.IsInt)
|
|
{
|
|
return new TomlValue(segment.SplitInteger(), TomlValueType.Integer, parentIndex);
|
|
}
|
|
else
|
|
{
|
|
return new TomlValue(segment, TomlValueType.Float, parentIndex);
|
|
}
|
|
|
|
case '"':
|
|
{
|
|
int pos;
|
|
if (segment.TrySearchAscii((Byte)'"', 1, out pos))
|
|
{
|
|
return new TomlValue(segment.Subbytes(0, pos + 1), TomlValueType.BasicString, parentIndex);
|
|
}
|
|
else
|
|
{
|
|
throw new ParserException("no close string: " + segment);
|
|
}
|
|
}
|
|
|
|
case '[':
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public static ListTreeNode<TomlValue> Parse(Utf8String segment)
|
|
{
|
|
var values = new List<TomlValue>()
|
|
{
|
|
new TomlValue(segment, TomlValueType.Table, -1),
|
|
};
|
|
var current = 0;
|
|
|
|
while (!segment.IsEmpty)
|
|
{
|
|
segment = segment.TrimStart();
|
|
if (segment.IsEmpty)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (segment[0] == '#')
|
|
{
|
|
// comment line
|
|
// skip to line end
|
|
segment = segment.Subbytes(segment.GetLine().ByteLength);
|
|
continue;
|
|
}
|
|
|
|
if (segment.ByteLength>=4 && segment[0]=='[' && segment[1]=='[')
|
|
{
|
|
// [[array_name]]
|
|
throw new NotImplementedException();
|
|
}
|
|
else if (segment.ByteLength>=2 && segment[0]=='[')
|
|
{
|
|
// [table_name]
|
|
int table_end;
|
|
if (!segment.TrySearchByte(x => x == ']', out table_end))
|
|
{
|
|
throw new ParserException("] not found");
|
|
}
|
|
var table_name = segment.Subbytes(1, table_end-1).Trim();
|
|
if (table_name.IsEmpty)
|
|
{
|
|
throw new ParserException("empty table name");
|
|
}
|
|
|
|
// top level key
|
|
values.Add(new TomlValue(table_name, TomlValueType.Table, 0));
|
|
current = values.Count - 1;
|
|
|
|
// skip to line end
|
|
segment = segment.Subbytes(segment.GetLine().ByteLength);
|
|
}
|
|
else
|
|
{
|
|
// key = value
|
|
{
|
|
var key = ParseLHS(segment, current);
|
|
switch(key.TomlValueType)
|
|
{
|
|
case TomlValueType.BareKey:
|
|
case TomlValueType.QuotedKey:
|
|
{
|
|
values.Add(key);
|
|
|
|
// skip key
|
|
segment = segment.Subbytes(key.Bytes.Count);
|
|
}
|
|
break;
|
|
|
|
case TomlValueType.DottedKey:
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
{
|
|
// search and skip =
|
|
int eq;
|
|
if (!segment.TrySearchByte(x => x == '=', out eq))
|
|
{
|
|
throw new ParserException("= not found");
|
|
}
|
|
segment = segment.Subbytes(eq + 1);
|
|
|
|
// skip white space
|
|
segment = segment.TrimStart();
|
|
}
|
|
|
|
{
|
|
var value = ParseRHS(segment, current);
|
|
values.Add(value);
|
|
|
|
// skip value
|
|
segment = segment.Subbytes(value.Bytes.Count);
|
|
|
|
// skip to line end
|
|
segment = segment.Subbytes(segment.GetLine().ByteLength);
|
|
}
|
|
}
|
|
}
|
|
|
|
return new ListTreeNode<TomlValue>(values);
|
|
}
|
|
|
|
public static ListTreeNode<TomlValue> Parse(String Toml)
|
|
{
|
|
return Parse(Utf8String.From(Toml));
|
|
}
|
|
}
|
|
}
|