add: Terminator and Expression
This commit is contained in:
parent
d6a6468a88
commit
8d30b1626b
37
Canon.Core/Enums/GrammarEnums.cs
Normal file
37
Canon.Core/Enums/GrammarEnums.cs
Normal 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
|
||||||
|
}
|
78
Canon.Core/GrammarParser/Expression.cs
Normal file
78
Canon.Core/GrammarParser/Expression.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
137
Canon.Core/GrammarParser/Terminator.cs
Normal file
137
Canon.Core/GrammarParser/Terminator.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user