feat: Grammar Parser (#3)
Reviewed-on: https://git.bupt-hpc.cn/jackfiled/CanonSharp/pulls/3 Co-authored-by: jackfiled <xcrenchangjun@outlook.com> Co-committed-by: jackfiled <xcrenchangjun@outlook.com>
This commit is contained in:
10
CanonSharp.Pascal/SyntaxTree/AssignNode.cs
Normal file
10
CanonSharp.Pascal/SyntaxTree/AssignNode.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class AssignNode(VariableNode variable, SyntaxNodeBase expression) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.Assign;
|
||||
|
||||
public VariableNode Variable => variable;
|
||||
|
||||
public SyntaxNodeBase Expression => expression;
|
||||
}
|
33
CanonSharp.Pascal/SyntaxTree/BinaryOperatorNode.cs
Normal file
33
CanonSharp.Pascal/SyntaxTree/BinaryOperatorNode.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public enum BinaryOperatorType
|
||||
{
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
|
||||
// Pascal特有的整数除法关键词div
|
||||
IntegerDivide,
|
||||
Divide,
|
||||
Mod,
|
||||
And,
|
||||
Or,
|
||||
Equal,
|
||||
NotEqual,
|
||||
Greater,
|
||||
GreaterEqual,
|
||||
Less,
|
||||
LessEqual
|
||||
}
|
||||
|
||||
public sealed class BinaryOperatorNode(BinaryOperatorType operatorType, SyntaxNodeBase left, SyntaxNodeBase right)
|
||||
: SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.BinaryOperator;
|
||||
|
||||
public BinaryOperatorType OperatorType => operatorType;
|
||||
|
||||
public SyntaxNodeBase Left => left;
|
||||
|
||||
public SyntaxNodeBase Right => right;
|
||||
}
|
8
CanonSharp.Pascal/SyntaxTree/BlockNode.cs
Normal file
8
CanonSharp.Pascal/SyntaxTree/BlockNode.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class BlockNode(IEnumerable<SyntaxNodeBase> statements) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.Block;
|
||||
|
||||
public IList<SyntaxNodeBase> Statements => statements.ToList();
|
||||
}
|
8
CanonSharp.Pascal/SyntaxTree/BooleanValueNode.cs
Normal file
8
CanonSharp.Pascal/SyntaxTree/BooleanValueNode.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class BooleanValueNode(bool value) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.BooleanValue;
|
||||
|
||||
public bool Value => value;
|
||||
}
|
8
CanonSharp.Pascal/SyntaxTree/CharValueNode.cs
Normal file
8
CanonSharp.Pascal/SyntaxTree/CharValueNode.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class CharValueNode(char value) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.CharValue;
|
||||
|
||||
public char Value => value;
|
||||
}
|
12
CanonSharp.Pascal/SyntaxTree/ConstantNode.cs
Normal file
12
CanonSharp.Pascal/SyntaxTree/ConstantNode.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using CanonSharp.Pascal.Scanner;
|
||||
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class ConstantNode(LexicalToken identifier, SyntaxNodeBase value) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.Constant;
|
||||
|
||||
public LexicalToken Identifier = identifier;
|
||||
|
||||
public SyntaxNodeBase Value = value;
|
||||
}
|
8
CanonSharp.Pascal/SyntaxTree/FloatValueNode.cs
Normal file
8
CanonSharp.Pascal/SyntaxTree/FloatValueNode.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class FloatValueNode(double value) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.FloatValue;
|
||||
|
||||
public double Value => value;
|
||||
}
|
20
CanonSharp.Pascal/SyntaxTree/ForNode.cs
Normal file
20
CanonSharp.Pascal/SyntaxTree/ForNode.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using CanonSharp.Pascal.Scanner;
|
||||
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class ForNode(
|
||||
LexicalToken identifier,
|
||||
SyntaxNodeBase leftCondition,
|
||||
SyntaxNodeBase rightCondition,
|
||||
SyntaxNodeBase statement) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.For;
|
||||
|
||||
public LexicalToken Identifier => identifier;
|
||||
|
||||
public SyntaxNodeBase LeftCondition => leftCondition;
|
||||
|
||||
public SyntaxNodeBase RightCondition => rightCondition;
|
||||
|
||||
public SyntaxNodeBase Statement => statement;
|
||||
}
|
26
CanonSharp.Pascal/SyntaxTree/IfNode.cs
Normal file
26
CanonSharp.Pascal/SyntaxTree/IfNode.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class IfNode : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.If;
|
||||
|
||||
public SyntaxNodeBase Condition { get; }
|
||||
|
||||
public SyntaxNodeBase Statement { get; }
|
||||
|
||||
public SyntaxNodeBase? ElseStatement { get; }
|
||||
|
||||
public IfNode(SyntaxNodeBase condition, SyntaxNodeBase statement)
|
||||
{
|
||||
Condition = condition;
|
||||
Statement = statement;
|
||||
ElseStatement = null;
|
||||
}
|
||||
|
||||
public IfNode(SyntaxNodeBase condition, SyntaxNodeBase statement, SyntaxNodeBase elseStatement)
|
||||
{
|
||||
Condition = condition;
|
||||
Statement = statement;
|
||||
ElseStatement = elseStatement;
|
||||
}
|
||||
}
|
8
CanonSharp.Pascal/SyntaxTree/IntegerValueNode.cs
Normal file
8
CanonSharp.Pascal/SyntaxTree/IntegerValueNode.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class IntegerValueNode(int value) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.IntegerValue;
|
||||
|
||||
public int Value => value;
|
||||
}
|
14
CanonSharp.Pascal/SyntaxTree/Parameter.cs
Normal file
14
CanonSharp.Pascal/SyntaxTree/Parameter.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using CanonSharp.Pascal.Scanner;
|
||||
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class Parameter(bool isReference, LexicalToken identifier, SyntaxNodeBase typeNode) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.Parameter;
|
||||
|
||||
public bool IsReference => isReference;
|
||||
|
||||
public LexicalToken Identifier => identifier;
|
||||
|
||||
public SyntaxNodeBase TypeNode => typeNode;
|
||||
}
|
18
CanonSharp.Pascal/SyntaxTree/ProcedureCallNode.cs
Normal file
18
CanonSharp.Pascal/SyntaxTree/ProcedureCallNode.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using CanonSharp.Pascal.Scanner;
|
||||
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class ProcedureCallNode : SyntaxNodeBase
|
||||
{
|
||||
public ProcedureCallNode(LexicalToken identifier, IEnumerable<SyntaxNodeBase> parameters)
|
||||
{
|
||||
Identifier = identifier;
|
||||
Parameters.AddRange(parameters);
|
||||
}
|
||||
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.ProcedureCall;
|
||||
|
||||
public LexicalToken Identifier { get; }
|
||||
|
||||
public List<SyntaxNodeBase> Parameters { get; } = [];
|
||||
}
|
10
CanonSharp.Pascal/SyntaxTree/Program.cs
Normal file
10
CanonSharp.Pascal/SyntaxTree/Program.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class Program(ProgramHead head, ProgramBody body) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.Program;
|
||||
|
||||
public ProgramHead Head => head;
|
||||
|
||||
public ProgramBody Body => body;
|
||||
}
|
17
CanonSharp.Pascal/SyntaxTree/ProgramBody.cs
Normal file
17
CanonSharp.Pascal/SyntaxTree/ProgramBody.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class ProgramBody(BlockNode constantDeclarations, BlockNode variableDeclarations,
|
||||
BlockNode subprograms,
|
||||
BlockNode mainBlock)
|
||||
: SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.ProgramBody;
|
||||
|
||||
public BlockNode ConstantDeclarations => constantDeclarations;
|
||||
|
||||
public BlockNode VariableDeclarations => variableDeclarations;
|
||||
|
||||
public BlockNode Subprograms => subprograms;
|
||||
|
||||
public BlockNode MainBlock => mainBlock;
|
||||
}
|
10
CanonSharp.Pascal/SyntaxTree/ProgramHead.cs
Normal file
10
CanonSharp.Pascal/SyntaxTree/ProgramHead.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using CanonSharp.Pascal.Scanner;
|
||||
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class ProgramHead(LexicalToken programName) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.ProgramHead;
|
||||
|
||||
public LexicalToken ProgramName => programName;
|
||||
}
|
10
CanonSharp.Pascal/SyntaxTree/Subprogram.cs
Normal file
10
CanonSharp.Pascal/SyntaxTree/Subprogram.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class Subprogram(SubprogramHead subprogramHead, SubprogramBody subprogramBody) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.SubProgram;
|
||||
|
||||
public SubprogramHead Head => subprogramHead;
|
||||
|
||||
public SubprogramBody Body => subprogramBody;
|
||||
}
|
12
CanonSharp.Pascal/SyntaxTree/SubprogramBody.cs
Normal file
12
CanonSharp.Pascal/SyntaxTree/SubprogramBody.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class SubprogramBody(BlockNode constDeclarations, BlockNode variableDeclarations, BlockNode mainBlock) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.SubprogramBody;
|
||||
|
||||
public BlockNode ConstDeclarations => constDeclarations;
|
||||
|
||||
public BlockNode VariableDeclarations => variableDeclarations;
|
||||
|
||||
public BlockNode MainBlock => mainBlock;
|
||||
}
|
28
CanonSharp.Pascal/SyntaxTree/SubprogramHead.cs
Normal file
28
CanonSharp.Pascal/SyntaxTree/SubprogramHead.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using CanonSharp.Pascal.Scanner;
|
||||
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class SubprogramHead : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.SubprogramHead;
|
||||
|
||||
public LexicalToken Identifier { get; }
|
||||
|
||||
public List<Parameter> Parameters { get; } = [];
|
||||
|
||||
public SyntaxNodeBase? TypeToken { get; }
|
||||
|
||||
public SubprogramHead(LexicalToken identifier, IEnumerable<Parameter> parameters)
|
||||
{
|
||||
Identifier = identifier;
|
||||
Parameters.AddRange(parameters);
|
||||
TypeToken = null;
|
||||
}
|
||||
|
||||
public SubprogramHead(LexicalToken identifier, IEnumerable<Parameter> parameters, SyntaxNodeBase typeToken) : this(
|
||||
identifier, parameters)
|
||||
{
|
||||
TypeToken = typeToken;
|
||||
}
|
||||
|
||||
}
|
43
CanonSharp.Pascal/SyntaxTree/SyntaxNodeBase.cs
Normal file
43
CanonSharp.Pascal/SyntaxTree/SyntaxNodeBase.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public enum SyntaxNodeType
|
||||
{
|
||||
BinaryOperator,
|
||||
UnaryOperator,
|
||||
IntegerValue,
|
||||
FloatValue,
|
||||
BooleanValue,
|
||||
CharValue,
|
||||
Variable,
|
||||
Type,
|
||||
Assign,
|
||||
Block,
|
||||
Constant,
|
||||
VariableDeclaration,
|
||||
If,
|
||||
While,
|
||||
For,
|
||||
ProcedureCall,
|
||||
Parameter,
|
||||
SubprogramHead,
|
||||
SubprogramBody,
|
||||
SubProgram,
|
||||
ProgramBody,
|
||||
ProgramHead,
|
||||
Program
|
||||
}
|
||||
|
||||
public abstract class SyntaxNodeBase
|
||||
{
|
||||
public abstract SyntaxNodeType NodeType { get; }
|
||||
|
||||
public T Convert<T>() where T : SyntaxNodeBase
|
||||
{
|
||||
if (this is not T result)
|
||||
{
|
||||
throw new InvalidCastException($"Can't convert {NodeType} to target node.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
24
CanonSharp.Pascal/SyntaxTree/TypeNode.cs
Normal file
24
CanonSharp.Pascal/SyntaxTree/TypeNode.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using CanonSharp.Pascal.Scanner;
|
||||
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public record struct ArrayRange(int Left, int Right);
|
||||
|
||||
public sealed class TypeNode : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.Type;
|
||||
|
||||
public LexicalToken TypeToken { get; }
|
||||
|
||||
public List<ArrayRange> ArrayRanges { get; } = [];
|
||||
|
||||
public TypeNode(LexicalToken typeToken)
|
||||
{
|
||||
TypeToken = typeToken;
|
||||
}
|
||||
|
||||
public TypeNode(LexicalToken typeToken, IEnumerable<ArrayRange> arrayRanges) : this(typeToken)
|
||||
{
|
||||
ArrayRanges.AddRange(arrayRanges);
|
||||
}
|
||||
}
|
17
CanonSharp.Pascal/SyntaxTree/UnaryOperatorNode.cs
Normal file
17
CanonSharp.Pascal/SyntaxTree/UnaryOperatorNode.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public enum UnaryOperatorType
|
||||
{
|
||||
Plus,
|
||||
Minus,
|
||||
Not
|
||||
}
|
||||
|
||||
public sealed class UnaryOperatorNode(UnaryOperatorType operatorType, SyntaxNodeBase node) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.UnaryOperator;
|
||||
|
||||
public UnaryOperatorType OperatorType => operatorType;
|
||||
|
||||
public SyntaxNodeBase Node => node;
|
||||
}
|
12
CanonSharp.Pascal/SyntaxTree/VariableDeclarationNode.cs
Normal file
12
CanonSharp.Pascal/SyntaxTree/VariableDeclarationNode.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using CanonSharp.Pascal.Scanner;
|
||||
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class VariableDeclarationNode(IEnumerable<LexicalToken> identifiers, TypeNode typeNode) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.VariableDeclaration;
|
||||
|
||||
public IList<LexicalToken> Identifiers => identifiers.ToList();
|
||||
|
||||
public TypeNode TypeNode => typeNode;
|
||||
}
|
23
CanonSharp.Pascal/SyntaxTree/VariableNode.cs
Normal file
23
CanonSharp.Pascal/SyntaxTree/VariableNode.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using CanonSharp.Pascal.Scanner;
|
||||
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class VariableNode : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.Variable;
|
||||
|
||||
public LexicalToken Identifier { get; }
|
||||
|
||||
public List<SyntaxNodeBase> Indexers { get; } = [];
|
||||
|
||||
public VariableNode(LexicalToken identifier)
|
||||
{
|
||||
Identifier = identifier;
|
||||
}
|
||||
|
||||
public VariableNode(LexicalToken identifier, IEnumerable<SyntaxNodeBase> expressions)
|
||||
{
|
||||
Identifier = identifier;
|
||||
Indexers.AddRange(expressions);
|
||||
}
|
||||
}
|
10
CanonSharp.Pascal/SyntaxTree/WhileNode.cs
Normal file
10
CanonSharp.Pascal/SyntaxTree/WhileNode.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace CanonSharp.Pascal.SyntaxTree;
|
||||
|
||||
public sealed class WhileNode(SyntaxNodeBase condition, SyntaxNodeBase statement) : SyntaxNodeBase
|
||||
{
|
||||
public override SyntaxNodeType NodeType => SyntaxNodeType.While;
|
||||
|
||||
public SyntaxNodeBase Condition => condition;
|
||||
|
||||
public SyntaxNodeBase Statement => statement;
|
||||
}
|
Reference in New Issue
Block a user