Update to version 1.0.0 #3

Merged
Booklordofthedings merged 23 commits from dev into main 2024-08-26 13:33:38 +02:00
6 changed files with 345 additions and 28 deletions
Showing only changes of commit 7da72c9344 - Show all commits

View file

@ -4,8 +4,23 @@ using System;
class Bofa
{
private String _line = null; //The actual line
private Bofa _lastObject = null; //If we are a container we keep track of the last container inside of us
public StringView Name;
public EBofaType Type;
public StringView Typename;
public BofaValue Value;
public ~this()
{
if(_line != null)
delete _line;
if(Type == .Text)
delete Value.Text;
else if(Type == .Object)
DeleteDictionaryAndValues!(Value.Object);
else if(Type == .Array)
DeleteContainerAndItems!(Value.Array);
}
}

View file

@ -8,41 +8,283 @@ using Bofa.Parser;
class BofaParser
{
public static Result<void, int64> Parse(StringView pToParse, List<Bofa> pResult)
public static void Parse(StringView pToParse, List<Bofa> pResult, List<int64> pErrors)
{
StringStream stream = new .(pToParse, .Reference);
defer delete stream;
return Parse(stream, pResult);
Parse(stream, pResult, pErrors);
}
public static Result<void, int64> Parse(Stream pToParse, List<Bofa> pResult)
public static void Parse(Stream pToParse, List<Bofa> pResult, List<int64> pErrors)
{
if(pToParse == null || pResult == null)
return .Err(-1);
if (pToParse == null || pResult == null)
{ //Cannot parse what doesnt exist
pErrors.Add(-1);
return;
}
StreamReader reader = new .(pToParse);
defer delete reader;
int64 line = 1;
while(reader.Peek() case .Ok) //This might technically cause an issue when there is data added to the stream while we where busy processing, but if you hook this up to a network stream you deserve this happening to you
while (reader.Peek() case .Ok) //This might technically cause an issue when there is data added to the stream while we where busy processing, but if you hook this up to a network stream you deserve this happening to you
{
String l = scope .();
if(reader.ReadLine(l) case .Err)
return .Err(-2);
String l = new .();
if (reader.ReadLine(l) case .Err)
{ //Despite data being here, we cannot read it
pErrors.Add(-2);
return;
}
var entry = ParseLine(l, line);
if(!(entry.Type == .Bofa || entry.Type == .Text))
delete l; //In these cases we have no useable data
if(entry.Type == .Error)
pErrors.Add(line);
//If we are on the lowest level we can just add them here
if(entry.Depth == 0 && entry.Type ==.Bofa)
{
if(pResult.FindIndex(scope (x) => { return x.Name == entry.Data.Bofa.Name;}) < 0)
pResult.Add(entry.Data.Bofa);
else
pErrors.Add(entry.Line); //Dublicate name error
}
else if(entry.Depth == 1 && entry.Type == .Text)
{
if(pResult[pResult.Count-1].Type == .Text)
pResult[pResult.Count-1].Value.Text.Append(entry.Data.Text);
else
pErrors.Add(entry.Line); //Bad text error
}
//if(pResult[pResult.Count-1].[Friend]_Insert(&entry) case .Err)
//pErrors.Add(line);
line++;
}
return .Ok;
return; //Being done normally
}
private static ParserEntry ParseLine(StringView pLine, int64 pLineNumber)
private static ParserEntry ParseLine(String pLine, int64 pLineNumber)
{
StringView line = pLine;
ParserEntry toReturn = .();
uint32 depth;
return .();
toReturn.Line = pLineNumber;
#region Depth
uint32 depth = 0;
var hasContent = false; //In order to check wether it just ran out, or wether we actually have content
for (var c in line)
{
if (c == ' ' || c == ' ')
{
depth++;
continue;
}
else if (c == '#')
{
toReturn.Type = .Empty;
return toReturn; //Comment
}
hasContent = true;
break;
}
if (!hasContent)
{
toReturn.Type = .Empty;
return toReturn; //Is empty
}
line = .(line, depth);
toReturn.Depth = depth;
#endregion
#region Type
//Get the type of the line
let type = NextPart(line);
line = type.1;
if (type.0 == "") //This should never be reached
{
Runtime.FatalError("Unreachable code reached");
toReturn.Type = .Error;
return toReturn;
}
else if (type.0 == "-")
{
toReturn.Type = .Text;
toReturn.Data.Text = line;
toReturn.Depth = depth + 1;
return toReturn;
}
//We have now assured, that the object we are handling is seemingly a normal one
StringView typeName;
switch (type.0)
{
case "c":
let tnameres = NextPart(line);
if (tnameres.0 == "")
{ //Its of type custom but ends after the custom
toReturn.Type = .Error;
return toReturn;
}
line = tnameres.1;
typeName = tnameres.0;
case "n":
typeName = "Number";
case "b":
typeName = "Boolean";
case "l":
typeName = "Line";
case "bn":
typeName = "BigNumber";
case "i":
typeName = "Integer";
case "bi":
typeName = "BigInteger";
case "t":
typeName = "Text";
case "a":
typeName = "Array";
case "o":
typeName = "Object";
default:
toReturn.Type = .Error;
return toReturn; //Unsupported type error
}
#endregion
#region Name
//Get the name and return if its a array or object
let nameres = NextPart(line);
line = nameres.1;
if (nameres.0 == "")
{
toReturn.Type = .Error;
return toReturn;
}
if (type.0 == "o" || type.0 == "a")
{
Bofa bofaRes = new Bofa();
bofaRes.Name = nameres.0;
bofaRes.Typename = typeName;
if (type.0 == "o")
{
bofaRes.Type = .Object;
bofaRes.Value.Object = new .();
toReturn.Type = .Bofa;
toReturn.Data.Bofa = bofaRes;
return toReturn;
}
bofaRes.Type = .Array;
bofaRes.Value.Array = new .();
toReturn.Type = .Bofa;
toReturn.Data.Bofa = bofaRes;
return toReturn;
}
#endregion
#region Value
if (line == "")
{
toReturn.Type = .Error;
return toReturn;
}
Bofa bofaRes = new .();
bofaRes.Name = nameres.0;
bofaRes.Typename = typeName;
switch (type.0)
{
case "n":
bofaRes.Type = .Number;
var result = float.Parse(line);
if (result case .Err)
{
delete bofaRes;
toReturn.Type = .Error;
return toReturn;
}
bofaRes.Value.Number = result.Value;
case "b":
if (line == "true")
bofaRes.Value.Boolean = true;
else if (line == "false")
bofaRes.Value.Boolean = false;
else
{
delete bofaRes;
toReturn.Type = .Error;
return toReturn;
}
bofaRes.Type = .Boolean;
case "l":
bofaRes.Value.Line = line;
bofaRes.Type = .Line;
case "bn":
bofaRes.Type = .BigNumber;
var result = double.Parse(line);
if (result case .Err)
{
delete bofaRes;
toReturn.Type = .Error;
return toReturn;
}
bofaRes.Value.BigNumber = result.Value;
case "i":
bofaRes.Type = .Integer;
var result = int32.Parse(line);
if (result case .Err)
{
delete bofaRes;
toReturn.Type = .Error;
return toReturn;
}
bofaRes.Value.Integer = result.Value;
case "bi":
bofaRes.Type = .BigInteger;
var result = int64.Parse(line);
if (result case .Err)
{
delete bofaRes;
toReturn.Type = .Error;
return toReturn;
}
bofaRes.Value.BigInteger = result.Value;
case "t":
bofaRes.Value.Text = new String(line);
bofaRes.Type = .Text;
case "c":
bofaRes.Value.Custom = line;
bofaRes.Type = .Custom;
default: //Unknown type
delete bofaRes;
toReturn.Type = .Error;
return toReturn;
}
#endregion
//If this ever returns something went wrong
bofaRes.[Friend]_line = pLine;
toReturn.Type = .Bofa;
toReturn.Data.Bofa = bofaRes;
return toReturn;
}
private static (StringView, StringView) NextPart(StringView pLine)
{
int i = 0;
for (var c in pLine)
{
if (c == ' ')
{
if (@c.GetNext() case .Ok(let val))
{
i++;
}
break;
}
i++;
}
return (.(pLine, 0, (i < pLine.Length) ? i - 1 : i), .(pLine, i));
}
}

View file

@ -6,14 +6,14 @@ using System.Collections;
[Union]
struct BofaValue
{
StringView Line;
StringView Text;
float Number;
double BigNumber;
int32 Integer;
int64 BigInteger;
bool Boolean;
String Custom;
Bofa Object;
Bofa Array;
public StringView Line;
public String Text;
public float Number;
public double BigNumber;
public int32 Integer;
public int64 BigInteger;
public bool Boolean;
public StringView Custom;
public Dictionary<StringView, Bofa> Object;
public List<Bofa> Array;
}

View file

@ -0,0 +1,42 @@
namespace Bofa;
using Bofa.Parser;
using System;
extension Bofa
{
private Result<void> _Insert(ParserEntry* pToAdd)
{
//See if we can insert and do so
if(pToAdd.Depth == 0 || (pToAdd.Type == .Text && pToAdd.Depth == 1))
{
if(pToAdd.Type == .Text && _lastObject.Type == .Text)
{
_lastObject.Value.Text.Append(pToAdd.Data.Text);
return .Ok;
}
else if(_lastObject.Type == .Object)
{
_lastObject.Value.Object.Add(pToAdd.Data.Bofa.Name, pToAdd.Data.Bofa);
_lastObject._lastObject = pToAdd.Data.Bofa;
return .Ok;
}
else if(_lastObject.Type == .Array)
{
_lastObject.Value.Array.Add(pToAdd.Data.Bofa);
_lastObject._lastObject = pToAdd.Data.Bofa;
return .Ok;
}
return .Err; //Cannot insert here
}
//Can we even go deeper
if(!(_lastObject.Type == .Object || _lastObject.Type == .Array))
return .Err;
pToAdd.Depth--;
return _lastObject._Insert(pToAdd);
}
}

View file

@ -4,5 +4,6 @@ enum EParserEntryType
{
Bofa,
Text,
Empty
Empty,
Error
}

View file

@ -2,13 +2,30 @@ namespace Bofa.Testing;
using System;
using System.IO;
using System.Collections;
class Default
{
[Test]
public static void Default_Test_1()
{
BofaParser.Parse("Without an ending", scope .()).IgnoreError();
String content = """
t text goes here
- Text addendum
""";
List<Bofa> output = new .();
List<int64> errors = new .();
BofaParser.Parse(content, output, errors);
DeleteContainerAndItems!(output);
delete errors;
}
}