⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 csharpast.cs

📁 C#编写的c#编译器
💻 CS
📖 第 1 页 / 共 5 页
字号:
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.CodeDom;
using System.Globalization;

using antlr;	
using antlr.collections;
using Dom = DDW.CSharp.Dom;
using DDW.CSharp.SymbolTable;

namespace DDW.CSharp.Parse
{
	#region CSharpAST 
	/// <summary>
	/// The base class for all custom ASTs.
	/// </summary>
	public class CSharpAST : antlr.BaseAST // was abstract
	{	
		private int ttype = Token.INVALID_TYPE;
		protected string p_text;
		protected bool isDirty = true;
		protected Dom.TypeDecl curType;
		//public static int CurLine = 0;
		//public static int CurCol = 0;
		#region Constructor 
		public						CSharpAST()			
		{
			//Console.WriteLine("tok: "+this.GetType()+" ln# " + LinePragma.Line);
		}
		/// <summary>
		/// Construct blank AST node using a token
		/// </summary>
		public						CSharpAST(Token tok)
		{
			Console.WriteLine("has tok: "+this.GetType());
			initialize(tok);
		}
 		#endregion 
		#region UserData 
		/// <summary>
		/// Gets or sets the user-definable data for the current object.
		/// </summary>
		public virtual IDictionary 	UserData			
		{
			get{ return null; }
			set{ }
		}
		#endregion 
		#region FileName
		private string p_filename = "";
		public string			FileName				
		{
			get{return p_filename;}	
			set{p_filename = value;}	
		}
		#endregion
 		#region Text 
		/// <summary>
		/// Gets or sets the text of the node.
		/// </summary>
		//		public override string		Text				
		//		{
		//			get{return p_text;}	
		//			set{p_text = value;}	
		//		}
		#endregion 
 		#region Type 
		/// <summary>
		/// Gets or sets the Type of the node (TODO: make this enum)
		/// </summary>
		public override int			Type				
		{
			get{return ttype;}	
			set{ttype = value;}	
		}
		#endregion 
		#region  LinePragma
		private Dom.LinePragma p_linePragma = new Dom.LinePragma();
		public Dom.LinePragma				LinePragma		
		{
			get
			{	
				return p_linePragma;
			}
			set
			{
					p_linePragma = value;
			}
		}
		#endregion
		// was abstract
		public virtual Dom.IGraph  GetGraph(){ return null;}
		public virtual Dom.IGraph  GetGraph(Dom.IGraph graph)
		{ 
			//graph.LinePragma = this.LinePragma;
			return graph;
		}

		#region ToString
		public override String		ToString()			
		{
			return p_text +" (" + this.GetType().Name+")";
		}
		#endregion
		#region Various Java methods 
		public override void		initialize(int t, String txt)	
		{
			setType(t);
			setText(txt);
			//LinePragma.Line = CurLine;
			//LinePragma.Column = CurCol;
		}

		public override void		initialize(AST t)				
		{
			p_text = t.getText();
			Type = t.Type;
//			if(t is CSharpAST)
//			{
//				LinePragma.Line = CurLine;
//				LinePragma.Column = CurCol;
//			}
		}

		public override void		initialize(Token tok)			
		{
			p_text = tok.getText();
			Type = tok.Type;
//			LinePragma.Line = tok.getLine();
//			LinePragma.Column = CurCol;
		}
		public override String		getText()						
		{
			return p_text;
		}
		public			int			getType()						
		{
			return ttype;
		}
		public override void		setText(String text_)			
		{
			p_text = text_;
		}

		public override void		setType(int ttype_)				
		{
			ttype = ttype_;
		}
		#endregion 

		#region ScopeTable
		private static Dom.CompileUnit currentCompileUnit;
		public static ScopeCollection ScopeTable
		{
			get
			{
				return  currentCompileUnit.ScopeTable;
			}
		}
		#endregion
		#region CurrentScope
		private static Scope p_currentScope;
		public static Scope CurrentScope
		{
			get
			{
				return  p_currentScope;
			}
			set
			{
				p_currentScope = value;
			}
		}
		#endregion		
		#region GlobalScope
		private static AssemblyScope p_globalScope;
		public static AssemblyScope GlobalScope
		{
			get
			{
				return  p_globalScope;
			}
			set
			{
				p_globalScope = value;
			}
		}
		#endregion

		#region SymbolTable
		private static DefinitionCollection  p_symtab = new DefinitionCollection();
		/// <summary>
		/// Stores un-attributed symbols until all types/vars are declared.
		/// </summary>
		public static DefinitionCollection SymbolTable
		{
			get
			{
				return  p_symtab;
			}
		}
		#endregion		
		#region AddSymbol(Dom.ISymbol)
		/// <summary>
		/// Symbols are variables that refer to types, or type refs themselves.
		/// </summary>
		public void AddSymbol(Dom.ISymbolRef sgraph, string name)
		{
			IDefinition d = sgraph.Definition;
			if(d == null)
			{
				d = new Definition();
				sgraph.Definition = d;
				d.Id = defCount++;
			}
			if(d.Scope == null) d.Scope = CSharpAST.CurrentScope;
			d.SourceGraph = sgraph;
			d.Name = name;

			CSharpAST.SymbolTable.Add(d);
		}
		#endregion	
		#region ResolveSymbols()
		/// <summary>
		/// Attributes all the stored symbols - only call once all definitions are parsed. This will clear the symbol table once its contents are attributed.
		/// </summary>
		public bool ResolveSymbols()
		{
			bool isValid = true;
			foreach(Definition d in SymbolTable)
			{
				Scope defScope = d.Scope;
				if(d.SourceGraph is Dom.IScope) 
					defScope = d.Scope.EnclosingScope;

				if(d.SourceGraph is Dom.UnknownReference)
				{
					Definition resolved = defScope.Lookup(d.Name);

					if(resolved != null)
					{
						//d.Scope = resolved.Scope;
						Dom.UnknownReference ur = (Dom.UnknownReference)d.SourceGraph;
						ur.Definition = resolved;
						Console.WriteLine(resolved.FullName);
					}
					else
					{
						isValid = false;
						Console.WriteLine(
							d.SourceGraph.GraphType.ToString() + 
							" def **not** found: " + d.Name);
					}
				}
				else if(d.SourceGraph is Dom.TypeRef)
				{	
					Definition resolved = defScope.Lookup(d.Name);
					if(resolved != null)
					{
						// rewrite the def to be the looked up def
						Dom.TypeRef tr = (Dom.TypeRef)d.SourceGraph;
						tr.Definition = resolved;
						Console.WriteLine("TypeRef: " + resolved.FullName);
					}
					else
					{
						isValid = false;
						Console.WriteLine(
							d.SourceGraph.GraphType.ToString() + 
							" not found: " + d.Name);
					}				
				}
				else
				{
					isValid = false;
					Console.WriteLine("*** " + d.Name +" - not resolved: " + d.SourceGraph.GraphType.ToString());
				}
			}
			SymbolTable.Clear();
			return isValid;
		}
		#endregion
		
		#region AddRootExpression(Dom.Expression, Type, string)
		private static ExpressionRootCollection  rootExprs = new ExpressionRootCollection();
		/// <summary>
		/// Stores root expressions (right sides, args, etc) to make expr exprAttr quicker.
		/// </summary>
		public void AddRootExpression(Dom.Expression expr, Type t, string propName)
		{
			if(expr == null) return;
			ExpressionRoot er = new ExpressionRoot();
			er.Expression = expr;
			er.Instance = t;
			er.PropertyName = propName;
			CSharpAST.rootExprs.Add(er);
		}
		#endregion	
		#region ResolveExpressions()
		/// <summary>
		/// Determines all the return types of expressions, needed for resolving overloads.
		/// </summary>
		public void ResolveExpressions()
		{
			Attribution.AttributeExpressions(CSharpAST.rootExprs);
		}
		#endregion

		#region OpenBlockScope()
		public Scope OpenBlockScope()
		{
			Scope sc = new BlockScope();
			sc.EnclosingScope =  CSharpAST.CurrentScope;
			CSharpAST.ScopeTable.Add(sc);
			CSharpAST.CurrentScope = sc;
			return sc;
		}
		#endregion
		#region OpenScope(IScope)
		/// <summary>
		/// Creates a new scope and sets it as the current scope. This will also add a definition to the parent scope if needed (in case of eg Class or Namespace, but not eg block or compile unit).
		/// </summary>
		/// <param name="graph">The current graph element.</param>
		/// <returns>Returns a reference to the newly created scope.</returns>
		public Scope OpenScope(Dom.IScope graph)
		{
			switch(graph.GraphType)
			{			
				case Dom.GraphTypes.CompileUnit		:
				{
					// set scope table to current assembly's scope
					currentCompileUnit = (Dom.CompileUnit)graph;
					// add a new Assembly scope to it
					GlobalScope = new AssemblyScope();
					graph.Scope = GlobalScope;
					break;
				}
				case Dom.GraphTypes.NamespaceDecl	:
				{
					graph.Scope = new NamespaceScope();
					break;
				}
				case Dom.GraphTypes.ClassDecl		:
				case Dom.GraphTypes.InterfaceDecl	:
				case Dom.GraphTypes.StructDecl		:
				case Dom.GraphTypes.EnumDecl		:
				{
					graph.Scope = new TypeScope();
					break;
				}
				case Dom.GraphTypes.MethodDecl		:
				case Dom.GraphTypes.IndexerDecl		:
				case Dom.GraphTypes.OperatorDecl	:	
				case Dom.GraphTypes.ConstructorDecl	:
				case Dom.GraphTypes.DestructorDecl	:
				case Dom.GraphTypes.AccessorDecl	:
				{
					graph.Scope = new MemberScope();
					break;
				}
				default	:
				{
					throw(new Exception("uncaught scope type"));
					break;
				}
			}
			// set parent and (parent's) child refs
			graph.Scope.EnclosingScope = CSharpAST.CurrentScope;
			if(CSharpAST.CurrentScope != null)
			{
				CSharpAST.CurrentScope.ChildScopes.Add(graph.Scope);
			}
			// add defintion and link scope to its name, if needed
			if(graph is Dom.IDeclaration)
			{
				((INamedScope)graph.Scope).Definition = 
					((Dom.IDeclaration)graph).Definition;
				// only add def after name is known		
				// AddDefinition((Dom.IDeclaration)graph, );
			}
			// add to the main scope table storage area too
			CSharpAST.ScopeTable.Add(graph.Scope);
			// set this to be the current scope
			CSharpAST.CurrentScope = graph.Scope;
			return graph.Scope;
		}
		#endregion
		public static int defCount = 1;
		#region AddDefinition(IDeclaration)
		public IDefinition AddDefinition(Dom.IDeclaration dgraph, string name, Dom.IDeclaration type)
		{
			dgraph.Definition.Scope = CSharpAST.CurrentScope;
			dgraph.Definition.SourceGraph = dgraph;
			dgraph.Definition.Name = name;
			dgraph.Definition.Type = type;
			dgraph.Definition.Id = defCount++;

			// overloadable types are stored as a collection in one OverloadableDefinition
			// that is always created here
			if(dgraph is Dom.IOverloadable)
			{
				// enclosing scopes are never null for defs..
				Definition d = CSharpAST.CurrentScope.Lookup(name);
				// overloads are stored in a main 'overloadable' definition
				// that contains a 'Definitions' collection of each overloaded def.

				// FIX: it is possible that a variable and a method have the same name
				// so we must make sure the looked up def is actaully for a variable
				// * thank you Niklas Pettersson
				bool dov = d is OverloadableDefinition;
				if(d == null || !dov)
				{
					d = new OverloadableDefinition();
					d.Name = name;
					d.Scope = CSharpAST.CurrentScope;
					d.SourceGraph = dgraph;
					d.Id = defCount++;
					d.Type = type;
					CSharpAST.CurrentScope.EnclosingScope.Add(d, name);
				}
				// must always be overloadable def
                ((OverloadableDefinition)d).Definitions.Add(dgraph.Definition); 
			}
			else if(dgraph is Dom.IScope)
			{
				// all other scopes should also be registered in the enclosing scope
				CSharpAST.CurrentScope.EnclosingScope.Add(dgraph.Definition, name);
			}
			else
			{
				// and locals, agrs should be registered in the scope they are found in
				CSharpAST.CurrentScope.Add(dgraph.Definition, name);
			}
			return dgraph.Definition;
		}
		#endregion

		#region AddBuiltInDefinition(string)
		public IDefinition AddBuiltInDefinition(string name)
		{
			BuiltInDefinition bid = 
				(BuiltInDefinition)GlobalScope.DefinitionTable[name];
			if(bid == null)
			{
				// set the def now for built in types as it is a subclass of def
				bid = new BuiltInDefinition();
				bid.Name = name;
				// set type now as that is what is different
				// the rest will get attributed once added to symbol table
				bid.Scope = GlobalScope;
				bid.Id = CSharpAST.defCount++;
				// must add this to defs if it isn't there already
				// this allows us to keep track of which built in types were used
				// always add built in to global scope
				GlobalScope.DefinitionTable.Add(name, bid);
			}
			return bid;
		}
		#endregion

		#region CloseScope()
		public void CloseScope()
		{			
			CSharpAST.CurrentScope = CSharpAST.CurrentScope.EnclosingScope;
		}
		#endregion

	}
	#endregion 

	#region CompileUnit 
	public class				CompileUnit : CSharpAST
	{	
		public override Dom.IGraph		GetGraph()				
		{	
			Dom.CompileUnit graph = 
				new Dom.CompileUnit();
			return this.GetGraph(graph);
		}	
		public Dom.CompileUnit	
			GetGraph(Dom.CompileUnit graph)
		{	
			base.GetGraph(graph);
			this.OpenScope(graph);
			Dom.NamespaceDecl dns = null;

			graph.FileName = this.FileName;

			AST tok = this.getFirstChild();
			while(tok != null)
			{			
				if(tok is NamespaceNode) 
				{
					Dom.NamespaceDecl ns = 
						(Dom.NamespaceDecl)((NamespaceNode)tok).GetGraph();
					graph.Namespaces.Add(ns);
				}
				else if(tok is CustomAttributes) 
					((CustomAttributes)tok).GetGraph(graph.AssemblyCustomAttributes);
				else if(tok is UsingNode) 
					graph.Imports.Add( (Dom.Import)((UsingNode)tok).GetGraph() );
				else //if(tok is Types || tok is QualIdent) 
				{					
					if(dns == null)
					{
						dns = new Dom.NamespaceDecl();
						dns.Name = "DefaultNamespace";
						graph.Namespaces.Add(dns);
					}
					Types.ParseTypesIntoNamespace(tok, dns);
				}

				tok = tok.getNextSibling();
			}
			this.CloseScope();
			// do type attribution for declarations, localdecls and args
			graph.IsAttributed = ResolveSymbols();
			// do type attribution for expressions
			if(graph.IsAttributed) 
			{
				ResolveExpressions();
			}
			else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -