// Build a try-catch-finally statement public static void BuildExceptionHandler(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var ex = new ExceptionHandler(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(ex); // Build the contents of the try block parser.ConsumeParseTree(root, ex.Try, currentNode.ChildNodes[0]); // Build each case block. if (currentNode.ChildNodes[1].ChildNodes.Count > 0) { foreach (var node in currentNode.ChildNodes[1].ChildNodes) { var c = new CatchClause(ex, node.Token.Convert()); c.Type = node.ChildNodes[1].FindTokenAndGetText(); c.Name = node.ChildNodes[2].FindTokenAndGetText(); ex.CatchClauses.Add(c); parser.ConsumeParseTree(root, c, node.ChildNodes[3]); } } // Build the finally block. parser.ConsumeParseTree(root, ex.Finally, currentNode.ChildNodes[2]); }
// 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]); }
// Build an instantiation expression "new foo()" public static void BuildInstantiation(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var ist = new Instantiation(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(ist); // A non-array instantiation if (currentNode.ChildNodes[1].ChildNodes[0].Term.ToString() == "new_instantiate") { ist.Name = parser.CheckAlias(currentNode.ChildNodes[1].ChildNodes[0].FindTokenAndGetText()); if (currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[1].ChildNodes.Count > 0) { foreach (var n in currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[1].ChildNodes) { ist.GenericTypes.Add(parser.CheckAlias(n.FindTokenAndGetText())); } } foreach (var n in currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[2].ChildNodes) { parser.ConsumeParseTree(root, ist.Parameters, n); } } else // An array instantiation { ist.IsArray = true; ist.Name = parser.CheckAlias(currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[0].FindTokenAndGetText()); parser.ConsumeParseTree(root, ist.Parameters, currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[2]); } }
// Build an instantiation expression "new foo()" public static void BuildInstantiation(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var ist = new Instantiation(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(ist); // A non-array instantiation if (currentNode.ChildNodes[1].ChildNodes[0].Term.ToString() == "new_instantiate") { ist.Name = parser.CheckAlias(currentNode.ChildNodes[1].ChildNodes[0].FindTokenAndGetText()); if (currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[1].ChildNodes.Count > 0) foreach (var n in currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[1].ChildNodes) { ist.GenericTypes.Add(parser.CheckAlias(n.FindTokenAndGetText())); } foreach (var n in currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[2].ChildNodes) { parser.ConsumeParseTree(root, ist.Parameters, n); } } else // An array instantiation { ist.IsArray = true; ist.Name = parser.CheckAlias(currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[0].FindTokenAndGetText()); parser.ConsumeParseTree(root, ist.Parameters, currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[2]); } }
// 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]); }
// Build property declaration statement public static void BuildProperty(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var property = new Property(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(property); // If the parent is a module, make the property shared var c = parentExpression as Class; if (c.IsModule) { property.IsShared = true; } // Interpret the modifiers for the property declaration InterpretModifiers(root, property, currentNode.ChildNodes[0].ChildNodes[0]); // Check for conflicting/invalid property modifiers if (property.IsShared && (property.IsFinal || property.IsOverride)) { root.CompilerErrors.Add(new IncompatibleModifiersCompilerError("", currentNode.FindToken().Location.Line, currentNode.FindToken().Location.Position)); } // Find the return type for the property: check if it's generic or an array var typeNode = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0]; if (typeNode.ChildNodes[0].Term.ToString() == "array") { property.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); property.TypeName = parser.CheckAlias(typeNode.ChildNodes[0].ChildNodes[0].FindTokenAndGetText()) + "[]"; } else if (typeNode.ChildNodes[0].Term.ToString() == "generic_identifier") { property.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); property.TypeName = typeNode.ChildNodes[0].ChildNodes[0].FindTokenAndGetText() + "<"; for (int i = 0; i < typeNode.ChildNodes[0].ChildNodes[2].ChildNodes.Count; i++) { property.TypeName += typeNode.ChildNodes[0].ChildNodes[2].ChildNodes[i].FindTokenAndGetText(); if (i < typeNode.ChildNodes[0].ChildNodes[2].ChildNodes.Count - 1) { property.TypeName += ","; } } property.TypeName += ">"; } else { property.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); property.TypeName = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].FindTokenAndGetText()); } // Build the get block for the property parser.ConsumeParseTree(root, property.GetBlock, currentNode.ChildNodes[1]); // Build the set block for the property parser.ConsumeParseTree(root, property.SetBlock, currentNode.ChildNodes[2]); }
// Build a while loop statement (a for loop with just the conditional) public static void BuildWhileLoop(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var whileLoop = new WhileLoop(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(whileLoop); // Build the conditional expressoin parser.ConsumeParseTree(root, whileLoop.Condition, currentNode.ChildNodes[1]); // Build the statements that make up the body of the while loop parser.ConsumeParseTree(root, whileLoop, currentNode.ChildNodes[2]); }
// Build a case block statement public static void BuildCaseBlock(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var caseBlock = new CaseBlock(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(caseBlock); // Get the expression being tested against parser.ConsumeParseTree(root, caseBlock.Variable, currentNode.ChildNodes[1]); // Build the expressions in the body of the case block foreach (var e in currentNode.ChildNodes[2].ChildNodes) parser.ConsumeParseTree(root, caseBlock, e); }
// Build property declaration statement public static void BuildProperty(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var property = new Property(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(property); // If the parent is a module, make the property shared var c = parentExpression as Class; if (c.IsModule) { property.IsShared = true; } // Interpret the modifiers for the property declaration InterpretModifiers(root, property, currentNode.ChildNodes[0].ChildNodes[0]); // Check for conflicting/invalid property modifiers if (property.IsShared && (property.IsFinal || property.IsOverride)) root.CompilerErrors.Add(new IncompatibleModifiersCompilerError("", currentNode.FindToken().Location.Line, currentNode.FindToken().Location.Position)); // Find the return type for the property: check if it's generic or an array var typeNode = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0]; if(typeNode.ChildNodes[0].Term.ToString() == "array") { property.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); property.TypeName = parser.CheckAlias(typeNode.ChildNodes[0].ChildNodes[0].FindTokenAndGetText()) + "[]"; } else if (typeNode.ChildNodes[0].Term.ToString() == "generic_identifier") { property.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); property.TypeName = typeNode.ChildNodes[0].ChildNodes[0].FindTokenAndGetText() + "<"; for(int i = 0; i < typeNode.ChildNodes[0].ChildNodes[2].ChildNodes.Count; i++) { property.TypeName += typeNode.ChildNodes[0].ChildNodes[2].ChildNodes[i].FindTokenAndGetText(); if (i < typeNode.ChildNodes[0].ChildNodes[2].ChildNodes.Count - 1) property.TypeName += ","; } property.TypeName += ">"; } else { property.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); property.TypeName = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].FindTokenAndGetText()); } // Build the get block for the property parser.ConsumeParseTree(root, property.GetBlock, currentNode.ChildNodes[1]); // Build the set block for the property parser.ConsumeParseTree(root, property.SetBlock, currentNode.ChildNodes[2]); }
// Build a case block statement public static void BuildCaseBlock(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var caseBlock = new CaseBlock(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(caseBlock); // Get the expression being tested against parser.ConsumeParseTree(root, caseBlock.Variable, currentNode.ChildNodes[1]); // Build the expressions in the body of the case block foreach (var e in currentNode.ChildNodes[2].ChildNodes) { parser.ConsumeParseTree(root, caseBlock, e); } }
// Build a method invocation with generic type names public static void BuildGenericMethodInvocation(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var methodInvocation = new MethodInvocation(parentExpression, currentNode.FindToken().Convert()); methodInvocation.Name = currentNode.ChildNodes[0].FindTokenAndGetText(); parentExpression.ChildExpressions.Add(methodInvocation); methodInvocation.ParentExpression = parentExpression; // Interpret the generic type names if (currentNode.ChildNodes[2].ChildNodes.Count > 0) { foreach (var n in currentNode.ChildNodes[2].ChildNodes) { methodInvocation.GenericTypes.Add(n.FindTokenAndGetText()); } } // interpret the expressions that are passed to the invocation as arguments if (currentNode.ChildNodes[4].ChildNodes.Count > 0) { foreach (var n in currentNode.ChildNodes[1].ChildNodes) { parser.ConsumeParseTree(root, methodInvocation.Parameters, n); } } }
// Builds a "class" expression: really could be a class, struct, or module. public static void BuildClass(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { Class c = new Class(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(c); int i = 0; // Interpret the declaration modifiers (abstract, public, internal, etc). InterpretClassModifiers( root, c, currentNode.ChildNodes[i]); i++; // Determine if it's a class, module, or struct. switch(currentNode.ChildNodes[i].Term.ToString()) { case "module": c.IsModule = true; c.IsFinal = true; c.IsPartial = true; break; case "struct": c.IsStruct = true; c.IsModule = false; break; default: c.IsStruct = false; c.IsModule = false; break; } i++; // Class name c.UnqualifiedName = currentNode.ChildNodes[i].FindTokenAndGetText(); i++; // Get the generic type list. if (currentNode.ChildNodes[i].ChildNodes.Count > 0) { var generics = currentNode.ChildNodes[i].ChildNodes[0].ChildNodes[1]; foreach (string s in IronyParser.InterpretList(generics)) c.GenericTypeNames.Add(s); } i++; // Get the base type list. if (currentNode.ChildNodes[i].ChildNodes.Count > 0) { var baseTypes = currentNode.ChildNodes[i].ChildNodes[0].ChildNodes[0]; foreach (string s in IronyParser.InterpretList(baseTypes)) c.BaseTypeNames.Add(s); } i+=1; // Build the child expressions of the class. parser.ConsumeParseTree(root, c, currentNode.ChildNodes[i]); }
// Build an indexed identifier expression (foo[0]) public static void BuildIndexedIdentifier(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var indexedIdentifier = new IndexedIdentifier(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(indexedIdentifier); indexedIdentifier.Name = currentNode.ChildNodes[0].FindTokenAndGetText(); parser.ConsumeParseTree(root, indexedIdentifier, currentNode.ChildNodes[2]); }
// Build a namespace expression public static void BuildNamespace(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { Namespace n = new Namespace(parentExpression, currentNode.FindToken().Convert()); n.Name = currentNode.ChildNodes[1].FindTokenAndGetText(); parentExpression.ChildExpressions.Add(n); parser.ConsumeParseTree(root, n, currentNode.ChildNodes[2]); }
// Build a throw expression public static void BuildThrow(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { Throw e = new Throw(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(e); e.ParentExpression = parentExpression; parser.ConsumeParseTree(root, e, currentNode.ChildNodes[1]); }
// Build an assignment statement: i = 0, i += 1, i |= foo, etc public static void BuildAssignment(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var assignment = new Assignment(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(assignment); // Get the expression being assigned to parser.ConsumeParseTree(root, assignment, currentNode.ChildNodes[0]); // Determine what kind of assignment this is switch (currentNode.ChildNodes[1].FindTokenAndGetText()) { case "=": assignment.AssignmentType = AssignmentType.Equal; break; case "+=": assignment.AssignmentType = AssignmentType.Add; break; case "-=": assignment.AssignmentType = AssignmentType.Subtract; break; case "*=": assignment.AssignmentType = AssignmentType.Multiply; break; case "/=": assignment.AssignmentType = AssignmentType.Divide; break; case "|=": assignment.AssignmentType = AssignmentType.Or; break; case "&=": assignment.AssignmentType = AssignmentType.And; break; } // Get the value being assigned. parser.ConsumeParseTree(root, assignment, currentNode.ChildNodes[2]); }
// Build an if conditional statement. public static void BuildIfBlock(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var i = new IfBlock(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(i); int c = 1; // Build the conditional expression parser.ConsumeParseTree(root, i.Conditional, currentNode.ChildNodes[c]); c++; // Build the true block parser.ConsumeParseTree(root, i.TrueBlock, currentNode.ChildNodes[c]); c++; // Build the false block if one exists. if(currentNode.ChildNodes[c].ChildNodes.Count != 0) parser.ConsumeParseTree(root, i.FalseBlock, currentNode.ChildNodes[c]); }
// Build a switch block statement public static void BuildSwitchBlock(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var s = new SwitchBlock(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(s); // Get the expression being tested parser.ConsumeParseTree(root, s.Variable, currentNode.ChildNodes[1]); // Build each case block if(currentNode.ChildNodes[2].ChildNodes.Count > 0) foreach(var node in currentNode.ChildNodes[2].ChildNodes[0].ChildNodes) BuildCaseBlock(parser, root, s, node); }
// Build an assignment statement: i = 0, i += 1, i |= foo, etc public static void BuildAssignment(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var assignment = new Assignment(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(assignment); // Get the expression being assigned to parser.ConsumeParseTree(root, assignment, currentNode.ChildNodes[0]); // Determine what kind of assignment this is switch(currentNode.ChildNodes[1].FindTokenAndGetText()) { case "=": assignment.AssignmentType = AssignmentType.Equal; break; case "+=": assignment.AssignmentType = AssignmentType.Add; break; case "-=": assignment.AssignmentType = AssignmentType.Subtract; break; case "*=": assignment.AssignmentType = AssignmentType.Multiply; break; case "/=": assignment.AssignmentType = AssignmentType.Divide; break; case "|=": assignment.AssignmentType = AssignmentType.Or; break; case "&=": assignment.AssignmentType = AssignmentType.And; break; } // Get the value being assigned. parser.ConsumeParseTree(root, assignment, currentNode.ChildNodes[2]); }
// Build an if conditional statement. public static void BuildIfBlock(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var i = new IfBlock(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(i); int c = 1; // Build the conditional expression parser.ConsumeParseTree(root, i.Conditional, currentNode.ChildNodes[c]); c++; // Build the true block parser.ConsumeParseTree(root, i.TrueBlock, currentNode.ChildNodes[c]); c++; // Build the false block if one exists. if (currentNode.ChildNodes[c].ChildNodes.Count != 0) { parser.ConsumeParseTree(root, i.FalseBlock, currentNode.ChildNodes[c]); } }
// Build a method invocation statement (foo(1)) public static void BuildMethodInvocation(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var methodInvocation = new MethodInvocation(parentExpression, currentNode.FindToken().Convert()); methodInvocation.Name = currentNode.ChildNodes[0].FindTokenAndGetText(); parentExpression.ChildExpressions.Add(methodInvocation); // interpret the expressions that are passed to the invocation as arguments if (currentNode.ChildNodes[1].ChildNodes.Count > 0) { foreach (var n in currentNode.ChildNodes[1].ChildNodes) { parser.ConsumeParseTree(root, methodInvocation.Parameters, n); } } }
// Build an interface expression. public static void BuildInterface(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var inter = new Interface(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(inter); int i = 0; // Find modifiers for the declaration InterpretModifiers(root, inter, currentNode.ChildNodes[i]); i++; i++; // get interface name inter.UnqualifiedName = currentNode.ChildNodes[i].FindTokenAndGetText(); i++; // Build the generic type list if (currentNode.ChildNodes[i].ChildNodes.Count > 0) { var generics = currentNode.ChildNodes[i].ChildNodes[0].ChildNodes[1]; foreach (string s in IronyParser.InterpretList(generics)) { inter.GenericTypeNames.Add(s); } } i++; // Build the base type list. if (currentNode.ChildNodes[i].ChildNodes.Count > 0) { var baseTypes = currentNode.ChildNodes[i].ChildNodes[0].ChildNodes[0]; foreach (string s in IronyParser.InterpretList(baseTypes)) { inter.BaseTypeNames.Add(s); } } i += 1; // Build the children of the interface parser.ConsumeParseTree(root, inter, currentNode.ChildNodes[i]); }
public static void BuildUnaryOperator(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var op = new UnaryOperator(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(op); switch (currentNode.ChildNodes[0].FindTokenAndGetText()) { case "!": op.OperatorType = UnaryOperatorType.Not; break; case "-": op.OperatorType = UnaryOperatorType.Negate; break; } parser.ConsumeParseTree(root, op, currentNode.ChildNodes[1]); }
// Build a switch block statement public static void BuildSwitchBlock(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var s = new SwitchBlock(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(s); // Get the expression being tested parser.ConsumeParseTree(root, s.Variable, currentNode.ChildNodes[1]); // Build each case block if (currentNode.ChildNodes[2].ChildNodes.Count > 0) { foreach (var node in currentNode.ChildNodes[2].ChildNodes[0].ChildNodes) { BuildCaseBlock(parser, root, s, node); } } }
// Build a for loop statement. public static void BuildForLoop(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var loop = new ForLoop(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(loop); // Build the initializer expression for the loop. parser.ConsumeParseTree(root, loop.Initialization, currentNode.ChildNodes[1]); // Build the conditional expression for the loop. switch (currentNode.ChildNodes[3].ChildNodes[0].Term.ToString()) { case "for_range": parser.ConsumeParseTree(root, loop.Condition, currentNode.ChildNodes[3].ChildNodes[0].ChildNodes[0]); parser.ConsumeParseTree(root, loop.Condition, currentNode.ChildNodes[3].ChildNodes[0].ChildNodes[2]); break; default: parser.ConsumeParseTree(root, loop.Condition, currentNode.ChildNodes[3].ChildNodes[0]); break; } // Build the increment/decrement step expression for the loop. if (currentNode.ChildNodes[4].ChildNodes.Count > 0) { parser.ConsumeParseTree(root, loop.Step, currentNode.ChildNodes[4]); } else { var literal = new Literal(loop, null); literal.Value = 1; loop.Step.ChildExpressions.Add(literal); } // Form the body of the loop. if (currentNode.ChildNodes[5].ChildNodes.Count > 0) { parser.ConsumeParseTree(root, loop, currentNode.ChildNodes[5]); } }
// Build a for loop statement. public static void BuildForLoop(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var loop = new ForLoop(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(loop); // Build the initializer expression for the loop. parser.ConsumeParseTree(root, loop.Initialization, currentNode.ChildNodes[1]); // Build the conditional expression for the loop. switch(currentNode.ChildNodes[3].ChildNodes[0].Term.ToString()) { case "for_range": parser.ConsumeParseTree(root, loop.Condition, currentNode.ChildNodes[3].ChildNodes[0].ChildNodes[0]); parser.ConsumeParseTree(root, loop.Condition, currentNode.ChildNodes[3].ChildNodes[0].ChildNodes[2]); break; default: parser.ConsumeParseTree(root, loop.Condition, currentNode.ChildNodes[3].ChildNodes[0]); break; } // Build the increment/decrement step expression for the loop. if(currentNode.ChildNodes[4].ChildNodes.Count > 0) { parser.ConsumeParseTree(root, loop.Step, currentNode.ChildNodes[4]); } else { var literal = new Literal(loop, null); literal.Value = 1; loop.Step.ChildExpressions.Add(literal); } // Form the body of the loop. if(currentNode.ChildNodes[5].ChildNodes.Count > 0) { parser.ConsumeParseTree(root, loop, currentNode.ChildNodes[5]); } }
public static void BuildUnaryOperator(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var op = new UnaryOperator(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(op); switch(currentNode.ChildNodes[0].FindTokenAndGetText()) { case "!": op.OperatorType = UnaryOperatorType.Not; break; case "-": op.OperatorType = UnaryOperatorType.Negate; break; } parser.ConsumeParseTree(root, op, currentNode.ChildNodes[1]); }
// Build a binary operator statement public static void BuildBinaryOperator(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var op = new BinaryOperator(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(op); // Determine which binary operator this is switch (currentNode.ChildNodes[1].Term.ToString()) { case "*": op.OperatorType = BinaryOperatorType.Multiply; break; case "/": op.OperatorType = BinaryOperatorType.Divide; break; case "+": op.OperatorType = BinaryOperatorType.Add; break; case "-": op.OperatorType = BinaryOperatorType.Subtract; break; case "%": op.OperatorType = BinaryOperatorType.Modulo; break; case "<=": op.OperatorType = BinaryOperatorType.LessOrEqual; break; case "<": op.OperatorType = BinaryOperatorType.Less; break; case "==": op.OperatorType = BinaryOperatorType.Equal; break; case "!=": op.OperatorType = BinaryOperatorType.NotEqual; break; case ">=": op.OperatorType = BinaryOperatorType.GreaterOrEqual; break; case ">": op.OperatorType = BinaryOperatorType.Greater; break; case ">>": op.OperatorType = BinaryOperatorType.BitwiseShiftRight; break; case "<<": op.OperatorType = BinaryOperatorType.BitwiseShiftLeft; break; case "&&": op.OperatorType = BinaryOperatorType.LogicalAnd; break; case "||": op.OperatorType = BinaryOperatorType.LogicalOr; break; case "|": op.OperatorType = BinaryOperatorType.BitwiseOr; break; case "&": op.OperatorType = BinaryOperatorType.BitwiseAnd; break; case "^": op.OperatorType = BinaryOperatorType.BitwiseXor; break; case "as": op.OperatorType = BinaryOperatorType.As; break; } // Get the left operand parser.ConsumeParseTree(root, op, currentNode.ChildNodes[0]); // "as" operator is a type case and needs to be handled differently if (op.OperatorType == BinaryOperatorType.As) { var v = new VariableReference(op, null); v.Name = currentNode.ChildNodes[2].ChildNodes[0].FindTokenAndGetText(); op.ChildExpressions.Add(v); } else { parser.ConsumeParseTree(root, op, currentNode.ChildNodes[2]); } }
// Builds a "class" expression: really could be a class, struct, or module. public static void BuildClass(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { Class c = new Class(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(c); int i = 0; // Interpret the declaration modifiers (abstract, public, internal, etc). InterpretClassModifiers(root, c, currentNode.ChildNodes[i]); i++; // Determine if it's a class, module, or struct. switch (currentNode.ChildNodes[i].Term.ToString()) { case "module": c.IsModule = true; c.IsFinal = true; c.IsPartial = true; break; case "struct": c.IsStruct = true; c.IsModule = false; break; default: c.IsStruct = false; c.IsModule = false; break; } i++; // Class name c.UnqualifiedName = currentNode.ChildNodes[i].FindTokenAndGetText(); i++; // Get the generic type list. if (currentNode.ChildNodes[i].ChildNodes.Count > 0) { var generics = currentNode.ChildNodes[i].ChildNodes[0].ChildNodes[1]; foreach (string s in IronyParser.InterpretList(generics)) { c.GenericTypeNames.Add(s); } } i++; // Get the base type list. if (currentNode.ChildNodes[i].ChildNodes.Count > 0) { var baseTypes = currentNode.ChildNodes[i].ChildNodes[0].ChildNodes[0]; foreach (string s in IronyParser.InterpretList(baseTypes)) { c.BaseTypeNames.Add(s); } } i += 1; // Build the child expressions of the class. parser.ConsumeParseTree(root, c, currentNode.ChildNodes[i]); }
// Build a method declaration expression public static void BuildMethodDeclaration(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { MethodDeclaration e = new MethodDeclaration(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(e); int i = 0; // Set default modifiers var c = parentExpression as Class; if (c.IsModule) // If the parent is a module, set the method to shared. { e.IsShared = true; } // Interpret the modifiers for the method declaration InterpretModifiers(root, e, currentNode.ChildNodes[0].ChildNodes[0]); if (e.IsShared && (e.IsFinal || e.IsOverride)) { root.CompilerErrors.Add(new IncompatibleModifiersCompilerError("", currentNode.FindToken().Location.Line, currentNode.FindToken().Location.Position)); } i += 1; // skip the def // Interpret the return type name: check if it's an array, generic, or simple type name if (currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0].Term.ToString() == "array") { e.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); e.ReturnTypeName = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0].FindTokenAndGetText()) + "[]"; } else if (currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0].Term.ToString() == "generic_identifier") { var genericNode = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0]; e.Name = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText()); e.ReturnTypeName = parser.CheckAlias(genericNode.ChildNodes[0].FindTokenAndGetText()) + "<"; for (int n = 0; n < genericNode.ChildNodes[2].ChildNodes.Count; n++) { e.ReturnTypeName += parser.CheckAlias(genericNode.ChildNodes[2].ChildNodes[n].FindTokenAndGetText()); if (n < genericNode.ChildNodes[2].ChildNodes.Count - 1) { e.ReturnTypeName += ","; } } e.ReturnTypeName += ">"; } else { e.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); e.ReturnTypeName = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].FindTokenAndGetText()); } i++; i++; // Add the generic type names for the method declaration if (currentNode.ChildNodes[1].ChildNodes.Count > 0) { var generics = currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[1]; foreach (string s in IronyParser.InterpretList(generics)) { e.GenericTypeNames.Add(s); } } i += 1; // add the arguments for the method declaration if (currentNode.ChildNodes[2].ChildNodes.Count > 0) { foreach (var n in currentNode.ChildNodes[2].ChildNodes) { BuildArgument(parser, e, n.ChildNodes[0]); } } // Build the body of statements in the method declaration parser.ConsumeParseTree(root, e, currentNode.ChildNodes[3]); }
// Build a method declaration expression public static void BuildMethodDeclaration(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { MethodDeclaration e = new MethodDeclaration(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(e); int i = 0; // Set default modifiers var c = parentExpression as Class; if(c.IsModule) // If the parent is a module, set the method to shared. { e.IsShared = true; } // Interpret the modifiers for the method declaration InterpretModifiers(root, e, currentNode.ChildNodes[0].ChildNodes[0]); if(e.IsShared && (e.IsFinal || e.IsOverride)) root.CompilerErrors.Add(new IncompatibleModifiersCompilerError("", currentNode.FindToken().Location.Line, currentNode.FindToken().Location.Position)); i+=1; // skip the def // Interpret the return type name: check if it's an array, generic, or simple type name if (currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0].Term.ToString() == "array") { e.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); e.ReturnTypeName = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0].FindTokenAndGetText()) + "[]"; } else if (currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0].Term.ToString() == "generic_identifier") { var genericNode = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0]; e.Name = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText()); e.ReturnTypeName = parser.CheckAlias(genericNode.ChildNodes[0].FindTokenAndGetText()) + "<"; for(int n = 0; n < genericNode.ChildNodes[2].ChildNodes.Count; n++) { e.ReturnTypeName += parser.CheckAlias(genericNode.ChildNodes[2].ChildNodes[n].FindTokenAndGetText()); if(n < genericNode.ChildNodes[2].ChildNodes.Count - 1) e.ReturnTypeName += ","; } e.ReturnTypeName += ">"; } else { e.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); e.ReturnTypeName = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].FindTokenAndGetText()); } i++; i++; // Add the generic type names for the method declaration if (currentNode.ChildNodes[1].ChildNodes.Count > 0) { var generics = currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[1]; foreach (string s in IronyParser.InterpretList(generics)) e.GenericTypeNames.Add(s); } i+=1; // add the arguments for the method declaration if (currentNode.ChildNodes[2].ChildNodes.Count > 0) { foreach (var n in currentNode.ChildNodes[2].ChildNodes) { BuildArgument(parser, e, n.ChildNodes[0]); } } // Build the body of statements in the method declaration parser.ConsumeParseTree(root, e, currentNode.ChildNodes[3]); }
// Build a binary operator statement public static void BuildBinaryOperator(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var op = new BinaryOperator(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(op); // Determine which binary operator this is switch (currentNode.ChildNodes[1].Term.ToString()) { case "*": op.OperatorType = BinaryOperatorType.Multiply; break; case "/": op.OperatorType = BinaryOperatorType.Divide; break; case "+": op.OperatorType = BinaryOperatorType.Add; break; case "-": op.OperatorType = BinaryOperatorType.Subtract; break; case "%": op.OperatorType = BinaryOperatorType.Modulo; break; case "<=": op.OperatorType = BinaryOperatorType.LessOrEqual; break; case "<": op.OperatorType = BinaryOperatorType.Less; break; case "==": op.OperatorType = BinaryOperatorType.Equal; break; case "!=": op.OperatorType = BinaryOperatorType.NotEqual; break; case ">=": op.OperatorType = BinaryOperatorType.GreaterOrEqual; break; case ">": op.OperatorType = BinaryOperatorType.Greater; break; case ">>": op.OperatorType = BinaryOperatorType.BitwiseShiftRight; break; case "<<": op.OperatorType = BinaryOperatorType.BitwiseShiftLeft; break; case "&&": op.OperatorType = BinaryOperatorType.LogicalAnd; break; case "||": op.OperatorType = BinaryOperatorType.LogicalOr; break; case "|": op.OperatorType = BinaryOperatorType.BitwiseOr; break; case "&": op.OperatorType = BinaryOperatorType.BitwiseAnd; break; case "^": op.OperatorType = BinaryOperatorType.BitwiseXor; break; case "as": op.OperatorType = BinaryOperatorType.As; break; } // Get the left operand parser.ConsumeParseTree(root, op, currentNode.ChildNodes[0]); // "as" operator is a type case and needs to be handled differently if(op.OperatorType == BinaryOperatorType.As) { var v = new VariableReference(op, null); v.Name = currentNode.ChildNodes[2].ChildNodes[0].FindTokenAndGetText(); op.ChildExpressions.Add(v); } else parser.ConsumeParseTree(root, op, currentNode.ChildNodes[2]); }