private static Func <double, double> CompileFunctionCall(NonterminalSyntaxNode node, CompilationContext context) { int childCount = node.Children.Count; if (childCount < 2) { context.AddError(ErrorType.ArgumentExpected); return(null); } var functionNode = (TerminalSyntaxNode)node.Children[0]; string functionName = functionNode.Token.Text; if (childCount == 2) { Func <double, double> monadicFunction = context.ResolveMonadicFunction(functionName); if (monadicFunction == null) { context.AddErrorWithParameter(ErrorType.UnknownFunction, functionNode); return(null); } Func <double, double> argument = Compile(node.Children[1], context); if (argument == null) { return(null); } return(x => monadicFunction(argument(x))); } if (childCount == 3) { Func <double, double, double> dyadicFunction = context.Symbols.ResolveDyadicFunction(functionName); if (dyadicFunction == null) { context.AddErrorWithParameter(ErrorType.UnknownFunction, functionNode); return(null); } Func <double, double> firstArgument = Compile(node.Children[1], context); if (firstArgument == null) { return(null); } Func <double, double> secondArgument = Compile(node.Children[2], context); if (secondArgument == null) { return(null); } return(x => dyadicFunction(firstArgument(x), secondArgument(x))); } context.AddError(ErrorType.ExcessArguments); return(null); }
private static Func <double, double> CompileUnaryOperation(NonterminalSyntaxNode node, CompilationContext context) { Func <double, double> operand = Compile(node.Children[0], context); if (operand == null) { return(null); } return(x => - 1.0 * operand(x)); }
private static Func <double, double> CompileBinaryOperation(NonterminalSyntaxNode node, CompilationContext context) { Func <double, double> left = Compile(node.Children[0], context); if (left == null) { return(null); } Func <double, double> right = Compile(node.Children[1], context); if (right == null) { return(null); } switch (node.Type) { case NodeType.Addition: return(x => left(x) + right(x)); case NodeType.Division: return(x => left(x) / right(x)); case NodeType.Modulus: return(x => left(x) % right(x)); case NodeType.Multiplication: return(x => left(x) * right(x)); case NodeType.Power: return(x => Math.Pow(left(x), right(x))); case NodeType.Subtraction: return(x => left(x) - right(x)); default: throw new InvalidOperationException($"Unsupported binary operation of NodeType {node.Type}"); } }