regex interpreter now can build partial correct AST (i forget groups), but in bad shape. building an optimizer.

This commit is contained in:
Youmu Liu
2026-02-06 17:07:03 +08:00
parent 1bfb8b67c4
commit 3a441b270c
13 changed files with 236 additions and 31 deletions
@@ -53,13 +53,18 @@ namespace StgSharp.RegularAnalysis.TextRegex
{
if ((token.Flag & RegexElementLabel.SEQUENCE) != 0)
{
Console.WriteLine($"Unit {token.Value}");
// char or charset
_stack.PushOperand(new RegexAstNode(token));
} else if ((token.Flag & RegexElementLabel.GROUP_BEGIN) != 0)
{
Console.WriteLine($"Group begin {token.Value}");
_stack.IncreaseDepth(0);
} else if ((token.Flag & RegexElementLabel.GROUP_END) != 0)
{
Console.WriteLine($"Group end {token.Value}");
// TODO: close all nodes here
while (_stack.TryPopOperator(out RegexAstNode? op))
{
@@ -69,14 +74,61 @@ namespace StgSharp.RegularAnalysis.TextRegex
throw new InvalidOperationException();
}
_stack.DecreaseDepth();
} else if ((token.Flag & RegexElementLabel.OPERATOR) != 0) { }
} else if ((token.Flag & RegexElementLabel.OPERATOR) != 0)
{
Console.WriteLine($"Operator {token.Value} with flag {token.Flag}");
if (_stack.OperatorInDepthCount == 0)
{
// the first operator in stack
_stack.PushOperator(new RegexAstNode(token));
} else
{
// process operator by precedence
while (_stack.TryPeekOperator(out RegexAstNode topOp))
{
(bool Valid, int Value) cmp = RegexAstNode.ComparePrecedence(token.Flag, topOp.Source.Flag);
if (!cmp.Valid) {
throw new InvalidOperationException("Operators with same precedence are not supported.");
}
if (cmp.Value < 0)
{
_stack.PopOperator();
ProcessOperator(topOp);
continue;
} else
{
break;
}
}
_stack.PushOperator(new RegexAstNode(token));
}
}
}
Console.WriteLine(1);
if (_stack.Depth == 1)
{
if (_stack.OperandInDepthCount != 1 || _stack.OperatorInDepthCount != 0)
{
while (_stack.TryPopOperator(out RegexAstNode? op)) {
ProcessOperator(op);
}
}
if (_stack.OperandInDepthCount == 1 && _stack.OperatorInDepthCount == 0)
{
_tree.Root = _stack.PopOperand();
return _tree;
}
throw new InvalidOperationException("Invalid regular expression syntax.");
}
throw new InvalidOperationException("Invalid regular expression syntax.");
}
private void ProcessOperator(
RegexAstNode op
)
{
Console.WriteLine($"Processing a {op.Source.Flag} operator");
if (op.EqualityTypeConvert == RegexElementLabel.CONCAT)
{
if (_stack.TryPopOperand(out RegexAstNode? _1) &&
@@ -85,11 +137,15 @@ namespace StgSharp.RegularAnalysis.TextRegex
if (RegexAstNode.TryMergeUnit(_2, _1, out RegexAstNode? _3))
{
_stack.PushOperand(_3);
_tree.AddNode(_3);
} else
{
op.Left = _2;
op.Right = _1;
_stack.PushOperand(op);
_tree.AddNode(op);
_tree.AddNode(_1);
_tree.AddNode(_2);
}
} else
{
@@ -101,6 +157,8 @@ namespace StgSharp.RegularAnalysis.TextRegex
{
op.Left = _1;
_stack.PushOperand(op);
_tree.AddNode(_1);
_tree.AddNode(op);
} else
{
throw new InvalidOperationException("Insufficient operands for CONCAT operator.");
@@ -113,6 +171,9 @@ namespace StgSharp.RegularAnalysis.TextRegex
op.Left = _1;
op.Right = _2;
_stack.PushOperand(op);
_tree.AddNode(op);
_tree.AddNode(_1);
_tree.AddNode(_2);
} else
{
throw new InvalidOperationException("Insufficient operands for CONCAT operator.");