// Build a constructor expression. public static void BuildConstructor(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var ctor = new Constructor(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(ctor); // Interpret the declaration modifiers. InterpretModifiers(root, ctor, currentNode.ChildNodes[0]); // Interpret the arguments of the constructor. if (currentNode.ChildNodes[2].ChildNodes.Count > 0) { foreach (var n in currentNode.ChildNodes[2].ChildNodes) { BuildArgument(parser, ctor, n.ChildNodes[0]); } } // Build the "this" or "base" constructors called, if any. if(currentNode.ChildNodes[3].ChildNodes.Count > 0) { if(currentNode.ChildNodes[3].ChildNodes[0].ChildNodes[0].Term.ToString() == "this") { ctor.Sub = true; } foreach (var n in currentNode.ChildNodes[3].ChildNodes[0].ChildNodes[1].ChildNodes) { parser.ConsumeParseTree(root, ctor.SubParameters, n); } } // Build the expressions in the method body of the constructor. parser.ConsumeParseTree(root, ctor, currentNode.ChildNodes[4]); }
// Builds an argument for the constructor. public static void BuildArgument(IronyParser parser, Constructor method, ParseTreeNode node) { // Check for a directioned argument (out, ref). if (node.Term.ToString() == "out_parameter") { var a = new DirectionedParameter(null, node.FindToken().Convert()); switch (node.ChildNodes[0].ChildNodes[0].Term.ToString()) { case "ref": a.Direction = ParameterDirection.Ref; break; case "out": a.Direction = ParameterDirection.Out; break; } a.TypeName = parser.CheckAlias(node.ChildNodes[1].FindTokenAndGetText()); a.Name = node.ChildNodes[2].FindTokenAndGetText(); method.Parameters.Add(a); } else { // Build an undirectioned argument. var a = new SimpleParameter(null, node.FindToken().Convert()); a.TypeName = parser.CheckAlias(node.ChildNodes[0].FindTokenAndGetText()); a.Name = node.ChildNodes[1].FindTokenAndGetText(); method.Parameters.Add(a); } }
// Generates a codedom constructor expression and attaches it to the given type. public static void Emit(CodeTypeDeclaration codeTypeDeclaration, Constructor ctor) { // Create the codedom constructor var codeCtor = new CodeConstructor(); codeTypeDeclaration.Members.Add(codeCtor); // Translate accessibility of the constructor MemberAttributes memberAttributes = MemberAttributes.Public; switch (ctor.Accessibility) { case Accessibility.Internal: memberAttributes |= MemberAttributes.FamilyAndAssembly; break; case Accessibility.Private: memberAttributes |= MemberAttributes.Private; break; case Accessibility.Protected: memberAttributes |= MemberAttributes.Family; break; case Accessibility.Public: memberAttributes |= MemberAttributes.Public; break; } codeCtor.Attributes = memberAttributes; // Translate the parameters of the constructor foreach (Expression p in ctor.Parameters) { if (p is SimpleParameter) // ex "int i" codeCtor.Parameters.Add(new CodeParameterDeclarationExpression((p as SimpleParameter).TypeName, (p as SimpleParameter).Name)); if (p is DirectionedParameter) // ex "ref int i" { var codeParameter = new CodeParameterDeclarationExpression((p as DirectionedParameter).TypeName, (p as DirectionedParameter).Name); switch ((p as DirectionedParameter).Direction) { case ParameterDirection.Out: codeParameter.Direction = FieldDirection.Out; break; case ParameterDirection.Ref: codeParameter.Direction = FieldDirection.Ref; break; } codeCtor.Parameters.Add(codeParameter); } } // Add call to a constructor of the base class or another in the same class. foreach (var a in ctor.SubParameters.ChildExpressions) { if (ctor.Sub) codeCtor.ChainedConstructorArgs.Add(CodeDomEmitter.EmitCodeExpression(a)); else codeCtor.BaseConstructorArgs.Add(CodeDomEmitter.EmitCodeExpression(a)); } // Add all the statements in the body of the constructor foreach (var e in ctor.ChildExpressions) codeCtor.Statements.Add(CodeDomEmitter.EmitCodeStatement(e)); }
// Interpret the modifiers for the constructor declaration. static void InterpretModifiers(Root root, Constructor c, ParseTreeNode node) { bool foundPublic = false; bool foundInternal = false; bool foundPrivate = false; bool foundProtected = false; foreach (var modifierNode in node.ChildNodes) { string text = modifierNode.FindTokenAndGetText(); if (text == "public") { if (foundPublic || foundInternal || foundPrivate || foundProtected) { root.CompilerErrors.Add(new MultipleAccessModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.Accessibility = Accessibility.Public; foundPublic = true; } } if (text == "internal") { if (foundInternal || foundPublic || foundPrivate || foundProtected) { root.CompilerErrors.Add(new MultipleAccessModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.Accessibility = Accessibility.Internal; foundInternal = true; } } if (text == "protected") { if (foundInternal || foundPublic || foundPrivate || foundProtected) { root.CompilerErrors.Add(new MultipleAccessModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.Accessibility = Accessibility.Protected; foundProtected = true; } } if (text == "private") { if (foundInternal || foundPublic || foundPrivate || foundProtected) { root.CompilerErrors.Add(new MultipleAccessModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.Accessibility = Accessibility.Private; foundPrivate = true; } } } }