feat: symbol-table & type checker (#14)
Reviewed-on: PostGuard/Canon#14 Co-authored-by: Lan_G <2911328695@qq.com> Co-committed-by: Lan_G <2911328695@qq.com>
This commit is contained in:
		@@ -95,3 +95,11 @@ public enum StateType
 | 
				
			|||||||
    Delimiter,
 | 
					    Delimiter,
 | 
				
			||||||
    Other
 | 
					    Other
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum BasicIdType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Int,
 | 
				
			||||||
 | 
					    Real,
 | 
				
			||||||
 | 
					    Char,
 | 
				
			||||||
 | 
					    Bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
namespace Canon.Core.Exceptions;
 | 
					namespace Canon.Core.Exceptions;
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
/// 语法分析中引发的异常
 | 
					/// 语法分析中引发的异常
 | 
				
			||||||
/// </summary>
 | 
					/// </summary>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										178
									
								
								Canon.Core/SemanticParser/IdentifierType.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								Canon.Core/SemanticParser/IdentifierType.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
				
			|||||||
 | 
					using Canon.Core.Enums;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Canon.Core.SemanticParser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// 标识符类型基类
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public abstract class IdentifierType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class BasicType : IdentifierType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public BasicIdType IdType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BasicType(BasicIdType basicIdType)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        IdType = basicIdType;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator ==(BasicType a, BasicType b)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return a.IdType == b.IdType;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator !=(BasicType a, BasicType b)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return !(a == b);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ArrayType : IdentifierType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public int Dimension;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public List<Limits> LimitsList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IdentifierType ElementType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ArrayType(int dimension, List<Limits> limitsList, IdentifierType elementType)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Dimension = dimension;
 | 
				
			||||||
 | 
					        LimitsList = limitsList;
 | 
				
			||||||
 | 
					        ElementType = elementType;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator ==(ArrayType a, ArrayType b)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (a.Dimension != b.Dimension || a.ElementType != b.ElementType || a.LimitsList.Count != b.LimitsList.Count)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int n = a.LimitsList.Count;
 | 
				
			||||||
 | 
					        for (int i = 0; i < n; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (a.LimitsList[i] != b.LimitsList[i])
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator !=(ArrayType a, ArrayType b)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return !(a == b);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class FuncType : IdentifierType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public List<Param> ParamTypeList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IdentifierType ReturnType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public FuncType(List<Param> paramTypeList, IdentifierType returnType)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ParamTypeList = paramTypeList;
 | 
				
			||||||
 | 
					        ReturnType = returnType;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ProcType : IdentifierType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public List<Param> ParamTypeList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ProcType()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ParamTypeList = new List<Param>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ProcType(List<Param> paramTypeList)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ParamTypeList = paramTypeList;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class RecordType : IdentifierType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public Dictionary<string, IdentifierType> MemberDic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public RecordType()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        MemberDic = new Dictionary<string, IdentifierType>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator ==(RecordType a, RecordType b)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (a.MemberDic.Count != b.MemberDic.Count)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach (var k in a.MemberDic.Keys)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!b.MemberDic.ContainsKey(k) || a.MemberDic[k] != b.MemberDic[k])
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator !=(RecordType a, RecordType b)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return !(a == b);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// 空类型,用于充当procedure的返回值
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public class NonType : IdentifierType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Limits
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public uint LowerBound;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public uint UpperBound;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Limits(uint lowerBound, uint upperBound)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        LowerBound = lowerBound;
 | 
				
			||||||
 | 
					        UpperBound = upperBound;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator ==(Limits a, Limits b)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return a.LowerBound == b.LowerBound && a.UpperBound == b.UpperBound;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator !=(Limits a, Limits b)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return !(a == b);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Param
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public string Name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IdentifierType Type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public bool IsVar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Param(string name, IdentifierType type, bool isVar)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Name = name;
 | 
				
			||||||
 | 
					        Type = type;
 | 
				
			||||||
 | 
					        IsVar = isVar;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										731
									
								
								Canon.Core/SemanticParser/SemanticBuilder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										731
									
								
								Canon.Core/SemanticParser/SemanticBuilder.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,731 @@
 | 
				
			|||||||
 | 
					using Canon.Core.Enums;
 | 
				
			||||||
 | 
					using Canon.Core.Exceptions;
 | 
				
			||||||
 | 
					using Canon.Core.GrammarParser;
 | 
				
			||||||
 | 
					using Canon.Core.LexicalParser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Canon.Core.SemanticParser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class SemanticBuilder
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private SymbolTable _curSymbolTable; //当前符号表
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Stack<SymbolTable> _stack;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public SemanticBuilder()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        _curSymbolTable = new SymbolTable();
 | 
				
			||||||
 | 
					        _stack = new Stack<SymbolTable>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 执行语义分析
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="root">语法树根节点</param>
 | 
				
			||||||
 | 
					    public void Build(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //新建一个符号表,压入栈
 | 
				
			||||||
 | 
					        _stack.Push(_curSymbolTable);
 | 
				
			||||||
 | 
					        //开始递归调用,完成构建符号表和类型检查
 | 
				
			||||||
 | 
					        SolveProgramStruct(root);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveProgramStruct(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SolveProgramHead(root.Children[0]);
 | 
				
			||||||
 | 
					        SolveProgramBody(root.Children[2]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveProgramHead(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //不做任何处理
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveProgramBody(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SolveConstDeclarations(root.Children[0]);
 | 
				
			||||||
 | 
					        SolveVarDeclarations(root.Children[1]);
 | 
				
			||||||
 | 
					        SolveSubprogramDeclarations(root.Children[2]);
 | 
				
			||||||
 | 
					        SolveCompoundStatement(root.Children[3]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveConstDeclarations(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (root.Children.Count > 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolveConstDeclaration(root.Children[1]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveConstDeclaration(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int offset = 0;
 | 
				
			||||||
 | 
					        if (!root.Children[0].IsTerminated)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolveConstDeclaration(root.Children[0]);
 | 
				
			||||||
 | 
					            offset = 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var idName = root.Children[offset].GetSemanticToken().LiteralValue;
 | 
				
			||||||
 | 
					        _curSymbolTable.AddEntry(idName, SolveConstValue(root.Children[offset+2]), true, false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IdentifierType SolveConstValue(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (root.Children.Count == 3)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return new BasicType(BasicIdType.Char);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var t = ((NumberSemanticToken)root.GetSemanticToken()).NumberType;
 | 
				
			||||||
 | 
					            if (t == NumberType.Real)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return new BasicType(BasicIdType.Real);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return new BasicType(BasicIdType.Int);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveVarDeclarations(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (root.Children.Count > 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolveVarDeclaration(root.Children[1]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveVarDeclaration(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int offset = 0;
 | 
				
			||||||
 | 
					        if (root.Children.Count > 3)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolveVarDeclaration(root.Children[0]);
 | 
				
			||||||
 | 
					            offset = 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        List<string> idList = new List<string>();
 | 
				
			||||||
 | 
					        SolveIdList(root.Children[offset], idList);   //获取待定义的标识符列表
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var type = SolveType(root.Children[offset + 2]);  //获取类型
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //将符号批量插入符号表
 | 
				
			||||||
 | 
					        foreach(var id in idList)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _curSymbolTable.AddEntry(id, type, false, false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveIdList(SyntaxNode root, List<string> idList)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (root.IsTerminated)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var word = root.GetSemanticToken().LiteralValue;
 | 
				
			||||||
 | 
					            if (word != ",")
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                idList.Add(word);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach (var child in root.Children)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolveIdList(child, idList);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IdentifierType SolveType(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        string typeName = root.Children[0].Children[0].GetSemanticToken().LiteralValue;
 | 
				
			||||||
 | 
					        //基本类型或记录类型
 | 
				
			||||||
 | 
					        if (root.Children.Count == 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            //逐层向外检查类型是否在类型表中
 | 
				
			||||||
 | 
					            var cur = _curSymbolTable;
 | 
				
			||||||
 | 
					            while (cur != null && !cur.TypesTable.Check(typeName))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                cur = cur.PreTable;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (cur != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return cur.TypesTable.GetTypeByName(typeName);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            throw new SemanticException(typeName + " is an undefined type!");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //数组类型
 | 
				
			||||||
 | 
					        var limitList = new List<Limits>();
 | 
				
			||||||
 | 
					        SolvePeriod(root.Children[2], limitList);
 | 
				
			||||||
 | 
					        return new ArrayType(limitList.Count, limitList, SolveType(root.Children[5]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolvePeriod(SyntaxNode root, List<Limits> limitsList)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!root.Children[0].IsTerminated)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolvePeriod(root.Children[0], limitsList); //递归获取子节点的界限列表
 | 
				
			||||||
 | 
					            offset = 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //token1和2对应数组当前维度的上下界
 | 
				
			||||||
 | 
					        var token1 = (NumberSemanticToken)root.Children[offset].GetSemanticToken();
 | 
				
			||||||
 | 
					        var t1 = token1.NumberType;
 | 
				
			||||||
 | 
					        var token2 = (NumberSemanticToken)root.Children[offset + 3].GetSemanticToken();
 | 
				
			||||||
 | 
					        var t2 = token2.NumberType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //检查数组上下界定义是否合法
 | 
				
			||||||
 | 
					        if (t1 == NumberType.Integer && t2 == NumberType.Integer)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            int lower = int.Parse(token1.LiteralValue);
 | 
				
			||||||
 | 
					            int upper = int.Parse(token2.LiteralValue);
 | 
				
			||||||
 | 
					            if (upper >= lower)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (lower >= 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    limitsList.Add(new Limits((uint)lower, (uint)upper));
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                throw new SemanticException("Array's bounds must be nonnegative!");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            throw new SemanticException("Array's upper bound must greater than low bound!");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw new SemanticException("Array's bounds must be integer!");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveSubprogramDeclarations(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (root.Children.Count > 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolveSubprogramDeclarations(root.Children[0]);
 | 
				
			||||||
 | 
					            SolveSubprogram(root.Children[1]);
 | 
				
			||||||
 | 
					            //处理完一个子过程/函数,将对应符号表出栈,当前符号表更新为新栈顶符号表
 | 
				
			||||||
 | 
					            _stack.Pop();
 | 
				
			||||||
 | 
					            _curSymbolTable = _stack.Peek();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveSubprogram(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SolveSubprogramHead(root.Children[0]);
 | 
				
			||||||
 | 
					        SolveSubprogramBody(root.Children[2]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveSubprogramHead(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //获取参数列表信息
 | 
				
			||||||
 | 
					        List<Param> paramList = new List<Param>();
 | 
				
			||||||
 | 
					        SolveFormalParameter(root.Children[2], paramList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //区分procedure和function
 | 
				
			||||||
 | 
					        IdentifierType identifierType;
 | 
				
			||||||
 | 
					        if (root.Children.Count == 3)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            identifierType = new ProcType(paramList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var type = SolveType(root.Children[4]); //获取函数返回值
 | 
				
			||||||
 | 
					            identifierType = new FuncType(paramList, type);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //创建子符号表
 | 
				
			||||||
 | 
					        SymbolTable subTable = new SymbolTable(_curSymbolTable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //将参数列表参数拷贝一份到子符号表
 | 
				
			||||||
 | 
					        foreach (var param in paramList)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            subTable.AddEntry(param.Name, param.Type, false, param.IsVar);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //将proc/func头定义写入当前符号表
 | 
				
			||||||
 | 
					        _curSymbolTable.AddEntry(root.Children[1].GetSemanticToken().LiteralValue, identifierType, subTable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //子符号表入栈
 | 
				
			||||||
 | 
					        _stack.Push(subTable);
 | 
				
			||||||
 | 
					        //更新当前符号表为子符号表
 | 
				
			||||||
 | 
					        _curSymbolTable = subTable;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveFormalParameter(SyntaxNode root, List<Param> paramList)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (root.Children.Count > 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolveParameterList(root.Children[1], paramList);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveParameterList(SyntaxNode root, List<Param> paramList)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int offset = 0;
 | 
				
			||||||
 | 
					        if (root.Children.Count > 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolveParameterList(root, paramList);
 | 
				
			||||||
 | 
					            offset = 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SolveParameter(root.Children[offset], paramList);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveParameter(SyntaxNode root, List<Param> paramList)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        bool isVarParam = false;
 | 
				
			||||||
 | 
					        SyntaxNode node = root.Children[0];
 | 
				
			||||||
 | 
					        if (node.GetNonTerminatorType() == NonTerminatorType.VarParameter)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            isVarParam = true;
 | 
				
			||||||
 | 
					            node = node.Children[1];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        List<string> list = new List<string>();
 | 
				
			||||||
 | 
					        SolveIdList(node.Children[0], list);
 | 
				
			||||||
 | 
					        var type = SolveType(node.Children[2]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach (var idName in list)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            paramList.Add(new Param(idName, type, isVarParam));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveSubprogramBody(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SolveConstDeclarations(root.Children[0]);
 | 
				
			||||||
 | 
					        SolveVarDeclarations(root.Children[1]);
 | 
				
			||||||
 | 
					        SolveCompoundStatement(root.Children[2]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveCompoundStatement(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SolveStatementList(root.Children[1]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveStatementList(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int offset = 0;
 | 
				
			||||||
 | 
					        if (root.Children.Count > 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolveStatementList(root.Children[0]);
 | 
				
			||||||
 | 
					            offset = 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SolveStatement(root.Children[offset]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveStatement(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var node = root.Children[0];
 | 
				
			||||||
 | 
					        if (node.IsTerminated)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            //通过子节点个数判断用的statement的哪个产生式
 | 
				
			||||||
 | 
					            int childCount = root.Children.Count;
 | 
				
			||||||
 | 
					            switch (childCount)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case 3:
 | 
				
			||||||
 | 
					                    CheckFuncAssign(root);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case 5:
 | 
				
			||||||
 | 
					                    SolveIf(root);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case 8:
 | 
				
			||||||
 | 
					                    CheckForLoop(root);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    throw new SemanticException("Semantic analysis failed and an illegal node was detected");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var nonTerminatorType = node.GetNonTerminatorType();
 | 
				
			||||||
 | 
					            switch (nonTerminatorType)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case NonTerminatorType.Variable:
 | 
				
			||||||
 | 
					                    SolveVariableAssign(root);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case NonTerminatorType.ProcedureCall:
 | 
				
			||||||
 | 
					                    SolveCall(node, false);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case NonTerminatorType.CompoundStatement:
 | 
				
			||||||
 | 
					                    SolveCompoundStatement(node);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    throw new SemanticException("Semantic analysis failed and an illegal node was detected");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 处理表达式
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="root"></param>
 | 
				
			||||||
 | 
					    /// <returns>表达式类型</returns>
 | 
				
			||||||
 | 
					    private IdentifierType SolveExpression(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (root.Children.Count == 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return SolveSimpleExpression(root.Children[0]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var type1 = SolveSimpleExpression(root.Children[0]);
 | 
				
			||||||
 | 
					        var type2 = SolveSimpleExpression(root.Children[2]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return CheckRelationOperation(type1, type2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IdentifierType SolveSimpleExpression(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (root.Children.Count == 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return SolveTerm(root.Children[0]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var type1 = SolveSimpleExpression(root.Children[0]);
 | 
				
			||||||
 | 
					        var type2 = SolveTerm(root.Children[2]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return CheckAddOperation(type1, type2, root.Children[1].Children[0].GetSemanticToken());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IdentifierType SolveTerm(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (root.Children.Count == 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return SolveFactor(root.Children[0]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var type1 = SolveTerm(root.Children[0]);
 | 
				
			||||||
 | 
					        var type2 = SolveFactor(root.Children[2]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return CheckMultiplyOperation(type1, type2, root.Children[1].Children[0].GetSemanticToken());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IdentifierType SolveFactor(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (root.Children.Count == 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (root.Children[0].IsTerminated)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var numberSemanticToken = (NumberSemanticToken)root.Children[0].GetSemanticToken();
 | 
				
			||||||
 | 
					                if (numberSemanticToken.NumberType == NumberType.Real)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    return _curSymbolTable.TypesTable.GetTypeByName("real");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return _curSymbolTable.TypesTable.GetTypeByName("integer");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return SolveVariable(root.Children[0]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //处理 Factor -> (expression)
 | 
				
			||||||
 | 
					        if (root.Children.Count == 3)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return SolveExpression(root.Children[1]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //函数掉用
 | 
				
			||||||
 | 
					        if (root.Children.Count == 4)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return SolveCall(root, true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //处理 Factor -> not Factor
 | 
				
			||||||
 | 
					        if (root.Children[0].GetSemanticToken() == new Terminator(KeywordType.Not))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var type = SolveFactor(root.Children[1]);
 | 
				
			||||||
 | 
					            if (type == _curSymbolTable.TypesTable.GetTypeByName("boolean"))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return type;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            throw new SemanticException("NOT can only be used for Boolean expressions");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //处理数字取负
 | 
				
			||||||
 | 
					        var type1 = SolveFactor(root.Children[1]);
 | 
				
			||||||
 | 
					        if (type1 == _curSymbolTable.TypesTable.GetTypeByName("integer") ||
 | 
				
			||||||
 | 
					            type1 == _curSymbolTable.TypesTable.GetTypeByName("real"))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return type1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw new SemanticException("minus can only be used on integer or real");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveIf(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var boolType = _curSymbolTable.TypesTable.GetTypeByName("boolean");
 | 
				
			||||||
 | 
					        if (SolveExpression(root.Children[0]) != boolType)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw new SemanticException("The conditional expression of the if statement must be of type Boolean");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SolveStatement(root.Children[3]);
 | 
				
			||||||
 | 
					        SolveElsePart(root.Children[4]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveElsePart(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (root.Children.Count > 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolveStatement(root.Children[1]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void CheckForLoop(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var intType = _curSymbolTable.TypesTable.GetTypeByName("integer");
 | 
				
			||||||
 | 
					        string idName = root.Children[1].GetSemanticToken().LiteralValue;
 | 
				
			||||||
 | 
					        if (_curSymbolTable.Find(idName) && _curSymbolTable.GetIdTypeByName(idName) == intType)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (SolveExpression(root.Children[3]) == intType && SolveExpression(root.Children[5]) == intType)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                SolveStatement(root.Children[7]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                throw new SemanticException("The upper and lower bounds of the loop variable in the for loop" +
 | 
				
			||||||
 | 
					                                            " must be set to integer");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw new SemanticException("The loop variable in the for loop must be integer");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveVariableAssign(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var varType = SolveVariable(root.Children[0]);
 | 
				
			||||||
 | 
					        var expType = SolveExpression(root.Children[2]);
 | 
				
			||||||
 | 
					        CheckAssign(varType, expType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //常量不允许被重复赋值
 | 
				
			||||||
 | 
					        var idName = root.Children[0].GetSemanticToken().LiteralValue;
 | 
				
			||||||
 | 
					        if (_curSymbolTable.IsConst(idName))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw new SemanticException("Constants defined as const are not allowed to be assigned repeatedly");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IdentifierType SolveVariable(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var idName = root.Children[0].GetSemanticToken().LiteralValue;
 | 
				
			||||||
 | 
					        var idType = _curSymbolTable.GetIdTypeByName(idName);
 | 
				
			||||||
 | 
					        if (idType is BasicType)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (root.Children[1].Children.Count == 1)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return idType;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            throw new SemanticException("The reference to variable "+ idName+  " is illegal");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //暂时只考虑数组类型
 | 
				
			||||||
 | 
					        List<IdentifierType> typeList = new List<IdentifierType>();
 | 
				
			||||||
 | 
					        SolveExpressionList(root.Children[1].Children[1], typeList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int dimension = ((ArrayType)idType).Dimension;
 | 
				
			||||||
 | 
					        //数组引用维数一致
 | 
				
			||||||
 | 
					        if (typeList.Count == dimension)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            //每个维度的表达式类型都是int
 | 
				
			||||||
 | 
					            var IntType = _curSymbolTable.TypesTable.GetTypeByName("integer");
 | 
				
			||||||
 | 
					            foreach (var t in typeList)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (t != IntType)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    throw new SemanticException("Array's index must be integer!");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return ((ArrayType)idType).ElementType;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw new SemanticException("The reference to array " + idName + " requires " + dimension + " subscripts");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void SolveExpressionList(SyntaxNode root, List<IdentifierType> typeList)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int offset = 0;
 | 
				
			||||||
 | 
					        if (root.Children.Count > 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            SolveExpressionList(root.Children[0], typeList);
 | 
				
			||||||
 | 
					            offset = 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        typeList.Add(SolveExpression(root.Children[offset]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IdentifierType SolveCall(SyntaxNode root, bool isFunc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var idName = root.Children[0].GetSemanticToken().LiteralValue;
 | 
				
			||||||
 | 
					        IdentifierType idType = _curSymbolTable.GetIdTypeByName(idName);
 | 
				
			||||||
 | 
					        //获取调用表达式的类型列表
 | 
				
			||||||
 | 
					        List<IdentifierType> typeList = new List<IdentifierType>();
 | 
				
			||||||
 | 
					        SolveExpressionList(root.Children[2], typeList);
 | 
				
			||||||
 | 
					        //将调用类型列表和定义参数列表的类型一一比对
 | 
				
			||||||
 | 
					        var paramList = isFunc ? ((FuncType)idType).ParamTypeList : ((ProcType)idType).ParamTypeList;
 | 
				
			||||||
 | 
					        if (paramList.Count == typeList.Count)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            int n = paramList.Count;
 | 
				
			||||||
 | 
					            for (int i = 0; i < n; i++) {
 | 
				
			||||||
 | 
					                if (paramList[i].Type != typeList[i])
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    throw new SemanticException("The parameter types are inconsistent");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return isFunc ? ((FuncType)idType).ReturnType : new NonType();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw new SemanticException("The number of parameters of procedure is inconsistent");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void CheckFuncAssign(SyntaxNode root)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (_curSymbolTable.PreTable is null)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw new SemanticException("Not allowed to assign a value to a function name in the main program");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        //获取函数返回值类型
 | 
				
			||||||
 | 
					        var idType =
 | 
				
			||||||
 | 
					            ((FuncType)_curSymbolTable.PreTable.GetIdTypeByName(root.Children[0].GetSemanticToken().LiteralValue)).ReturnType;
 | 
				
			||||||
 | 
					        //获取右侧表达式类型
 | 
				
			||||||
 | 
					        var expressionType = SolveExpression(root.Children[2]);
 | 
				
			||||||
 | 
					        //对赋值进行类型检查
 | 
				
			||||||
 | 
					        CheckAssign(idType, expressionType);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 检查赋值语句左右部分类型是否相容
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="leftType">赋值号左边类型(若为函数,则取返回值)</param>
 | 
				
			||||||
 | 
					    /// <param name="rightType">赋值号右边类型</param>
 | 
				
			||||||
 | 
					    private void CheckAssign(IdentifierType leftType, IdentifierType rightType)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (leftType == rightType)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var intType = _curSymbolTable.TypesTable.GetTypeByName("integer");
 | 
				
			||||||
 | 
					        var realType = _curSymbolTable.TypesTable.GetTypeByName("real");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (leftType == realType && rightType == intType)   //int可以赋值给real
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw new SemanticException("Incompatible types in assign operation");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 检查关系操作(比大小)的操作数类型
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="leftType">左边符号类型</param>
 | 
				
			||||||
 | 
					    /// <param name="rightType">右边符号类型</param>
 | 
				
			||||||
 | 
					    /// <returns>成功则返回boolean类型</returns>
 | 
				
			||||||
 | 
					    private IdentifierType CheckRelationOperation(IdentifierType leftType, IdentifierType rightType)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var intType = _curSymbolTable.TypesTable.GetTypeByName("integer");
 | 
				
			||||||
 | 
					        var realType = _curSymbolTable.TypesTable.GetTypeByName("real");
 | 
				
			||||||
 | 
					        var boolType = _curSymbolTable.TypesTable.GetTypeByName("boolean");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //左右为相等的基本类型或 一个int和一个real
 | 
				
			||||||
 | 
					        if (leftType == rightType && leftType is BasicType ||
 | 
				
			||||||
 | 
					            leftType == intType && rightType == realType ||
 | 
				
			||||||
 | 
					            leftType == realType && rightType == intType)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return boolType;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw new SemanticException("Incompatible types in relation operations");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IdentifierType CheckAddOperation(IdentifierType leftType, IdentifierType rightType, SemanticToken semanticToken)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // or操作两边必为boolean
 | 
				
			||||||
 | 
					        var boolType = _curSymbolTable.TypesTable.GetTypeByName("boolean");
 | 
				
			||||||
 | 
					        if (semanticToken == new Terminator(KeywordType.Or))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (leftType == boolType && rightType == boolType)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return boolType;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            throw new SemanticException("Incompatible types in add operation \"or\"");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var intType = _curSymbolTable.TypesTable.GetTypeByName("integer");
 | 
				
			||||||
 | 
					        var realType = _curSymbolTable.TypesTable.GetTypeByName("real");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //左右为相等的基本类型但不为boolean
 | 
				
			||||||
 | 
					        if (leftType == rightType && leftType is BasicType && leftType != boolType)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return leftType;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        //int和real可兼容
 | 
				
			||||||
 | 
					        if (leftType == intType && rightType == realType || leftType == realType && rightType == intType)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return realType;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw new SemanticException("Incompatible types in add operations");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IdentifierType CheckMultiplyOperation(IdentifierType leftType, IdentifierType rightType, SemanticToken semanticToken)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // and操作两边必为boolean
 | 
				
			||||||
 | 
					        var boolType = _curSymbolTable.TypesTable.GetTypeByName("boolean");
 | 
				
			||||||
 | 
					        if (semanticToken == new Terminator(KeywordType.And))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (leftType == boolType && rightType == boolType)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return boolType;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            throw new SemanticException("Incompatible types in multiply operation \"and\"");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // div和mod操作数必为int
 | 
				
			||||||
 | 
					        var intType = _curSymbolTable.TypesTable.GetTypeByName("integer");
 | 
				
			||||||
 | 
					        if (semanticToken == new Terminator(KeywordType.Mod) || semanticToken == new Terminator(KeywordType.Divide))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (leftType == intType && rightType == intType)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return intType;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            throw new SemanticException("Incompatible types in multiply operation \"mod/div\"");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //都是int或都是real
 | 
				
			||||||
 | 
					        var realType = _curSymbolTable.TypesTable.GetTypeByName("real");
 | 
				
			||||||
 | 
					        if (leftType == intType && rightType == intType || leftType == realType && rightType == realType)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return leftType;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        //一个是int,另一个real
 | 
				
			||||||
 | 
					        if (leftType == intType && rightType == realType || leftType == realType && rightType == intType)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return realType;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw new SemanticException("Incompatible types in multiply operations");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										107
									
								
								Canon.Core/SemanticParser/SymbolTable.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								Canon.Core/SemanticParser/SymbolTable.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					using Canon.Core.Exceptions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Canon.Core.SemanticParser;
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					///符号表类
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public class SymbolTable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public Dictionary<string, SymbolTableEntry> Entries;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public TypeTable TypesTable;    //当前符号表对应的类型表
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public SymbolTable? PreTable;  //直接外围符号表
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public SymbolTable()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Entries = new Dictionary<string, SymbolTableEntry>();
 | 
				
			||||||
 | 
					        TypesTable = new TypeTable();
 | 
				
			||||||
 | 
					        PreTable = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public SymbolTable(SymbolTable preTable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Entries = new Dictionary<string, SymbolTableEntry>();
 | 
				
			||||||
 | 
					        TypesTable = new TypeTable();
 | 
				
			||||||
 | 
					        PreTable = preTable;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 向符号表里插入一个表项
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public void AddEntry(string idName, IdentifierType type, bool isConst, bool isVarParam)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (Check(idName))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw new SemanticException("failed to insert to SymbolTable! " +  idName + " is defined repeatedly");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Entries.Add(idName, new SymbolTableEntry(idName, type, isConst, isVarParam));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void AddEntry(string idName, IdentifierType type, SymbolTable subTable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (Check(idName))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw new SemanticException("failed to insert to SymbolTable! " +  idName + " is defined repeatedly");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Entries.Add(idName, new SymbolTableEntry(idName, type, subTable));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///检查符号表,看是否有变量重复声明
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="idName">查询的id名称</param>
 | 
				
			||||||
 | 
					    /// <returns>如果变量重复声明,返回true</returns>
 | 
				
			||||||
 | 
					    public bool Check(string idName)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return Entries.ContainsKey(idName);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 在符号表里查找,看当前引用变量是否声明
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="idName">查询的id名称</param>
 | 
				
			||||||
 | 
					    /// <returns>如果有定义,返回true</returns>
 | 
				
			||||||
 | 
					    public bool Find(string idName)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (Entries.ContainsKey(idName))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (PreTable is not null && PreTable.Entries.ContainsKey(idName))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw new SemanticException("identifier "+ idName + " is not defined!");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 通过id名获取id的类型
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="idName">id名字</param>
 | 
				
			||||||
 | 
					    /// <returns>id在符号表里的类型</returns>
 | 
				
			||||||
 | 
					    public IdentifierType GetIdTypeByName(string idName)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (Entries.ContainsKey(idName))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return Entries[idName].Type;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (PreTable is not null && PreTable.Entries.ContainsKey(idName))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return PreTable.Entries[idName].Type;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw new SemanticException("identifier "+ idName + " is not defined!");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public bool IsConst(string idName)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return Find(idName) && Entries[idName].IsConst;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										37
									
								
								Canon.Core/SemanticParser/SymbolTableEntry.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Canon.Core/SemanticParser/SymbolTableEntry.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					namespace Canon.Core.SemanticParser;
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// 符号表表项类
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public class SymbolTableEntry
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public string Name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IdentifierType Type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public bool IsConst;    //是否为常量
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public bool IsVarParam;     //是否为引用变量
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public SymbolTable? SubTable;  //当前表项的子表
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public SymbolTableEntry(string name, IdentifierType type, bool isConst, bool isVarParam)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Name = name;
 | 
				
			||||||
 | 
					        Type = type;
 | 
				
			||||||
 | 
					        IsConst = isConst;
 | 
				
			||||||
 | 
					        IsVarParam = isVarParam;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public SymbolTableEntry(string name, IdentifierType type, SymbolTable subTable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Name = name;
 | 
				
			||||||
 | 
					        Type = type;
 | 
				
			||||||
 | 
					        IsConst = false;
 | 
				
			||||||
 | 
					        IsVarParam = false;
 | 
				
			||||||
 | 
					        SubTable = subTable;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										66
									
								
								Canon.Core/SemanticParser/TypeTable.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								Canon.Core/SemanticParser/TypeTable.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					using System.Security;
 | 
				
			||||||
 | 
					using Canon.Core.Enums;
 | 
				
			||||||
 | 
					using Canon.Core.Exceptions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Canon.Core.SemanticParser;
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// 类型表
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public class TypeTable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private Dictionary<string, IdentifierType> EntryDict { get; init; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public TypeTable()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        EntryDict = new Dictionary<string, IdentifierType>();
 | 
				
			||||||
 | 
					        //加入4种基本类型
 | 
				
			||||||
 | 
					        EntryDict.Add("integer", new BasicType(BasicIdType.Int));
 | 
				
			||||||
 | 
					        EntryDict.Add("real", new BasicType(BasicIdType.Real));
 | 
				
			||||||
 | 
					        EntryDict.Add("char", new BasicType(BasicIdType.Char));
 | 
				
			||||||
 | 
					        EntryDict.Add("boolean", new BasicType(BasicIdType.Bool));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 判断类型表里是否已经有该类型
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="typeName">类型名称</param>
 | 
				
			||||||
 | 
					    /// <returns>如果有,返回true</returns>
 | 
				
			||||||
 | 
					    public bool Check(string typeName)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return EntryDict.ContainsKey(typeName);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 往类型表里添加类型
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="typeName">类型名称</param>
 | 
				
			||||||
 | 
					    /// <param name="identifierType">类型的类别(一般是记录)</param>
 | 
				
			||||||
 | 
					    public void AddEntry(string typeName, IdentifierType identifierType)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!Check(typeName))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            EntryDict.Add(typeName, identifierType);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw new SemanticException("Failed to add to TypeTable! Types were repeatedly defined");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// 由类型名获取类型
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public IdentifierType GetTypeByName(string typeName)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (Check(typeName))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return EntryDict[typeName];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw new SecurityException("Failed to get type from typeTable! Type is not existed");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user