feat: 对输入的记号流进行分析 (#4)
添加了语法分析中各个重要状态类的`ToString`方法,方便调试 Reviewed-on: PostGuard/Canon#4
This commit is contained in:
@@ -78,6 +78,26 @@ public class Expression : IEquatable<Expression>
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = $"{Left} -> ";
|
||||
|
||||
for (int i = 0; i < Right.Count; i++)
|
||||
{
|
||||
if (i == Pos)
|
||||
{
|
||||
result += '~';
|
||||
}
|
||||
|
||||
result += ' ';
|
||||
result += Right[i].ToString();
|
||||
}
|
||||
|
||||
result += $", {LookAhead}";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool operator ==(Expression a, Expression b)
|
||||
{
|
||||
return a.Equals(b);
|
||||
|
@@ -1,8 +1,79 @@
|
||||
namespace Canon.Core.GrammarParser;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.GrammarParser;
|
||||
|
||||
public class Grammar
|
||||
{
|
||||
public required NonTerminator Begin { get; init; }
|
||||
|
||||
public required LrState BeginState { get; init; }
|
||||
|
||||
public void Analyse(IEnumerable<SemanticToken> tokens)
|
||||
{
|
||||
Stack<LrState> stack = [];
|
||||
stack.Push(BeginState);
|
||||
|
||||
using IEnumerator<SemanticToken> enumerator = tokens.GetEnumerator();
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
throw new InvalidOperationException("Input token list is empty");
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
LrState top = stack.Peek();
|
||||
|
||||
// 尝试进行移进
|
||||
bool acceptFlag = false, reduceFlag = false;
|
||||
foreach (Expression e in top.Expressions)
|
||||
{
|
||||
if (e.Pos == e.Right.Count && e.LookAhead == enumerator.Current)
|
||||
{
|
||||
if (e.Left == Begin)
|
||||
{
|
||||
acceptFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
reduceFlag = true;
|
||||
|
||||
for (int i = 0; i < e.Right.Count; i++)
|
||||
{
|
||||
stack.Pop();
|
||||
}
|
||||
|
||||
stack.Push(stack.Peek().Transformer[e.Left]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (acceptFlag)
|
||||
{
|
||||
// 接受文法 退出循环
|
||||
break;
|
||||
}
|
||||
|
||||
if (reduceFlag)
|
||||
{
|
||||
// 归约
|
||||
continue;
|
||||
}
|
||||
|
||||
// 尝试进行移进
|
||||
if (top.Transformer.TryGetValue(enumerator.Current, out LrState? next))
|
||||
{
|
||||
stack.Push(next);
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Run out of token but not accept");
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Failed to analyse input grammar");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
namespace Canon.Core.GrammarParser;
|
||||
using System.Text;
|
||||
|
||||
namespace Canon.Core.GrammarParser;
|
||||
|
||||
/// <summary>
|
||||
/// LR语法中的一个项目集规范族
|
||||
@@ -76,6 +78,18 @@ public class LrState : IEquatable<LrState>
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder builder = new();
|
||||
|
||||
foreach (Expression e in Expressions)
|
||||
{
|
||||
builder.Append(e).Append('\n');
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public static bool operator ==(LrState a, LrState b)
|
||||
{
|
||||
return a.Equals(b);
|
||||
|
@@ -66,7 +66,7 @@ public class Terminator : TerminatorBase, IEquatable<Terminator>
|
||||
/// <summary>
|
||||
/// 栈底的终结符
|
||||
/// </summary>
|
||||
public static Terminator EndTerminator => new(KeywordType.End);
|
||||
public static Terminator EndTerminator => new(SemanticTokenType.End);
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
@@ -85,6 +85,21 @@ public class Terminator : TerminatorBase, IEquatable<Terminator>
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
switch (_terminatorType)
|
||||
{
|
||||
case SemanticTokenType.Keyword:
|
||||
return _keywordType.ToString();
|
||||
case SemanticTokenType.Operator:
|
||||
return _operatorType.ToString();
|
||||
case SemanticTokenType.Delimiter:
|
||||
return _delimiterType.ToString();
|
||||
default:
|
||||
return _keywordType.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Equals(Terminator? other)
|
||||
{
|
||||
if (other is null)
|
||||
@@ -190,6 +205,8 @@ public class NonTerminator : TerminatorBase, IEquatable<NonTerminator>
|
||||
return _type.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString() => _type.ToString();
|
||||
|
||||
public bool Equals(NonTerminator? other)
|
||||
{
|
||||
if (other is null)
|
||||
|
Reference in New Issue
Block a user