add: Terminator and Expression

This commit is contained in:
jackfiled 2024-03-09 23:57:43 +08:00
parent d6a6468a88
commit 8d30b1626b
3 changed files with 252 additions and 0 deletions

View File

@ -0,0 +1,37 @@
namespace Canon.Core.Enums;
public enum NonTerminatorType
{
ProgramStruct,
ProgramHead,
ProgramBody,
IdentifierList,
ConstDeclarations,
VarDeclarations,
SubprogramDeclarations,
CompoundStatement,
ConstDeclaration,
ConstValue,
VarDeclaration,
Type,
BasicType,
Range,
Subprogram,
SubprogramHead,
SubprogramBody,
FormalParameter,
ParameterList,
Parameter,
VarParameter,
ValueParameter,
StatementList,
Statement,
Variable,
Expression,
ProcedureCall,
ElsePart,
ExpressionList,
SimpleExpression,
Term,
Factor
}

View File

@ -0,0 +1,78 @@
namespace Canon.Core.GrammarParser;
/// <summary>
/// An expression in the LR, like 'program_struct -> ~program_head ; program_body.'
/// The '~' is the shift position now.
/// </summary>
public class Expression : IEquatable<Expression>
{
public required NonTerminator Left { get; init; }
public required Terminator LookAhead { get; init; }
public required List<TerminatorBase> Right { get; init; }
public int Pos { get; set; }
public bool Equals(Expression? other)
{
if (other is null)
{
return false;
}
if (Right.Count != other.Right.Count)
{
return false;
}
for (int i = 0; i < Right.Count; i++)
{
if (Right[i].IsTerminated != other.Right[i].IsTerminated)
{
return false;
}
if (!Right[i].Equals(other.Right[i]))
{
return false;
}
}
return Left == other.Left
&& LookAhead == other.LookAhead;
}
public override bool Equals(object? obj)
{
if (obj is not Expression other)
{
return false;
}
return Equals(other);
}
public override int GetHashCode()
{
int hash = Left.GetHashCode();
hash ^= LookAhead.GetHashCode();
foreach (TerminatorBase terminator in Right)
{
hash ^= terminator.GetHashCode();
}
return hash;
}
public static bool operator ==(Expression a, Expression b)
{
return a.Equals(b);
}
public static bool operator !=(Expression a, Expression b)
{
return !a.Equals(b);
}
}

View File

@ -0,0 +1,137 @@
using Canon.Core.Enums;
namespace Canon.Core.GrammarParser;
public abstract class TerminatorBase
{
public abstract bool IsTerminated { get; }
}
/// <summary>
/// A terminator in grammar and it always represents a semantic token.
/// </summary>
public class Terminator : TerminatorBase, IEquatable<Terminator>
{
public override bool IsTerminated => true;
private readonly bool _isKeyword;
private readonly KeywordType _keywordType;
private readonly DelimiterType _delimiterType;
public Terminator(KeywordType keywordType)
{
_isKeyword = true;
_keywordType = keywordType;
}
public Terminator(DelimiterType delimiterType)
{
_isKeyword = false;
_delimiterType = delimiterType;
}
public override int GetHashCode()
{
if (_isKeyword)
{
return _keywordType.GetHashCode();
}
else
{
return _delimiterType.GetHashCode();
}
}
public bool Equals(Terminator? other)
{
if (other is null)
{
return false;
}
if (_isKeyword != other._isKeyword)
{
return false;
}
if (_isKeyword)
{
return _keywordType == other._keywordType;
}
else
{
return _delimiterType == other._delimiterType;
}
}
public override bool Equals(object? obj)
{
if (obj is not Terminator other)
{
return false;
}
return Equals(other);
}
public static bool operator ==(Terminator a, Terminator b)
{
return a.Equals(b);
}
public static bool operator !=(Terminator a, Terminator b)
{
return !a.Equals(b);
}
}
/// <summary>
/// A non-terminator in grammar like the 'ProgramStruct'.
/// </summary>
public class NonTerminator : TerminatorBase, IEquatable<NonTerminator>
{
public override bool IsTerminated => false;
private readonly NonTerminatorType _type;
public NonTerminator(NonTerminatorType type)
{
_type = type;
}
public override int GetHashCode()
{
return _type.GetHashCode();
}
public bool Equals(NonTerminator? other)
{
if (other is null)
{
return false;
}
return _type == other._type;
}
public override bool Equals(object? obj)
{
if (obj is not NonTerminator other)
{
return false;
}
return Equals(other);
}
public static bool operator ==(NonTerminator a, NonTerminator b)
{
return a.Equals(b);
}
public static bool operator !=(NonTerminator a, NonTerminator b)
{
return !a.Equals(b);
}
}