143 lines
4.3 KiB
C#
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;
|
|
}
|
|
}
|