예제 #1
0
        private static CodeStatement[] CreateConstructorAssignmentStatements(
            RuleStruct rule,
            CodeMemberProperty property)
        {
            var paramName  = GetLocalName(property.Name);
            var fieldName  = GetFieldName(property.Name);
            var assignStmt = Assign(fieldName, paramName);
            var stmts      = new List <CodeStatement>();

            if (property.Type.BaseType != typeof(List <>).FullName || !IsOptional(rule, property))
            {
                stmts.Add(assignStmt);
            }
            else
            {
                stmts.Add(
                    new CodeConditionStatement(
                        BinOpExp(
                            VarRef(paramName),
                            CodeBinaryOperatorType.IdentityInequality,
                            Null()),
                        new[] { assignStmt },
                        new[]
                {
                    Assign(
                        fieldName,
                        new CodeObjectCreateExpression(property.Type))
                }));
            }

            return(stmts.ToArray());
        }
예제 #2
0
        private CodeTypeDeclaration CreateCodeType(RuleStruct rule)
        {
            var decl = CreateType(rule.Name);

            decl.BaseTypes.Add(TypeRef(rule.BaseName));
            var properties = CreateProperties(rule);

            decl.Members.AddRange(properties);
            decl.Members.AddRange(CreateFields(properties));
            var publicCtor = CreateConstructor(rule, properties, isInternal: false);

            decl.Members.Add(publicCtor);
            decl.Members.Add(CreateConstructor(rule, properties, isInternal: true));

            if (publicCtor.Parameters.Count != 0)
            {
                decl.Members.Add(new CodeConstructor {
                    Attributes = MemberAttributes.Private
                });
            }

            AddGetChildrenMethod(rule, decl);
            AddTypeProperty(rule, decl);

            return(decl);
        }
예제 #3
0
        private void AddTypeProperty(RuleStruct rule, CodeTypeDeclaration decl)
        {
            var enumType = _baseTypeName + "Type";

            var prop = new CodeMemberProperty
            {
                Attributes = MemberAttributes.Public |
                             MemberAttributes.Override,
                Type = TypeRef(enumType),
                Name = "Type"
            };

            prop.GetStatements.Add(Return(PropRef(enumType, rule.Name)));
            decl.Members.Add(prop);
        }
예제 #4
0
        private CodeParameterDeclarationExpression CreateConstructorParameter(
            RuleStruct rule,
            CodeMemberProperty property)
        {
            var exp = new CodeParameterDeclarationExpression(
                property.Type,
                GetLocalName(property.Name));

            if (IsOptional(rule, property))
            {
                exp.CustomAttributes.Add(
                    new CodeAttributeDeclaration(TypeRef <OptionalAttribute>()));
            }

            return(exp);
        }
예제 #5
0
        public CodeTypeDeclaration CreateCodeType(RuleStruct rule)
        {
            // Todo: extract code helper methods from this bullshit
            var decl = new CodeTypeDeclaration(rule.Name)
            {
                IsPartial = true,
            };

            decl.BaseTypes.Add(CodeHelper.TypeRef(rule.BaseName));

            var properties = CreateProperties(rule);

            foreach (var p in properties)
            {
                p.GetStatements.Add(CodeHelper.Return(GetFieldName(p.Name)));
            }

            decl.Members.AddRange(properties);

            decl.Members.AddRange(
                properties
                    .Select(x => new CodeMemberField(x.Type, GetFieldName(x.Name))
                    {
                        Attributes = MemberAttributes.Private,
                    })
                    .ToArray());

            var ctor = new CodeConstructor()
            {
                Attributes = MemberAttributes.Public,
            };

            ctor.Parameters.AddRange(
                properties
                    .Select(x => CreateCtorParameter(rule, x))
                    .ToArray());

            ctor.Statements.AddRange(
                properties
                    .Select(x => CodeHelper.Assign(GetFieldName(x.Name), GetLocalName(x.Name)))
                    .ToArray());

            decl.Members.Add(ctor);

            return decl;
        }
예제 #6
0
        private CodeConstructor CreateConstructor(
            RuleStruct rule,
            CodeMemberProperty[] properties,
            bool isInternal)
        {
            var ctor = new CodeConstructor
            {
                Attributes = !isInternal ?
                             MemberAttributes.Public :
                             MemberAttributes.Assembly
            };

            if (isInternal)
            {
                ctor.Parameters.Add(
                    new CodeParameterDeclarationExpression(
                        TypeRef(_config.ExpressionContextClass),
                        ParserName.ContextParam));

                ctor.Statements.Add(
                    Assign(
                        ParserName.ContextProperty,
                        ParserName.ContextParam));
            }
            else
            {
                ctor.Statements.Add(
                    Assign(
                        ParserName.ContextProperty,
                        New(TypeRef(_config.ExpressionContextClass))));
            }

            ctor.Parameters.AddRange(
                properties
                .Select(x => CreateConstructorParameter(rule, x))
                .ToArray());

            ctor.Statements.AddRange(
                properties
                .SelectMany(x => CreateConstructorAssignmentStatements(rule, x))
                .ToArray());

            return(ctor);
        }
예제 #7
0
        private static CodeMemberProperty[] CreateProperties(RuleStruct ruleType)
        {
            var isMutable = ParserGeneratorConfig.Current.IsAstMutable;

            var properties = ruleType.Properties
                             .Select(x => new CodeMemberProperty
            {
                Name             = x.Name,
                Attributes       = MemberAttributes.Public | MemberAttributes.Final,
                Type             = ParserCode.GetTypeRef(x),
                HasGet           = true,
                HasSet           = isMutable,
                CustomAttributes = new CodeAttributeDeclarationCollection(
                    new[]
                {
                    new CodeAttributeDeclaration(
                        TypeRef <DataMemberAttribute>())
                })
            })
                             .ToArray();

            foreach (var p in properties)
            {
                p.GetStatements.Add(Return(GetFieldName(p.Name)));

                if (isMutable)
                {
                    p.SetStatements.Add(
                        Assign(
                            GetFieldName(p.Name),
                            VarRef("value")));
                }
            }

            return(properties);
        }
예제 #8
0
 private static bool IsOptional(RuleStruct rule, CodeMemberProperty property) =>
 rule.Properties.Single(x => x.Name == property.Name).IsOptional;
예제 #9
0
        private void AddGetChildrenMethod(RuleStruct rule, CodeTypeDeclaration decl)
        {
            if (!rule.Properties.Any(x => _resolver.Is(x.Type, _baseTypeName)))
            {
                return;
            }

            decl.BaseTypes.Add("IParentNode");

            var children = rule.Properties
                           .Where(x => _resolver.Is(x.Type, _baseTypeName))
                           .ToArray();

            var scalarChildren = children
                                 .Where(x => !x.IsList)
                                 .Select(x => VarRef(x.Name))
                                 .ToArray();;

            CodeExpression childExpression = scalarChildren.Length > 0 ?
                                             new CodeArrayCreateExpression(_baseTypeName, scalarChildren) :
                                             null;

            var hasLists = false;

            foreach (var child in children.Where(x => x.IsList))
            {
                hasLists = true;
                CodeExpression childRef = VarRef(child.Name);

                if (childExpression != null)
                {
                    var target = childExpression is CodeArrayCreateExpression ?
                                 childExpression :
                                 Invoke(childExpression, "OfType", new[] { _baseTypeName });

                    childRef = Invoke(
                        TypeRefExp(_helperName),
                        _getCollection,
                        childRef);

                    childExpression = Invoke(target, "Concat", childRef);
                }
                else
                {
                    childExpression = childRef;
                }
            }

            if (hasLists)
            {
                childExpression = Invoke(childExpression, "ToArray");
            }

            var method = new CodeMemberMethod
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Final,
                Name       = "GetChildren",
                ReturnType = new CodeTypeReference("IEnumerable", TypeRef(_baseTypeName))
            };

            method.Statements.Add(Return(childExpression));
            decl.Members.Add(method);
        }
예제 #10
0
 private CodeMemberProperty[] CreateProperties(RuleStruct ruleType)
 {
     return ruleType.Properties
         .Select(x => new CodeMemberProperty()
         {
             Name = x.Name,
             Attributes = MemberAttributes.Public | MemberAttributes.Final,
             Type = GetTypeRef(x),
             HasGet = true,
         })
         .ToArray();
 }
예제 #11
0
        private CodeParameterDeclarationExpression CreateCtorParameter(RuleStruct rule, CodeMemberProperty property)
        {
            var exp = new CodeParameterDeclarationExpression(
                property.Type,
                GetLocalName(property.Name));

            if (rule.Properties.Single(x => x.Name == property.Name).IsOptional)
            {
                exp.CustomAttributes.Add(new CodeAttributeDeclaration(CodeHelper.TypeRef<OptionalAttribute>()));
            }

            return exp;
        }