Files
TextParser/TextParser/Schema/FragmentSchemaBuilder.cs

143 lines
4.3 KiB
C#

namespace Parsing.Schema;
using Parsing.Schema.BuildingBlocks;
using System.Text.RegularExpressions;
public class FragmentSchemaBuilder : RepetitionSchemaBuilder<FragmentSchemaBuilder, FragmentSchema, FragmentSchemaContext>, ISchemaBuilder<FragmentSchema, FragmentSchemaContext>
{
protected string fragmentRegex = @"";
private List<string> namedGroups = new List<string>();
private List<string> namedLiterals = new List<string>();
public FragmentSchemaBuilder()
{
}
public FragmentSchemaBuilder StartOptions()
{
this.fragmentRegex += "((";
return this;
}
public FragmentSchemaBuilder EndOptions()
{
this.fragmentRegex += "))";
return this;
}
public FragmentSchemaBuilder Option()
{
// if we just started an options group there is no need to add an option separator
if (!this.fragmentRegex.EndsWith("(") || this.fragmentRegex.EndsWith("\\("))
{
this.fragmentRegex += ")|(";
}
return this;
}
public FragmentSchemaBuilder Expect(InputType type, string name = "")
{
string groupNamePrefix = "";
if (!string.IsNullOrEmpty(name))
{
groupNamePrefix = "?<" + name + ">";
namedGroups.Add(name);
}
switch (type)
{
case InputType.String:
this.fragmentRegex += "(" + groupNamePrefix + "\\w+)";
break;
case InputType.Integer:
this.fragmentRegex += "(" + groupNamePrefix + "\\d+)";
break;
default:
throw new Exception("Unrecognized InputType");
}
return this;
}
public FragmentSchemaBuilder Expect(string literal, string name = "")
{
string groupNamePrefix = "";
if (!string.IsNullOrEmpty(name))
{
groupNamePrefix = "?<" + name + ">";
namedLiterals.Add(name);
}
this.fragmentRegex += "(" + groupNamePrefix + Regex.Escape(literal) + ")";
return this;
}
public FragmentSchemaBuilder Repeat(int repetitionCount)
{
// add another layer of parsing
var newSchemaBuilder = this.GetNewRepetitionSchemaBuilder(this);
newSchemaBuilder.NumRepetition = repetitionCount;
newSchemaBuilder.RepetitionType = RepetitionType.FixedRepetition;
return newSchemaBuilder;
}
public FragmentSchemaBuilder Repeat()
{
// add another layer of parsing
var newSchemaBuilder = this.GetNewRepetitionSchemaBuilder(this);
newSchemaBuilder.RepetitionType = RepetitionType.GreedyRepetition;
return newSchemaBuilder;
}
public FragmentSchemaBuilder Repeat(RepetitionType repetitionType)
{
// add another layer of parsing
var newSchemaBuilder = this.GetNewRepetitionSchemaBuilder(this);
newSchemaBuilder.RepetitionType = repetitionType;
return newSchemaBuilder;
}
public FragmentSchemaBuilder EndRepetition()
{
// return back to upper layer of parsing
var currentBuilder = this as FragmentSchemaBuilder;
if (currentBuilder == null)
{
throw new Exception("Invalid repetition definitions!");
}
var oldSchemaBuilder = currentBuilder.UpperLayerBuilder;
if (oldSchemaBuilder == null)
{
throw new Exception("Something went terribly wrong!");
}
var currentRegex = "(" + currentBuilder.fragmentRegex + ")";
switch (currentBuilder.RepetitionType)
{
case RepetitionType.FixedRepetition:
currentRegex += "{" + this.NumRepetition.ToString() + "}";
break;
case RepetitionType.GreedyRepetition:
currentRegex += "*";
break;
case RepetitionType.NonZeroRepetition:
case RepetitionType.NonZeroRepetition | RepetitionType.GreedyRepetition:
currentRegex += "+";
break;
default:
throw new Exception("Unrecognized RepetitionType");
}
oldSchemaBuilder.fragmentRegex += "(" + currentRegex + ")";
return oldSchemaBuilder;
}
public FragmentSchema Build()
{
var schema = new FragmentSchema(this.fragmentRegex, this.namedGroups, this.namedLiterals);
return schema;
}
}