private IExpression CompileQualifiedName(IExpressionNodeFactory factory, IExpression curContext, IList <ParseNode> identifiers, int startIndex) { if (startIndex >= identifiers.Count) { return(curContext); } int curIndex = startIndex; ParseNode curNode = identifiers[curIndex].Nodes[0]; var nameParts = new List <string>(); while (curNode != null && curNode.Token.Type == TokenType.IDENTIFIER) { nameParts.Add(curNode.Token.Text); curIndex += 1; curNode = (curIndex < identifiers.Count) ? identifiers[curIndex].Nodes[0] : null; } if (curNode != null) { if (curNode.Token.Type == TokenType.Array) { nameParts.Add(curNode.Nodes[0].Token.Text); IExpression arrayContext = new QualifiedName(curContext, nameParts.ToArray()); var arrayFunc = new ItemAtIndex(); IExpression index = CompileExpressionNode(factory, curNode.Nodes[2]); arrayFunc.AcceptArguments(arrayContext, index); return(CompileQualifiedName(factory, arrayFunc, identifiers, curIndex + 1)); } if (curNode.Token.Type == TokenType.Method) { var methodContext = nameParts.Count > 0 ? new QualifiedName(curContext, nameParts.ToArray()) : curContext; string methodName = curNode.Nodes[0].Token.Text; IList <ParseNode> argNodes = Select(curNode.Nodes[2].Nodes, TokenType.BooleanExpr); var args = new List <IExpression>(); if (methodContext != null) { args.Add(methodContext); } foreach (ParseNode argNode in argNodes) { args.Add(CompileExpressionNode(factory, argNode)); } return(CompileQualifiedName(factory, factory.CreateFunction(methodName, args.ToArray()), identifiers, curIndex + 1)); } } if (curContext == null && nameParts.Count == 1) { return(factory.CreateVariable(nameParts[0])); } return(new QualifiedName(curContext, nameParts.ToArray())); }
protected virtual IExpression CompileExpressionNode(IExpressionNodeFactory factory, ParseTreeNode astNode) { switch (astNode.Term.Name) { case "Number": var num = TypeNormalizer.EnsureType <double>(astNode.Token.Value); return(factory.CreateLiteral(num)); case "String": var str = TypeNormalizer.EnsureType <string>(astNode.Token.Value); return(factory.CreateLiteral(str)); case "Boolean": var bln = TypeNormalizer.EnsureType <bool>(astNode.Token.Value); return(factory.CreateLiteral(bln)); case "Identifier": var variable = astNode.Token.Value; if (variable != null) { return(factory.CreateVariable(variable.ToString())); } break; case "Expr": if (astNode.ChildNodes.Count == 3 && astNode.ChildNodes[1].Term is SymbolTerminal) { IExpression left = CompileExpressionNode(factory, astNode.ChildNodes[0]); IExpression right = CompileExpressionNode(factory, astNode.ChildNodes[2]); return(factory.CreateBinaryOperator(astNode.ChildNodes[1].Term.Name, left, right)); } if (astNode.ChildNodes.Count == 2 && astNode.ChildNodes[0].Term is SymbolTerminal) { IExpression arg = CompileExpressionNode(factory, astNode.ChildNodes[1]); return(factory.CreateUnaryOperator(astNode.ChildNodes[0].Term.Name, arg)); } if (astNode.ChildNodes.Count == 2 && astNode.ChildNodes[1].Term is SymbolTerminal) { IExpression arg = CompileExpressionNode(factory, astNode.ChildNodes[0]); return(factory.CreateUnaryOperator(astNode.ChildNodes[1].Term.Name, arg)); } break; case "QualifiedName": var parts = new List <string>(); if (astNode.ChildNodes.Count == 2) { return(new QualifiedName(new[] { astNode.ChildNodes[1].Token.ValueString })); } //Condition ought to be impossible if (astNode.ChildNodes.Count != 3) { throw new Exception("Malformed QualifiedName - should have 3 child nodes"); } ExtractQualifiedName(astNode, parts); return(new QualifiedName(parts.ToArray())); case "FunctionExpression": string functionName = (astNode.ChildNodes[0].Token.ValueString); var args = new IExpression[astNode.ChildNodes[1].ChildNodes.Count]; for (int i = 0; i < astNode.ChildNodes[1].ChildNodes.Count; i++) { args[i] = CompileExpressionNode(factory, astNode.ChildNodes[1].ChildNodes[i]); } return(factory.CreateFunction(functionName, args)); case "IfThen": IExpression condition = CompileExpressionNode(factory, astNode.ChildNodes[1]); IExpression trueExpr = CompileExpressionNode(factory, astNode.ChildNodes[3]); IExpression falseExpr = null; if (astNode.ChildNodes.Count == 6) { falseExpr = CompileExpressionNode(factory, astNode.ChildNodes[5]); } var func = new IfThen(); if (falseExpr != null) { func.AcceptArguments(condition, trueExpr, falseExpr); } else { func.AcceptArguments(condition, trueExpr); } return(func); case "ArrayExpression": IExpression context = CompileExpressionNode(factory, astNode.ChildNodes[0]); IExpression index = CompileExpressionNode(factory, astNode.ChildNodes[1]); var indexer = new ItemAtIndex(); indexer.AcceptArguments(context, index); return(indexer); } return(null); }