| 3096 | }; |
| 3097 | |
| 3098 | ParseTrace EventFilterModel::ParseExpressionToFilters(QString expr, rdcarray<EventFilter> &filters) const |
| 3099 | { |
| 3100 | // we have a simple grammar, we pick out subexpressions and they're all independent. |
| 3101 | // |
| 3102 | // - Individual words are literal subexpressions on their own and end with whitespace. |
| 3103 | // - A " starts a quoted literal subexpression, which is a literal string and ends on the next |
| 3104 | // ". It supports escaping " with \ and otherwise any escaped character is the literal |
| 3105 | // character. The quotes must be followed by whitespace or the end of the expression. |
| 3106 | // - Both literal subexpressions are matched case-insensitively. For case-sensitive matching |
| 3107 | // you can use a regexp as a functional expression. |
| 3108 | // - A $ starts a functional expression, with parameters in brackets. The name starts with a |
| 3109 | // letter and contains alphanumeric and . characters. The name is followed by a ( to begin the |
| 3110 | // parameters and ends when the matching ) is found. Whitespace between the name and the ( is |
| 3111 | // ignored, but any other character is a parse error. The ) must be followed by whitespace or |
| 3112 | // the end of the expression or that's a parse error. Note that whitespace is allowed in the |
| 3113 | // parameters. |
| 3114 | // - We allow nesting with simple () brackets. Unquoted literals cannot contain a ( to avoid |
| 3115 | // parsing ambiguity between e.g. Foo(Bar Blah) and Foo (Bar Blah). |
| 3116 | // |
| 3117 | // This means there's a simple state machine we can follow from any point. |
| 3118 | // |
| 3119 | // 1) start -> whitespace -> start |
| 3120 | // 2) start -> " -> quoted_expression -> wait until unescaped " -> start |
| 3121 | // 3) start -> $ -> function_expression -> parse name > optional whitespace -> |
| 3122 | // ( -> wait until matching parenthesis -> ) -> whitespace -> start |
| 3123 | // 4) start -> ( -> nested_expression -> wait until matching unquoted ) -> start |
| 3124 | // 5) start -> anything else -> literal -> wait until whitespace -> start |
| 3125 | // |
| 3126 | // We also have two modifiers: |
| 3127 | // |
| 3128 | // 6) start -> + -> note that next filter is a MustMatch -> start |
| 3129 | // 7) start -> - -> note that next filter is a CantMatch -> start |
| 3130 | // |
| 3131 | // any non-existant edge is a parse error |
| 3132 | |
| 3133 | ParseTrace trace; |
| 3134 | |
| 3135 | enum |
| 3136 | { |
| 3137 | Start, |
| 3138 | QuotedExpr, |
| 3139 | FunctionExprName, |
| 3140 | FunctionExprParams, |
| 3141 | Literal, |
| 3142 | Nested, |
| 3143 | } state = Start; |
| 3144 | |
| 3145 | expr = expr.trimmed(); |
| 3146 | |
| 3147 | MatchType matchType = MatchType::Normal; |
| 3148 | |
| 3149 | // temporary string we're building up somewhere |
| 3150 | QString s; |
| 3151 | |
| 3152 | // parenthesis depth |
| 3153 | int parenDepth = 0; |
| 3154 | // start of the current set of parameters |
| 3155 | int paramStartPos = 0; |
no test coverage detected