namespace CanonSharp.Common.LexicalAnalyzer;
public abstract class RegularExpression
{
public abstract NondeterministicFiniteAutomation Convert2Nfa();
///
/// 匹配空字符串
///
public static RegularExpression Empty => new EmptyExpression();
///
/// 匹配单个字符
/// c
///
///
///
public static RegularExpression Single(char c) => new SymbolExpression(c);
///
/// left|right
///
///
///
///
public static RegularExpression Alternate(RegularExpression left, RegularExpression right) =>
new AlternationExpression(left, right);
///
/// left-right
///
///
///
///
public static RegularExpression Concatenate(RegularExpression first, RegularExpression second) =>
new ConcatenationExpression(first, second);
///
/// inner*
///
///
///
public static RegularExpression Kleene(RegularExpression inner) => new KleeneExpression(inner);
///
/// value
///
///
///
public static RegularExpression String(string value) => new StringExpression(value);
public static RegularExpression CharSetOf(string value) => new CharSetExpression(value.ToCharArray());
public static RegularExpression CharSetOf(Func predicate)
=> new CharSetExpression(Iterate(char.MinValue, char.MaxValue).Where(predicate).ToArray());
///
/// [a-b]
///
///
///
///
public static RegularExpression Range(char a, char b) => new CharSetExpression(Iterate(a, b).ToArray());
private static IEnumerable Iterate(char a, char b)
{
for (char c = a; c <= b; c++)
{
if (c == char.MaxValue)
{
yield break;
}
yield return c;
}
}
}
public class EmptyExpression : RegularExpression
{
public override NondeterministicFiniteAutomation Convert2Nfa()
{
NondeterministicState final = new();
NondeterministicState start = new();
start.AddTransaction(EmptyChar.Empty, final);
return new NondeterministicFiniteAutomation(start, [final]);
}
}
public class SymbolExpression(char symbol) : RegularExpression
{
public char Symbol { get; } = symbol;
public override NondeterministicFiniteAutomation Convert2Nfa()
{
NondeterministicState final = new();
NondeterministicState start = new();
start.AddTransaction(new EmptyChar(Symbol), final);
return new NondeterministicFiniteAutomation(start, [final]);
}
}
public class AlternationExpression(RegularExpression left, RegularExpression right) : RegularExpression
{
public RegularExpression Left { get; } = left;
public RegularExpression Right { get; } = right;
public override NondeterministicFiniteAutomation Convert2Nfa()
{
NondeterministicFiniteAutomation left = Left.Convert2Nfa();
NondeterministicFiniteAutomation right = Right.Convert2Nfa();
NondeterministicState final = new();
foreach (NondeterministicState state in left.FinalStates.Concat(right.FinalStates))
{
state.AddTransaction(EmptyChar.Empty, final);
}
NondeterministicState start = new();
start.AddTransaction(EmptyChar.Empty, left.Start);
start.AddTransaction(EmptyChar.Empty, right.Start);
return new NondeterministicFiniteAutomation(start, [final]);
}
}
public class ConcatenationExpression(RegularExpression first, RegularExpression second) : RegularExpression
{
public RegularExpression First { get; } = first;
public RegularExpression Second { get; } = second;
public override NondeterministicFiniteAutomation Convert2Nfa()
{
NondeterministicFiniteAutomation first = First.Convert2Nfa();
NondeterministicFiniteAutomation second = Second.Convert2Nfa();
foreach (NondeterministicState state in first.FinalStates)
{
state.AddTransaction(EmptyChar.Empty, second.Start);
}
return new NondeterministicFiniteAutomation(first.Start, second.FinalStates);
}
}
public class KleeneExpression(RegularExpression inner) : RegularExpression
{
public RegularExpression Inner { get; } = inner;
public override NondeterministicFiniteAutomation Convert2Nfa()
{
NondeterministicFiniteAutomation inner = Inner.Convert2Nfa();
NondeterministicState final = new();
final.AddTransaction(EmptyChar.Empty, inner.Start);
foreach (NondeterministicState state in inner.FinalStates)
{
state.AddTransaction(EmptyChar.Empty, final);
}
return new NondeterministicFiniteAutomation(final, [final]);
}
}
public class CharSetExpression : RegularExpression
{
public char[] Set { get; }
public CharSetExpression(Span set)
{
if (set.Length == 0)
{
throw new InvalidOperationException();
}
Set = set.ToArray();
}
public override NondeterministicFiniteAutomation Convert2Nfa()
{
NondeterministicState start = new();
NondeterministicState final = new();
foreach (char c in Set)
{
start.AddTransaction(new EmptyChar(c), final);
}
return new NondeterministicFiniteAutomation(start, [final]);
}
}
public class StringExpression : RegularExpression
{
public string Word { get; }
public StringExpression(string word)
{
if (string.IsNullOrEmpty(word))
{
throw new InvalidOperationException();
}
Word = word;
}
public override NondeterministicFiniteAutomation Convert2Nfa()
{
NondeterministicState start = new();
NondeterministicState final = Word.Aggregate(start, (state, c) =>
{
NondeterministicState next = new();
state.AddTransaction(new EmptyChar(c), next);
return next;
});
return new NondeterministicFiniteAutomation(start, [final]);
}
}