Esempio n. 1
0
        public void Basic_TplRegex_Test()
        {
            TplRegex tplReg = new TplRegex(new ParsableString("field2 \"Regex Here\""));

            Assert.IsTrue(tplReg.TargetField == "field2", "First Field capture failed: " + tplReg.TargetField);
            Assert.IsTrue(tplReg.Rex.ToString() == "Regex Here", "First Regex capture failed: " + tplReg.Rex);

            tplReg = new TplRegex(new ParsableString("  \"Regex Here\" "));

            Assert.IsTrue(tplReg.TargetField == "_raw", "Second Field capture failed: " + tplReg.TargetField);
            Assert.IsTrue(tplReg.Rex.ToString() == "Regex Here", "Second Regex capture failed: " + tplReg.Rex);
        }
Esempio n. 2
0
        public static TplFunction Create(string query, out IReadOnlyList <LogMessage> errors)
        {
            var grammar     = new TplGrammar();
            var tplLangData = new LanguageData(grammar);
            var tplParser   = new Parser(tplLangData);

            var parseTree = tplParser.Parse(query);

            if (parseTree.HasErrors())
            {
                errors = parseTree.ParserMessages;
                return(null);
            }
            else
            {
                errors = new List <LogMessage>(0);
                var         functionNodes = parseTree.Root.ChildNodes.Select(node => node.ChildNodes);
                TplFunction rootFunction  = null;

                foreach (var funcNode in functionNodes)
                {
                    TplFunction currentFunction;
                    var         funcName = funcNode[0].FindToken().Text;
                    switch (funcName.ToLower())
                    {
                    case "between":
                        currentFunction = new TplBetween()
                        {
                            TargetField = GetOptionalVariable(funcNode[1]),
                            StartValue  = funcNode[2].FindToken().ValueString,
                            EndValue    = funcNode[3].FindToken().ValueString,
                            Inclusive   = GetSwitchValue(funcNode[4], "inclusive"),
                        };
                        break;

                    case "dedup":
                        currentFunction = new TplDedup()
                        {
                            TargetFields = GetOptionalVariableList(funcNode[1]),
                            Mode         = GetSwitchValue(funcNode[2], "all") ? TplDedup.DedupMode.All : TplDedup.DedupMode.Consecutive,
                        };
                        break;

                    case "delete":
                    {
                        var fields = GetOptionalVariableList(funcNode[1]);

                        if (fields.Count < 1)
                        {
                            throw funcNode[0].GetException("At least one field name is required in Delete function");
                        }

                        currentFunction = new TplDelete()
                        {
                            SelectedFields = fields
                        };
                    }
                    break;

                    case "eval":
                        var expTree = GetAsExpressionTree(funcNode[3], null);

                        currentFunction = new TplEval(funcNode[3].GetAsExpressionTree(null))
                        {
                            NewFieldName = funcNode[1].FindTokenAndGetValue <string>(),
                        };
                        break;

                    case "first":
                        currentFunction = new TplFirst()
                        {
                            First = funcNode[1].FindTokenAndGetValue <int>(),
                        };
                        break;

                    case "last":
                        currentFunction = new TplLast()
                        {
                            Last = funcNode[1].FindTokenAndGetValue <int>(),
                        };
                        break;

                    case "group":
                        currentFunction = new TplGroup()
                        {
                            TargetField = GetOptionalVariable(funcNode[1]),
                            StartRegex  = funcNode[2].FindToken().GetTokenAsRegex(),
                            EndRegex    = funcNode[3].FindToken().GetTokenAsRegex(),
                        };
                        break;

                    case "kv":
                        currentFunction = new TplKeyValue()
                        {
                            TargetFields  = GetOptionalVariableList(funcNode[1], TplResult.DEFAULT_FIELD),
                            KeyValueRegex = GetTokenAsRegex(funcNode[2].FindToken())
                        };
                        break;

                    case "rex":
                        ValidateArgumentList(funcNode[3], "passthru");
                        currentFunction = new TplRegex()
                        {
                            TargetField = GetOptionalVariable(funcNode[1]),
                            Rex         = GetTokenAsRegex(funcNode[2].FindToken()),
                            PassThru    = GetNamedArgumentValue(funcNode[3], "passthru", false),
                        };
                        break;

                    case "select":
                        currentFunction = new TplSelect()
                        {
                            SelectedFields = GetOptionalVariableList(funcNode[1], TplResult.DEFAULT_FIELD)
                        };
                        break;

                    case "sort":
                        currentFunction = new TplSort(
                            funcNode[1].ChildNodes
                            .Select(sortNode => new TplSortField(sortNode.ChildNodes[0].FindToken().ValueString, (sortNode.ChildNodes.Count > 1 ? (sortNode.ChildNodes[1].FindToken().ValueString == "desc") : false)))
                            .ToList()
                            );
                        break;

                    case "stats":
                    {
                        ValidateArgumentList(funcNode[3], "count", "sum", "avg");
                        if (!funcNode[3].ChildNodes.Any())
                        {
                            throw funcNode[0].GetException("Expected 1 or more of the following arguments: 'count', 'sum', or 'avg' in 'stats' function");
                        }

                        List <string> byFields;
                        if (funcNode[2].ChildNodes.Any())         // if the keyword 'by' is present, look for by fields
                        {
                            byFields = GetOptionalVariableList(funcNode[2].ChildNodes[1]);
                            if (!byFields.Any())
                            {
                                throw funcNode[2].GetException("Expected 1 or more variables in 'stats' function after 'by'");
                            }
                        }
                        else
                        {
                            byFields = new List <string>(0);
                        }

                        currentFunction = new TplStats()
                        {
                            TargetFields = GetOptionalVariableList(funcNode[1], TplResult.DEFAULT_FIELD),
                            ByFields     = byFields,
                            Avg          = GetNamedArgumentValue(funcNode[3], "avg", false),
                            Count        = GetNamedArgumentValue(funcNode[3], "count", false),
                            Sum          = GetNamedArgumentValue(funcNode[3], "sum", false),
                        };
                    }
                    break;

                    case "where":
                        currentFunction = new TplWhere(funcNode[1].GetAsExpressionTree(null));
                        break;

                    case "tolower":
                    case "toupper":
                        ValidateArgumentList(funcNode[2], "rex", "group");
                        {
                            var rex   = GetNamedArgumentValue <Regex>(funcNode[2], "rex", null);
                            var group = GetNamedArgumentValue <string>(funcNode[2], "group", null);

                            if (rex == null && group != null)
                            {
                                throw new InvalidOperationException($"Invalid argument 'group' in {funcName}. A group cannot be specified unless the 'rex' argument is also specified");
                            }
                            else if (rex != null && group != null && !rex.GetNamedCaptureGroupNames().Contains(group))
                            {
                                throw new InvalidOperationException($"Invalid value '{group}' for 'group' argument in {funcName}. The capture group does not exist in the specified regex");
                            }

                            currentFunction = new TplChangeCase()
                            {
                                TargetFields  = GetOptionalVariableList(funcNode[1], TplResult.DEFAULT_FIELD),
                                ToUpper       = funcName.ToLower() == "toupper",
                                TargetGroup   = group,
                                MatchingRegex = rex
                            };
                        }
                        break;

                    case "replace":
                        ValidateArgumentList(funcNode[4], "as", "rex", "group", "case");
                        {
                            var rex = new TplReplace()
                            {
                                TargetFields  = GetOptionalVariableList(funcNode[1], TplResult.DEFAULT_FIELD),
                                Replace       = funcNode[3].FindTokenAndGetValue <string>(),
                                AsField       = GetNamedArgumentValue <string>(funcNode[4], "as", null),
                                TargetGroup   = GetNamedArgumentValue <string>(funcNode[4], "group", null),
                                CaseSensitive = GetNamedArgumentValue <bool>(funcNode[4], "case", false),
                                RegexMode     = GetNamedArgumentValue <bool>(funcNode[4], "rex", false),
                            };
                            rex.Find        = funcNode[2].FindTokenAndGetValue <string>();
                            currentFunction = rex;
                        }
                        break;

                    case "splice":
                    {
                        ValidateArgumentList(funcNode[3], "as");
                        var targetField = GetOptionalVariable(funcNode[1]);
                        currentFunction = new TplSplice(funcNode[2].FindTokenAndGetValue <string>())
                        {
                            TargetField = targetField,
                            AsField     = GetNamedArgumentValue(funcNode[3], "as", targetField)
                        };
                    }
                    break;

                    case "concat":
                    {
                        var concatValues = funcNode[3].ChildNodes
                                           .Select(value => value.FindToken())
                                           .Select(t => new ConcatValue(t.ValueString, t.Text[0] == '$'))
                                           .ToList();
                        currentFunction = new TplStringConcat(concatValues, funcNode[1].FindToken().ValueString);
                    }
                    break;

                    case "padleft":
                    case "padright":
                    {
                        ValidateArgumentList(funcNode[3], "char");
                        currentFunction = new TplStringPad()
                        {
                            TargetFields = GetOptionalVariableList(funcNode[1], TplResult.DEFAULT_FIELD),
                            TotalLength  = funcNode[2].FindTokenAndGetValue <int>(),
                            PaddingChar  = GetNamedArgumentValue <char>(funcNode[3], "char", ' '),
                            PadRight     = funcName == "padright",
                        };
                    }
                    break;

                    case "substr":
                    {
                        ValidateArgumentList(funcNode[4], "as");
                        var target = GetOptionalVariable(funcNode[1]);
                        currentFunction = new TplSubstring()
                        {
                            TargetField = target,
                            StartIndex  = funcNode[2].FindTokenAndGetValue <int>(),
                            MaxLength   = funcNode[3].FindTokenAndGetValue <int>(-1),
                            AsField     = GetNamedArgumentValue <string>(funcNode[4], "as", target),
                        };
                    }
                    break;

                    case "split":
                    {
                        currentFunction = new TplSplit()
                        {
                            TargetField = GetOptionalVariable(funcNode[1]),
                            SplitOn     = funcNode[2].FindTokenAndGetValue <string>(),
                        };
                    }
                    break;

                    case "readlines":
                    {
                        ValidateArgumentList(funcNode[2], "recurse");
                        currentFunction = new TplReadLines()
                        {
                            FilePath = funcNode[1].FindTokenAndGetValue <string>(),
                            Recurse  = GetNamedArgumentValue(funcNode[2], "recurse", false),
                        };
                    }
                    break;

                    default:
                        throw new InvalidOperationException($"Invalid function name '{funcName}'");
                    }

                    if (rootFunction == null)
                    {
                        rootFunction = currentFunction;
                    }

                    else
                    {
                        rootFunction.AddToPipeline(currentFunction);
                    }
                }

                return(rootFunction);
            }
        }