示例#1
0
        public string Generate(List <AphidExpression> nodes, string code)
        {
            ParseDirectives(nodes);
            var lexer = GenerateLexer(nodes, code);

            ParseRuleStructs(nodes);
            nodes = new PlusEqualMutator().MutateRecursively(nodes);
            var rules = GetRules(nodes);

            _ruleNames = GetRuleNames(nodes).ToArray();
            var mutator = new TypeInferenceMutator(_config);

            foreach (var r in rules)
            {
                nodes.Remove(r);
            }

            do
            {
                rules = rules
                        .Select(x => new BinaryOperatorExpression(
                                    x.LeftOperand,
                                    x.Operator,
                                    new FunctionExpression(
                                        x.RightOperand.ToFunction().Args,
                                        mutator.MutateRecursively(x.RightOperand.ToFunction().Body))))
                        .ToArray();
            }while (mutator.HasMutated);

            nodes.AddRange(rules);
            var declMutator = new DeclarativeStatementMutator(_tokenTypes, _ruleNames);

            nodes = declMutator.Mutate(nodes);
            nodes = AddIndexTracking(nodes);
            var ruleTypeBuilder = new RuleTypeBuilder(_config, _ruleTypes.Select(x => x.Value));
            var typeClasses     = ruleTypeBuilder.CreateRuleTypeClasses();
            var enumBuilder     = new EnumBuilder(_config.BaseClass, _ruleTypes.Select(x => x.Key));
            var enumDecl        = enumBuilder.CreateEnum();

            var ns = new CodeNamespace(
                string.Join(".", _config.Namespace.Concat(new[] { ParserName.Parser })));

            ns.Imports.Add(new CodeNamespaceImport(
                               string.Join(".", _config.Namespace.Concat(new[] { ParserName.Lexer }))));

            ns.Imports.Add(new CodeNamespaceImport("System.Linq"));
            ns.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
            ns.Types.Add(enumDecl);
            ns.Types.AddRange(typeClasses);

            var parserType = new CodeTypeDeclaration(_config.ParserClass)
            {
                IsPartial = true
            };

            parserType.Members.Add(GenerateContextField());
            parserType.Members.AddRange(nodes.Select(Generate).Where(x => x != null).ToArray());
            ns.Types.Add(parserType);

            var str = CSharpHelper.GenerateCode(ns);

            return(str + "\r\n\r\n" + lexer);
        }
        public Type BuildType(string typeName)
        {
            var nameTable = _sourcePropertyTable.Value;

            var type2 = new CodeTypeDeclaration(typeName)
            {
                CustomAttributes = new CodeAttributeDeclarationCollection(
                    new[] { new CodeAttributeDeclaration(CodeHelper.TypeRef <SerializableAttribute>()) })
            };

            var fields = nameTable
                         .ToDictionary(
                x => x.Key,
                x => new CodeMemberField(x.Value.PropertyType, string.Format("_autoField_{0}", x.Key)));

            var props = nameTable
                        .Select(x => new CodeMemberProperty
            {
                Attributes       = MemberAttributes.Public,
                Type             = CodeHelper.TypeRef(x.Value.PropertyType),
                Name             = x.Key,
                HasGet           = true,
                HasSet           = true,
                CustomAttributes = new CodeAttributeDeclarationCollection(
                    new[] { new CodeAttributeDeclaration(CodeHelper.TypeRef <TAttribute>()) })
            })
                        .ToArray();

            foreach (var p in props)
            {
                var field = CodeHelper.FieldRef(fields[p.Name].Name);
                p.GetStatements.Add(CodeHelper.Return(field));
                p.SetStatements.Add(CodeHelper.Assign(field, CodeHelper.VarRef("value")));
            }

            type2.Members.AddRange(fields.Select(x => x.Value).ToArray());
            type2.Members.AddRange(props);

            var code = CSharpHelper.GenerateCode(type2);

            using (var provider = new CSharpCodeProvider())
            {
                var options = new CompilerParameters
                {
                    GenerateExecutable = false,
                    GenerateInMemory   = true,
                };

                var references = nameTable
                                 .Select(x => x.Value.PropertyType.Assembly.Location)
                                 .Concat(new[] { typeof(SerializableAttribute), typeof(TAttribute) }
                                         .Select(x => x.Assembly.Location))
                                 .Distinct()
                                 .ToArray();

                options.ReferencedAssemblies.AddRange(references);

                var results = provider.CompileAssemblyFromSource(options, code);

                return(results.CompiledAssembly.GetType(typeName));
            }
        }