tbf/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Searching/SearchOrderParser.cs

87 lines
3.2 KiB
C#

using System;
using System.Text.RegularExpressions;
using TBF.Rig.Input.DataStorage.UniDataStorageWriter.Searching;
namespace TBF.Rig.Input.DataStorage.UniDataStorageWriter
{
/// <summary>
/// Parses SQL-like QueryTemplate expressions.
/// Supported syntax:
/// SELECT [ReturnColumn] WHERE [MatchColumn] = QUERYPARAM
/// SELECT COLUMN(1) WHERE COLUMN(0) = QUERYPARAM
/// Mixed forms are also supported.
/// </summary>
public static class SearchOrderParser
{
private static readonly Regex FullPattern = new Regex(
@"^\s*SELECT\s+(?<select>\[[^\]]+\]|COLUMN\(\d+\))\s+WHERE\s+(?<where>\[[^\]]+\]|COLUMN\(\d+\))\s*=\s*QUERYPARAM\s*$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex NamedColumnPattern = new Regex(
@"^\[(?<name>[^\]]+)\]$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex IndexedColumnPattern = new Regex(
@"^COLUMN\((?<index>\d+)\)$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
/// <summary>
/// Parses QueryTemplate text into structured definition.
/// Throws if syntax is invalid.
/// </summary>
public static SearchOrderDefinition Parse(string searchOrder)
{
if (string.IsNullOrWhiteSpace(searchOrder))
throw new InvalidOperationException("QueryTemplate is empty.");
Match match = FullPattern.Match(searchOrder);
if (!match.Success)
{
throw new InvalidOperationException(
"Invalid QueryTemplate syntax. Expected: SELECT [ReturnColumn] WHERE [MatchColumn] = QUERYPARAM");
}
string selectToken = match.Groups["select"].Value;
string whereToken = match.Groups["where"].Value;
return new SearchOrderDefinition
{
SelectColumn = ParseColumnReference(selectToken),
WhereColumn = ParseColumnReference(whereToken)
};
}
/// <summary>
/// Parses one column reference token:
/// [ColumnName] or COLUMN(number)
/// </summary>
private static ColumnReference ParseColumnReference(string token)
{
if (string.IsNullOrWhiteSpace(token))
throw new InvalidOperationException("Column reference token is empty.");
Match nameMatch = NamedColumnPattern.Match(token);
if (nameMatch.Success)
{
return new ColumnReference
{
Name = nameMatch.Groups["name"].Value.Trim(),
Index = null
};
}
Match indexMatch = IndexedColumnPattern.Match(token);
if (indexMatch.Success)
{
return new ColumnReference
{
Name = null,
Index = int.Parse(indexMatch.Groups["index"].Value)
};
}
throw new InvalidOperationException(
"Invalid column reference '" + token + "'. Use [ColumnName] or COLUMN(number).");
}
}
}