private static StringBuilder ConstructSql(ProcessedToken token, StringBuilder buffer = null) { if (buffer == null) { buffer = new StringBuilder(BUFFER_CAPACITY); } if (!token.IsValid) { return(buffer); } switch (token) { case ProcessedParameter parsedParameter: buffer.Append(parsedParameter.ConditionSql); break; case ProcessedScopeSeparator scopeSeparator: buffer.Append(scopeSeparator.ParserToken.Text); buffer.Append(scopeSeparator.Suffix); break; default: switch (token.ParserToken) { case Sql sql: buffer.Append(sql.Text); break; case ContentToken contentToken: buffer.Append(contentToken.OpeningTag); if (contentToken.Content != null) { ConstructSql(token.Children.First(), buffer); } buffer.Append(contentToken.ClosingTag); break; case TextToken textToken: buffer.Append(textToken.Text); break; case NestedToken _: foreach (var childToken in token.Children) { ConstructSql(childToken, buffer); } break; default: throw new NotSupportedException(); } break; } return(buffer); }
private ProcessedToken ProcessToken(Token token, ProcessedToken parentToken = null, ProcessedToken previousSibling = null) { ProcessedToken newToken = null; if (token is NestedToken nestedToken) { ProcessedToken prevTokenBuf = null; if (nestedToken is Scope scopeToken) { var parsedScope = (ProcessedScope)(newToken = new ProcessedScope(scopeToken)); parentToken?.Children.Add(parsedScope); foreach (var childToken in scopeToken.Children) { prevTokenBuf = ProcessToken(childToken, parsedScope, prevTokenBuf); } // Validate this scope parsedScope.IsValid = parsedScope.Children.OfType <ProcessedScope>().Any(s => s.IsValid) || parsedScope.Children.OfType <ProcessedParameter>().Any(); // Validate scope separator that came before it if (previousSibling is ProcessedScopeSeparator thisScopeSeparator) { if (!(thisScopeSeparator.IsValid = parsedScope.IsValid && (parentToken?.Children.OfType <ProcessedScope>().Any(s => s.IsValid && s != parsedScope) ?? false))) { return(newToken); } if (parentToken is ProcessedScope parentTokenScope) { if (parentTokenScope.ParserToken.Flags.Contains('@')) { thisScopeSeparator.Suffix = "OR "; } } if (parsedScope.ParserToken.Flags.Contains('+')) { thisScopeSeparator.Suffix = ""; // The + sign means NO suffix } else if (thisScopeSeparator.Suffix == null) { thisScopeSeparator.Suffix = "AND "; } } } else { var parsedChild = newToken = new ProcessedToken(nestedToken); parentToken?.Children.Add(parsedChild); foreach (var childToken in nestedToken.Children) { prevTokenBuf = ProcessToken(childToken, parsedChild, prevTokenBuf); } } } else if (token is ScopeSeparator separatorToken) { parentToken?.Children.Add(newToken = new ProcessedScopeSeparator(separatorToken)); } else if (token is SqlBinderComment) { return(previousSibling); } else if (token is Parameter parameterToken) { var parsedParam = (ProcessedParameter)(newToken = ParseParameter(parameterToken)); if (!string.IsNullOrEmpty(parsedParam.ConditionSql)) { parentToken.Children.Add(parsedParam); } } else if (token is ContentToken contentToken) { var parsedContent = newToken = new ProcessedToken(contentToken); parentToken?.Children.Add(parsedContent); ProcessToken(contentToken.Content, parsedContent); } else { parentToken?.Children.Add(newToken = new ProcessedToken(token)); } return(newToken); }