feat:完成语法树结点的类型检查 (#59)
Co-authored-by: jackfiled <xcrenchangjun@outlook.com> Reviewed-on: PostGuard/Canon#59 Co-authored-by: ichirinko <1621543655@qq.com> Co-committed-by: ichirinko <1621543655@qq.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using Canon.Core.Abstractions;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
@@ -8,8 +7,6 @@ public class CompoundStatement : NonTerminatedSyntaxNode
|
||||
{
|
||||
public override NonTerminatorType Type => NonTerminatorType.CompoundStatement;
|
||||
|
||||
public IEnumerable<Statement> Statements => Children[1].Convert<StatementList>().Statements;
|
||||
|
||||
public override void PreVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PreVisit(this);
|
||||
@@ -24,16 +21,4 @@ public class CompoundStatement : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new CompoundStatement { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var statement in Statements.Reverse())
|
||||
{
|
||||
if (statement.Children.Count > 0)
|
||||
{
|
||||
statement.GenerateCCode(builder);
|
||||
builder.AddString(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,5 @@
|
||||
using Canon.Core.Abstractions;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -9,11 +7,6 @@ public class ConstDeclarations : NonTerminatedSyntaxNode
|
||||
{
|
||||
public override NonTerminatorType Type => NonTerminatorType.ConstDeclarations;
|
||||
|
||||
/// <summary>
|
||||
/// 声明的常量列表
|
||||
/// </summary>
|
||||
public IEnumerable<(IdentifierSemanticToken, ConstValue)> ConstValues => GetConstValues();
|
||||
|
||||
public override void PreVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PreVisit(this);
|
||||
@@ -28,62 +21,4 @@ public class ConstDeclarations : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new ConstDeclarations { Children = children };
|
||||
}
|
||||
|
||||
private IEnumerable<(IdentifierSemanticToken, ConstValue)> GetConstValues()
|
||||
{
|
||||
if (Children.Count == 0)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
ConstDeclaration declaration = Children[1].Convert<ConstDeclaration>();
|
||||
|
||||
while (true)
|
||||
{
|
||||
yield return declaration.ConstValue;
|
||||
|
||||
if (declaration.IsRecursive)
|
||||
{
|
||||
declaration = declaration.Children[0].Convert<ConstDeclaration>();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var pair in ConstValues.Reverse())
|
||||
{
|
||||
builder.AddString(" const");
|
||||
//获取常量类型
|
||||
var token = pair.Item2.Children[0].Convert<TerminatedSyntaxNode>().Token;
|
||||
var tokenType = token.TokenType;
|
||||
if (tokenType == SemanticTokenType.Number)
|
||||
{
|
||||
if (token.Convert<NumberSemanticToken>().NumberType == NumberType.Integer)
|
||||
{
|
||||
builder.AddString(" int ");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddString(" double ");
|
||||
}
|
||||
}
|
||||
else if (tokenType == SemanticTokenType.Character)
|
||||
{
|
||||
builder.AddString(" char ");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddString(" bool ");
|
||||
}
|
||||
|
||||
builder.AddString(pair.Item1.IdentifierName + " =");
|
||||
pair.Item2.GenerateCCode(builder);
|
||||
builder.AddString(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -47,7 +47,7 @@ public class Expression : NonTerminatedSyntaxNode
|
||||
|
||||
private PascalType? _expressionType;
|
||||
|
||||
public PascalType ExprssionType
|
||||
public PascalType ExpressionType
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@@ -3,6 +3,11 @@ using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
public class OnExpressionListEventArgs : EventArgs
|
||||
{
|
||||
public required ExpressionList ExpressionList { get; init; }
|
||||
}
|
||||
|
||||
public class ExpressionList : NonTerminatedSyntaxNode
|
||||
{
|
||||
public override NonTerminatorType Type => NonTerminatorType.ExpressionList;
|
||||
@@ -12,26 +17,40 @@ public class ExpressionList : NonTerminatedSyntaxNode
|
||||
/// </summary>
|
||||
public List<Expression> Expressions { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 当前ExpressionList中的Expression定义
|
||||
/// </summary>
|
||||
public required Expression Expression { get; init; }
|
||||
|
||||
public override void PreVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PreVisit(this);
|
||||
RaiseEvent();
|
||||
}
|
||||
|
||||
public override void PostVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PostVisit(this);
|
||||
RaiseEvent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用ExpressionList产生式的时间
|
||||
/// </summary>
|
||||
public event EventHandler<OnExpressionListEventArgs>? OnExpressionList;
|
||||
|
||||
public static ExpressionList Create(List<SyntaxNodeBase> children)
|
||||
{
|
||||
ExpressionList result = new() { Children = children };
|
||||
ExpressionList result;
|
||||
|
||||
if (children.Count == 1)
|
||||
{
|
||||
result = new ExpressionList { Expression = children[0].Convert<Expression>(), Children = children };
|
||||
result.Expressions.Add(children[0].Convert<Expression>());
|
||||
}
|
||||
else if (children.Count == 3)
|
||||
else
|
||||
{
|
||||
result = new ExpressionList { Expression = children[2].Convert<Expression>(), Children = children };
|
||||
foreach (Expression expression in children[0].Convert<ExpressionList>().Expressions)
|
||||
{
|
||||
result.Expressions.Add(expression);
|
||||
@@ -42,4 +61,15 @@ public class ExpressionList : NonTerminatedSyntaxNode
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void RaiseEvent()
|
||||
{
|
||||
if (Children.Count == 3)
|
||||
{
|
||||
OnExpressionList?.Invoke(this,
|
||||
new OnExpressionListEventArgs { ExpressionList = Children[0].Convert<ExpressionList>() });
|
||||
}
|
||||
|
||||
OnExpressionList = null;
|
||||
}
|
||||
}
|
||||
|
@@ -3,15 +3,20 @@ using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
public class OnParameterGeneratorEventArgs : EventArgs
|
||||
public class OnIndexGeneratorEventArgs : EventArgs
|
||||
{
|
||||
public required ExpressionList Parameters { get; init; }
|
||||
public required ExpressionList IndexParameters { get; init; }
|
||||
}
|
||||
|
||||
public class IdentifierVarPart : NonTerminatedSyntaxNode
|
||||
{
|
||||
public override NonTerminatorType Type => NonTerminatorType.IdVarPart;
|
||||
|
||||
/// <summary>
|
||||
/// 数组索引的个数
|
||||
/// </summary>
|
||||
public int IndexCount { get; set; }
|
||||
|
||||
public override void PreVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PreVisit(this);
|
||||
@@ -24,7 +29,10 @@ public class IdentifierVarPart : NonTerminatedSyntaxNode
|
||||
RaiseEvent();
|
||||
}
|
||||
|
||||
public event EventHandler<OnParameterGeneratorEventArgs>? OnParameterGenerator;
|
||||
/// <summary>
|
||||
/// 使用了索引产生式的事件
|
||||
/// </summary>
|
||||
public event EventHandler<OnIndexGeneratorEventArgs>? OnIndexGenerator;
|
||||
|
||||
public static IdentifierVarPart Create(List<SyntaxNodeBase> children)
|
||||
{
|
||||
@@ -35,12 +43,12 @@ public class IdentifierVarPart : NonTerminatedSyntaxNode
|
||||
{
|
||||
if (Children.Count == 3)
|
||||
{
|
||||
OnParameterGenerator?.Invoke(this, new OnParameterGeneratorEventArgs
|
||||
OnIndexGenerator?.Invoke(this, new OnIndexGeneratorEventArgs()
|
||||
{
|
||||
Parameters = Children[1].Convert<ExpressionList>()
|
||||
IndexParameters = Children[1].Convert<ExpressionList>()
|
||||
});
|
||||
}
|
||||
|
||||
OnParameterGenerator = null;
|
||||
OnIndexGenerator = null;
|
||||
}
|
||||
}
|
||||
|
@@ -10,8 +10,6 @@ public abstract class NonTerminatedSyntaxNode : SyntaxNodeBase, IEnumerable<Synt
|
||||
|
||||
public abstract NonTerminatorType Type { get; }
|
||||
|
||||
|
||||
|
||||
public required List<SyntaxNodeBase> Children { get; init; }
|
||||
|
||||
public IEnumerator<SyntaxNodeBase> GetEnumerator()
|
||||
|
@@ -7,13 +7,6 @@ public class ParameterList : NonTerminatedSyntaxNode
|
||||
{
|
||||
public override NonTerminatorType Type => NonTerminatorType.ParameterList;
|
||||
|
||||
public bool IsRecursive { get; private init; }
|
||||
|
||||
/// <summary>
|
||||
/// 声明的参数列表
|
||||
/// </summary>
|
||||
public IEnumerable<Parameter> Parameters => GetParameters();
|
||||
|
||||
public override void PreVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PreVisit(this);
|
||||
@@ -26,40 +19,6 @@ public class ParameterList : NonTerminatedSyntaxNode
|
||||
|
||||
public static ParameterList Create(List<SyntaxNodeBase> children)
|
||||
{
|
||||
bool isRecursive;
|
||||
|
||||
if (children.Count == 1)
|
||||
{
|
||||
isRecursive = false;
|
||||
}
|
||||
else if (children.Count == 3)
|
||||
{
|
||||
isRecursive = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return new ParameterList { Children = children, IsRecursive = isRecursive };
|
||||
}
|
||||
|
||||
private IEnumerable<Parameter> GetParameters()
|
||||
{
|
||||
ParameterList list = this;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (list.IsRecursive)
|
||||
{
|
||||
yield return list.Children[2].Convert<Parameter>();
|
||||
list = list.Children[0].Convert<ParameterList>();
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return list.Children[0].Convert<Parameter>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new ParameterList { Children = children };
|
||||
}
|
||||
}
|
||||
|
@@ -1,27 +1,36 @@
|
||||
using Canon.Core.Abstractions;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
public class OnParameterGeneratorEventArgs : EventArgs
|
||||
{
|
||||
public required ExpressionList Parameters { get; init; }
|
||||
}
|
||||
|
||||
public class ProcedureCall : NonTerminatedSyntaxNode
|
||||
{
|
||||
public override NonTerminatorType Type => NonTerminatorType.ProcedureCall;
|
||||
|
||||
public IdentifierSemanticToken ProcedureId
|
||||
=> (IdentifierSemanticToken)Children[0].Convert<TerminatedSyntaxNode>().Token;
|
||||
=> Children[0].Convert<TerminatedSyntaxNode>().Token.Convert<IdentifierSemanticToken>();
|
||||
|
||||
public IEnumerable<Expression> Arguments => GetArguments();
|
||||
/// <summary>
|
||||
/// 调用函数时含有参数的事件
|
||||
/// </summary>
|
||||
public event EventHandler<OnParameterGeneratorEventArgs>? OnParameterGenerator;
|
||||
|
||||
public override void PreVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PreVisit(this);
|
||||
RaiseEvent();
|
||||
}
|
||||
|
||||
public override void PostVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PostVisit(this);
|
||||
RaiseEvent();
|
||||
}
|
||||
|
||||
public static ProcedureCall Create(List<SyntaxNodeBase> children)
|
||||
@@ -29,38 +38,16 @@ public class ProcedureCall : NonTerminatedSyntaxNode
|
||||
return new ProcedureCall { Children = children };
|
||||
}
|
||||
|
||||
private IEnumerable<Expression> GetArguments()
|
||||
private void RaiseEvent()
|
||||
{
|
||||
if (Children.Count == 1)
|
||||
if (Children.Count == 4)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (Expression expression in Children[2].Convert<ExpressionList>().Expressions)
|
||||
{
|
||||
yield return expression;
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
builder.AddString(ProcedureId.IdentifierName + "(");
|
||||
|
||||
//用逗号分隔输出的expression
|
||||
using (var enumerator = Arguments.GetEnumerator())
|
||||
{
|
||||
if (enumerator.MoveNext())
|
||||
OnParameterGenerator?.Invoke(this, new OnParameterGeneratorEventArgs
|
||||
{
|
||||
enumerator.Current.GenerateCCode(builder);
|
||||
}
|
||||
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
builder.AddString(", ");
|
||||
enumerator.Current.GenerateCCode(builder);
|
||||
}
|
||||
Parameters = Children[2].Convert<ExpressionList>()
|
||||
});
|
||||
}
|
||||
|
||||
builder.AddString(")");
|
||||
OnParameterGenerator = null;
|
||||
}
|
||||
}
|
||||
|
@@ -82,7 +82,7 @@ public class Statement : NonTerminatedSyntaxNode
|
||||
|
||||
private void RaiseEvent()
|
||||
{
|
||||
if (Children.Count == 2)
|
||||
if (Children.Count == 3)
|
||||
{
|
||||
if (Children[0].IsTerminated)
|
||||
{
|
||||
|
@@ -8,10 +8,6 @@ public class StatementList : NonTerminatedSyntaxNode
|
||||
{
|
||||
public override NonTerminatorType Type => NonTerminatorType.StatementList;
|
||||
|
||||
public bool IsRecursive { get; private init; }
|
||||
|
||||
public IEnumerable<Statement> Statements => GetStatements();
|
||||
|
||||
public override void PreVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PreVisit(this);
|
||||
@@ -24,52 +20,6 @@ public class StatementList : NonTerminatedSyntaxNode
|
||||
|
||||
public static StatementList Create(List<SyntaxNodeBase> children)
|
||||
{
|
||||
bool isRecursive;
|
||||
|
||||
if (children.Count == 1)
|
||||
{
|
||||
isRecursive = false;
|
||||
}
|
||||
else if (children.Count == 3)
|
||||
{
|
||||
isRecursive = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return new StatementList { Children = children, IsRecursive = isRecursive };
|
||||
}
|
||||
|
||||
private IEnumerable<Statement> GetStatements()
|
||||
{
|
||||
StatementList list = this;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (list.IsRecursive)
|
||||
{
|
||||
yield return list.Children[2].Convert<Statement>();
|
||||
list = list.Children[0].Convert<StatementList>();
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return list.Children[0].Convert<Statement>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var statement in Statements.Reverse())
|
||||
{
|
||||
if (statement.Children.Count > 0)
|
||||
{
|
||||
statement.GenerateCCode(builder);
|
||||
builder.AddString(";");
|
||||
}
|
||||
}
|
||||
return new StatementList { Children = children};
|
||||
}
|
||||
}
|
||||
|
@@ -8,11 +8,6 @@ public class SubprogramDeclarations : NonTerminatedSyntaxNode
|
||||
{
|
||||
public override NonTerminatorType Type => NonTerminatorType.SubprogramDeclarations;
|
||||
|
||||
/// <summary>
|
||||
/// 声明的子程序列表
|
||||
/// </summary>
|
||||
public IEnumerable<Subprogram> Subprograms => GetSubprograms();
|
||||
|
||||
public override void PreVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PreVisit(this);
|
||||
@@ -27,28 +22,4 @@ public class SubprogramDeclarations : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new SubprogramDeclarations { Children = children };
|
||||
}
|
||||
|
||||
private IEnumerable<Subprogram> GetSubprograms()
|
||||
{
|
||||
SubprogramDeclarations declarations = this;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (declarations.Children.Count == 0)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return declarations.Children[1].Convert<Subprogram>();
|
||||
declarations = declarations.Children[0].Convert<SubprogramDeclarations>();
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var subprogram in Subprograms)
|
||||
{
|
||||
subprogram.GenerateCCode(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using Canon.Core.Abstractions;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
|
@@ -1,7 +1,5 @@
|
||||
using Canon.Core.Abstractions;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.SemanticParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -9,11 +7,6 @@ public class VarDeclarations : NonTerminatedSyntaxNode
|
||||
{
|
||||
public override NonTerminatorType Type => NonTerminatorType.VarDeclarations;
|
||||
|
||||
/// <summary>
|
||||
/// 声明的变量列表
|
||||
/// </summary>
|
||||
// public IEnumerable<(IdentifierList, TypeSyntaxNode)> Variables => EnumerateVariables();
|
||||
|
||||
public override void PreVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PreVisit(this);
|
||||
@@ -28,73 +21,4 @@ public class VarDeclarations : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new VarDeclarations { Children = children };
|
||||
}
|
||||
|
||||
// private IEnumerable<(IdentifierList, TypeSyntaxNode)> EnumerateVariables()
|
||||
// {
|
||||
// if (Children.Count == 0)
|
||||
// {
|
||||
// yield break;
|
||||
// }
|
||||
//
|
||||
// VarDeclaration declaration = Children[1].Convert<VarDeclaration>();
|
||||
//
|
||||
// while (true)
|
||||
// {
|
||||
// yield return declaration.Variable;
|
||||
//
|
||||
// if (declaration.IsRecursive)
|
||||
// {
|
||||
// declaration = declaration.Children[0].Convert<VarDeclaration>();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// public override void GenerateCCode(CCodeBuilder builder)
|
||||
// {
|
||||
// foreach (var pair in Variables.Reverse())
|
||||
// {
|
||||
// //BasicType定义
|
||||
// if (pair.Item2.Children.Count == 1)
|
||||
// {
|
||||
// //输出类型
|
||||
// pair.Item2.GenerateCCode(builder);
|
||||
// //输出idList
|
||||
// pair.Item1.GenerateCCode(builder);
|
||||
// builder.AddString(";");
|
||||
// }
|
||||
// //array定义
|
||||
// else
|
||||
// {
|
||||
// //构造出C语言形式的数组下标定义
|
||||
// string arrayPeriod = "";
|
||||
// var ranges = pair.Item2.Children[2]
|
||||
// .Convert<Period>().Ranges;
|
||||
// PascalType pascalType = pair.Item2.Children[5].Convert<BasicType>().TryGetPascalType();
|
||||
//
|
||||
// foreach (var range in ranges)
|
||||
// {
|
||||
// int low = int.Parse(range.Item1.LiteralValue);
|
||||
// int high = int.Parse(range.Item2.LiteralValue);
|
||||
// arrayPeriod = "[" + System.Convert.ToString(high-low+1) + "]" + arrayPeriod;
|
||||
// pascalType = new PascalArrayType(pascalType, low, high); //嵌套地构造出多维数组
|
||||
// }
|
||||
//
|
||||
// //依次定义每一个符号
|
||||
// foreach (var id in pair.Item1.Identifiers.Reverse())
|
||||
// {
|
||||
// pair.Item2.Children[5].GenerateCCode(builder);
|
||||
// builder.AddString(" " + id.IdentifierName + arrayPeriod + ";");
|
||||
// //写入符号表
|
||||
// builder.SymbolTable.TryAddSymbol(new Symbol()
|
||||
// {
|
||||
// SymbolName = id.IdentifierName, SymbolType = pascalType, Reference = false
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using Canon.Core.Abstractions;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
using Canon.Core.SemanticParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -8,12 +9,39 @@ public class Variable : NonTerminatedSyntaxNode
|
||||
{
|
||||
public override NonTerminatorType Type => NonTerminatorType.Variable;
|
||||
|
||||
private PascalType? _variableType;
|
||||
|
||||
/// <summary>
|
||||
/// Variable实际的类型,用于数组赋值
|
||||
/// </summary>
|
||||
public PascalType VariableType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_variableType is null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return _variableType;
|
||||
}
|
||||
set
|
||||
{
|
||||
_variableType = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 变量的名称
|
||||
/// </summary>
|
||||
public IdentifierSemanticToken Identifier =>
|
||||
(IdentifierSemanticToken)Children[0].Convert<TerminatedSyntaxNode>().Token;
|
||||
|
||||
/// <summary>
|
||||
/// 声明数组访问的部分
|
||||
/// </summary>
|
||||
public IdentifierVarPart VarPart => Children[1].Convert<IdentifierVarPart>();
|
||||
|
||||
public override void PreVisit(SyntaxNodeVisitor visitor)
|
||||
{
|
||||
visitor.PreVisit(this);
|
||||
|
Reference in New Issue
Block a user