static string Compile(IEnumerable <Token> tokens, IFunctionCallRewriter rewriter) { using var token = tokens.GetEnumerator(); return(Function(null)); string Function(string name) { var expression = new StringBuilder(); var lastIdentier = (string)null; var args = (ImmutableArray <string> .Builder)null; void PushArg(string arg) { args ??= ImmutableArray.CreateBuilder <string>(); args.Add(arg); } while (token.TryRead(out var t)) { switch (t.Type) { case nameof(TOKEN_ID): case nameof(TOKEN_LEFT): case nameof(TOKEN_RIGHT): case nameof(TOKEN_NULLIF): { lastIdentier = t.Text; break; } case "(": { expression.Append(Function(Reset(ref lastIdentier)?.Trim())); break; } case ")": { if (name is null) // just a parenthesized expression { return("(" + expression.Append(lastIdentier).Append(t.Text)); } var arg = (expression + lastIdentier).Trim(); if (arg.Length > 0) { PushArg(arg); } return(rewriter.Rewrite(new FunctionCall(TransactSql.DequoteQuoutedIdentifier(name), args?.ToImmutable() ?? ImmutableArray <string> .Empty))); } case ",": { PushArg((expression + Reset(ref lastIdentier)).Trim()); expression.Clear(); break; } case nameof(LEX_WHITE): { if (lastIdentier is null) { expression.Append(" "); } else { lastIdentier += " "; } break; } case nameof(LEX_END_OF_LINE_COMMENT): { expression.Append("/*") .Append(t.Text.Substring(2).TrimEnd('\r')) .Append(" */"); break; } case nameof(TOKEN_CONVERT): case nameof(TOKEN_TRY_CONVERT): { // These should have been caught out during parsing so arriving // here is considered an internal implementation error. throw new Exception("Internal error due to forbidden use of native function call: " + t.Text); } default: { expression.Append(Reset(ref lastIdentier)).Append(t.Text); break; } } } return(expression.Append(lastIdentier).ToString()); } }
public static string Compile(Expression expression, IFunctionCallRewriter rewriter) { return(Compile(expression.Tokens, rewriter ?? FunctionCallRewriter.PassThru));
ArgCount(this IFunctionCallRewriter rewriter, int minArgCount, int maxArgCount) => Create(call =>
ArgCount(this IFunctionCallRewriter rewriter, int argCount) => rewriter.ArgCount(argCount, argCount);
public static IFunctionCallRewriter Rename(this IFunctionCallRewriter rewriter, string name) => Create(call => rewriter.Rewrite(call.WithName(name)));
public DelegatingFunction(string name, IFunctionCallRewriter rewriter) { _rewriter = rewriter; Name = name; }