main.cs

来自「SharpDevelop2.0.0 c#开发免费工具」· CS 代码 · 共 495 行 · 第 1/2 页

CS
495
字号
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
//     <version>$Revision: 1080 $</version>
// </file>

using System;
using System.Collections.Generic;
using System.CodeDom;
using System.Diagnostics;
using System.Reflection;
using System.IO;
using NRefactoryASTGenerator.AST;

namespace NRefactoryASTGenerator
{
	class MainClass
	{
		public static void Main(string[] args)
		{
			string directory = "../../../Project/Src/Parser/AST/";
			string visitorsDir = "../../../Project/Src/Parser/Visitors/";
			Debug.WriteLine("AST Generator running...");
			if (!File.Exists(directory + "INode.cs")) {
				Debug.WriteLine("did not find output directory");
				return;
			}
			if (!File.Exists(visitorsDir + "IASTVisitor.cs")) {
				Debug.WriteLine("did not find visitor output directory");
				return;
			}
			
			List<Type> nodeTypes = new List<Type>();
			foreach (Type type in typeof(MainClass).Assembly.GetTypes()) {
				if (type.IsClass && typeof(INode).IsAssignableFrom(type)) {
					nodeTypes.Add(type);
				}
			}
			nodeTypes.Sort(delegate(Type a, Type b) { return a.Name.CompareTo(b.Name); });
			
			CodeCompileUnit ccu = new CodeCompileUnit();
			CodeNamespace cns = new CodeNamespace("ICSharpCode.NRefactory.Parser.AST");
			ccu.Namespaces.Add(cns);
			cns.Imports.Add(new CodeNamespaceImport("System"));
			cns.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
			cns.Imports.Add(new CodeNamespaceImport("System.Diagnostics"));
			cns.Imports.Add(new CodeNamespaceImport("System.Drawing"));
			foreach (Type type in nodeTypes) {
				if (type.GetCustomAttributes(typeof(CustomImplementationAttribute), false).Length == 0) {
					CodeTypeDeclaration ctd = new CodeTypeDeclaration(type.Name);
					if (type.IsAbstract) {
						ctd.TypeAttributes |= TypeAttributes.Abstract;
					}
					ctd.BaseTypes.Add(new CodeTypeReference(type.BaseType.Name));
					cns.Types.Add(ctd);
					
					ProcessType(type, ctd);
					
					foreach (object o in type.GetCustomAttributes(false)) {
						if (o is TypeImplementationModifierAttribute) {
							(o as TypeImplementationModifierAttribute).ModifyImplementation(cns, ctd, type);
						}
					}
					
					if (!type.IsAbstract) {
						CodeMemberMethod method = new CodeMemberMethod();
						method.Name = "AcceptVisitor";
						method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
						method.Parameters.Add(new CodeParameterDeclarationExpression("IAstVisitor", "visitor"));
						method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "data"));
						method.ReturnType = new CodeTypeReference(typeof(object));
						CodeExpression ex = new CodeVariableReferenceExpression("visitor");
						ex = new CodeMethodInvokeExpression(ex, "Visit",
						                                    new CodeThisReferenceExpression(),
						                                    new CodeVariableReferenceExpression("data"));
						method.Statements.Add(new CodeMethodReturnStatement(ex));
						ctd.Members.Add(method);
						
						method = new CodeMemberMethod();
						method.Name = "ToString";
						method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
						method.ReturnType = new CodeTypeReference(typeof(string));
						method.Statements.Add(new CodeMethodReturnStatement(CreateToString(type)));
						ctd.Members.Add(method);
					}
				}
			}
			
			System.CodeDom.Compiler.CodeGeneratorOptions settings = new System.CodeDom.Compiler.CodeGeneratorOptions();
			settings.IndentString = "\t";
			settings.VerbatimOrder = true;
			
			using (StringWriter writer = new StringWriter()) {
				new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromCompileUnit(ccu, writer, settings);
				File.WriteAllText(directory + "Generated.cs", writer.ToString());
			}
			
			ccu = new CodeCompileUnit();
			cns = new CodeNamespace("ICSharpCode.NRefactory.Parser");
			ccu.Namespaces.Add(cns);
			cns.Imports.Add(new CodeNamespaceImport("System"));
			cns.Imports.Add(new CodeNamespaceImport("ICSharpCode.NRefactory.Parser.AST"));
			cns.Types.Add(CreateAstVisitorInterface(nodeTypes));
			
			using (StringWriter writer = new StringWriter()) {
				new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromCompileUnit(ccu, writer, settings);
				File.WriteAllText(visitorsDir + "IAstVisitor.cs", writer.ToString());
			}
			
			ccu = new CodeCompileUnit();
			cns = new CodeNamespace("ICSharpCode.NRefactory.Parser");
			ccu.Namespaces.Add(cns);
			cns.Imports.Add(new CodeNamespaceImport("System"));
			cns.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
			cns.Imports.Add(new CodeNamespaceImport("System.Diagnostics"));
			cns.Imports.Add(new CodeNamespaceImport("ICSharpCode.NRefactory.Parser.AST"));
			cns.Types.Add(CreateAstVisitorClass(nodeTypes, false));
			
			using (StringWriter writer = new StringWriter()) {
				new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromCompileUnit(ccu, writer, settings);
				File.WriteAllText(visitorsDir + "AbstractAstVisitor.cs", writer.ToString());
			}
			
			ccu = new CodeCompileUnit();
			cns = new CodeNamespace("ICSharpCode.NRefactory.Parser");
			ccu.Namespaces.Add(cns);
			cns.Imports.Add(new CodeNamespaceImport("System"));
			cns.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
			cns.Imports.Add(new CodeNamespaceImport("System.Diagnostics"));
			cns.Imports.Add(new CodeNamespaceImport("ICSharpCode.NRefactory.Parser.AST"));
			cns.Types.Add(CreateAstVisitorClass(nodeTypes, true));
			
			using (StringWriter writer = new StringWriter()) {
				new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromCompileUnit(ccu, writer, settings);
				File.WriteAllText(visitorsDir + "AbstractAstTransformer.cs", writer.ToString());
			}
		}
		
		static CodeTypeDeclaration CreateAstVisitorInterface(List<Type> nodeTypes)
		{
			CodeTypeDeclaration td = new CodeTypeDeclaration("IAstVisitor");
			td.IsInterface = true;
			
			foreach (Type t in nodeTypes) {
				if (!t.IsAbstract) {
					CodeMemberMethod m = new CodeMemberMethod();
					m.Name = "Visit";
					m.ReturnType = new CodeTypeReference(typeof(object));
					m.Parameters.Add(new CodeParameterDeclarationExpression(ConvertType(t), GetFieldName(t.Name)));
					m.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(object)), "data"));
					td.Members.Add(m);
				}
			}
			return td;
		}
		
		static CodeTypeDeclaration CreateAstVisitorClass(List<Type> nodeTypes, bool transformer)
		{
			CodeTypeDeclaration td = new CodeTypeDeclaration(transformer ? "AbstractAstTransformer" : "AbstractAstVisitor");
			td.TypeAttributes = TypeAttributes.Public | TypeAttributes.Abstract;
			td.BaseTypes.Add(new CodeTypeReference("IAstVisitor"));
			
			if (transformer) {
				string comment = "<summary>\n " +
					"The AbstractAstTransformer will iterate through the whole AST,\n " +
					"just like the AbstractAstVisitor. However, the AbstractAstTransformer allows\n " +
					"you to modify the AST at the same time: It does not use 'foreach' internally,\n " +
					"so you can add members to collections of parents of the current node (but\n " +
					"you cannot insert or delete items as that will make the index used invalid).\n " +
					"You can use the methods ReplaceCurrentNode and RemoveCurrentNode to replace\n " +
					"or remove the current node, totally independent from the type of the parent node.\n " +
					"</summary>";
				td.Comments.Add(new CodeCommentStatement(comment, true));
				
				CodeMemberField field = new CodeMemberField("Stack", "nodeStack");
				field.Type.TypeArguments.Add("INode");
				field.InitExpression = new CodeObjectCreateExpression(field.Type);
				td.Members.Add(field);
				
				CodeExpression nodeStack = new CodeVariableReferenceExpression("nodeStack");
				
				/*
				CodeMemberProperty p = new CodeMemberProperty();
				p.Name = "CurrentNode";
				p.Type = new CodeTypeReference("INode");
				p.Attributes = MemberAttributes.Public | MemberAttributes.Final;
				p.GetStatements.Add(new CodeMethodReturnStatement(new CodeVariableReferenceExpression("currentNode")));
				p.SetStatements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("currentNode"),
				                                            new CodePropertySetValueReferenceExpression()));
				td.Members.Add(p);
				 */
				
				CodeMemberMethod m = new CodeMemberMethod();
				m.Name = "ReplaceCurrentNode";
				m.Attributes = MemberAttributes.Public | MemberAttributes.Final;
				m.Parameters.Add(new CodeParameterDeclarationExpression("INode", "newNode"));
				m.Statements.Add(new CodeMethodInvokeExpression(nodeStack, "Pop"));
				m.Statements.Add(new CodeMethodInvokeExpression(nodeStack, "Push",
				                                                new CodeVariableReferenceExpression("newNode")));
				td.Members.Add(m);
				
				m = new CodeMemberMethod();
				m.Name = "RemoveCurrentNode";
				m.Attributes = MemberAttributes.Public | MemberAttributes.Final;
				m.Statements.Add(new CodeMethodInvokeExpression(nodeStack, "Pop"));
				m.Statements.Add(new CodeMethodInvokeExpression(nodeStack, "Push",
				                                                new CodePrimitiveExpression(null)));
				td.Members.Add(m);
			}
			
			foreach (Type type in nodeTypes) {
				if (!type.IsAbstract) {
					CodeMemberMethod m = new CodeMemberMethod();
					m.Name = "Visit";
					m.Attributes = MemberAttributes.Public;
					m.ReturnType = new CodeTypeReference(typeof(object));
					m.Parameters.Add(new CodeParameterDeclarationExpression(ConvertType(type), GetFieldName(type.Name)));
					m.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(object)), "data"));
					td.Members.Add(m);
					
					List<CodeStatement> assertions = new List<CodeStatement>();
					CodeVariableReferenceExpression var = new CodeVariableReferenceExpression(GetFieldName(type.Name));
					assertions.Add(AssertIsNotNull(var));
					
					AddFieldVisitCode(m, type, var, assertions, transformer);
					
					if (type.GetCustomAttributes(typeof(HasChildrenAttribute), true).Length > 0) {
						if (transformer) {
							m.Statements.Add(new CodeSnippetStatement(CreateTransformerLoop(var.VariableName + ".Children", "INode")));
							m.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(null)));
						} else {
							CodeExpression ex = new CodeMethodInvokeExpression(var, "AcceptChildren",
							                                                   new CodeThisReferenceExpression(),
							                                                   new CodeVariableReferenceExpression("data"));
							m.Statements.Add(new CodeMethodReturnStatement(ex));
						}
					} else {
						CodeExpressionStatement lastStatement = null;
						if (m.Statements.Count > 0) {
							lastStatement = m.Statements[m.Statements.Count - 1] as CodeExpressionStatement;
						}
						if (lastStatement != null) {
							m.Statements.RemoveAt(m.Statements.Count - 1);
							m.Statements.Add(new CodeMethodReturnStatement(lastStatement.Expression));
						} else {
							m.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(null)));
						}

⌨️ 快捷键说明

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