DTLib/DtsodParser2.cs

208 lines
8.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DTLib
{
class DtsodParser2
{
enum ValueType
{
List,
Complex,
String,
Double,
Long,
Ulong,
Short,
Ushort,
Int,
Uint,
Null,
Boolean,
Default
}
Dictionary<string, dynamic> ParseNew(string text)
{
Dictionary<string, dynamic> parsed = new();
int i = 0;
for (; i < text.Length; i++) ReadName();
return parsed;
void ReadName()
{
bool isListElem = false;
void ReadCommentLine()
{
for (; i < text.Length && text[i] != '\n'; i++) ;
}
dynamic value = null;
StringBuilder defaultNameBuilder = new();
for (; i < text.Length; i++)
{
switch (text[i])
{
case ' ':
case '\t':
case '\r':
case '\n':
break;
case ':':
value = ReadValue();
break;
// строка, начинающаяся с # будет считаться комментом
case '#':
ReadCommentLine();
break;
case '}':
throw new Exception("ParseConfig() error: unexpected '}' at " + i + "char");
// если $ перед названием параметра поставить, значение value добавится в лист с названием name
case '$':
if (defaultNameBuilder.ToString().Length != 0) throw new Exception("unexpected usage of '$' at char " + i.ToString());
isListElem = true;
break;
case ';':
string name = defaultNameBuilder.ToString();
if (isListElem)
{
if (!parsed.ContainsKey(name)) parsed.Add(name, new List<dynamic>());
parsed[name].Add(value);
}
else parsed.Add(name, value);
return;
default:
defaultNameBuilder.Append(text[i]);
break;
}
}
}
dynamic ReadValue()
{
ValueType type = ValueType.Default;
string ReadString()
{
i++;
StringBuilder valueBuilder = new();
for (; text[i] != '"' || text[i - 1] == '\\'; i++)
valueBuilder.Append(text[i]);
type = ValueType.String;
return valueBuilder.ToString();
}
List<string> ReadList()
{
List<string> output = new();
StringBuilder valueBuilder = new();
for (; text[i] != ']'; i++)
{
switch (text[i])
{
case ' ':
case '\t':
case '\r':
case '\n':
break;
case ',':
output.Add(valueBuilder.ToString());
break;
default:
valueBuilder.Append(text[i]);
break;
}
}
type = ValueType.List;
return output;
}
Dictionary<string, dynamic> ReadComplex()
{
i++;
StringBuilder valueBuilder = new();
for (; text[i] != '}'; i++)
{
if (text[i] == '"') valueBuilder.Append(ReadString());
else valueBuilder.Append(text[i]);
}
type = ValueType.Complex;
return ParseNew(valueBuilder.ToString());
}
dynamic value = null;
StringBuilder defaultValueBuilder = new();
for (; i < text.Length; i++)
{
switch (text[i])
{
case ' ':
case '\t':
case '\r':
case '\n':
break;
case '"':
value = ReadString();
break;
case ';':
if (type == ValueType.Default)
{
string valueString = defaultValueBuilder.ToString();
type = valueString switch
{
"true" or "false" => ValueType.Boolean,
"null" => ValueType.Null,
_ when valueString.Contains('.') => ValueType.Null,
_ when (valueString.Length > 2 && valueString[valueString.Length - 2] == 'u') => valueString[valueString.Length - 1] switch
{
's' => ValueType.Ushort,
'i' => ValueType.Uint,
'l' => ValueType.Ulong,
_ => throw new Exception($"Dtsod.Parse.ReadValue() error: wrong type <u{valueString[valueString.Length - 1]}>")
},
_ => valueString[valueString.Length - 1] switch
{
's' => ValueType.Short,
'l' => ValueType.Long,
_ => ValueType.Int
}
};
}
return type switch
{
ValueType.String or ValueType.List or ValueType.Complex => value,
ValueType.Double => SimpleConverter.ToDouble(value),
ValueType.Long => SimpleConverter.ToLong(value.Remove(value.Length - 1)),
ValueType.Ulong => SimpleConverter.ToULong(value.Remove(value.Length - 2)),
ValueType.Short => SimpleConverter.ToShort(value.Remove(value.Length - 1)),
ValueType.Ushort => SimpleConverter.ToUShort(value.Remove(value.Length - 2)),
ValueType.Int => SimpleConverter.ToInt(value),
ValueType.Uint => SimpleConverter.ToUInt(value),
ValueType.Boolean => SimpleConverter.ToBool(value),
ValueType.Null => null,
_ => throw new Exception($"Dtlib.Parse.ReadValue() error: can't convert value to type <{type}>")
};
case '[':
value = ReadList();
break;
case '{':
value = ReadComplex();
break;
default:
defaultValueBuilder.Append(text[i]);
break;
}
}
throw new Exception("Dtsod.Parse.ReadValue error: end of text");
}
}
}
}