From 6f754073d58fd268da8fd7e68d79598c6c31199c Mon Sep 17 00:00:00 2001 From: Fabian Reinartz Date: Tue, 3 Mar 2015 10:58:28 +0100 Subject: [PATCH] Add OR operation and vector matching options. This commits implements the OR operation between two vectors. Vector matching using the ON clause is added to limit the set of labels that define a match between two elements. Group modifiers (GROUP_LEFT/GROUP_RIGHT) to request many-to-one matching are added. --- rules/ast/ast.go | 314 ++++-- rules/helpers.go | 44 +- rules/helpers_test.go | 57 ++ rules/lexer.l | 3 + rules/lexer.l.go | 2269 ++++++++++++++++++++++++----------------- rules/parser.y | 36 +- rules/parser.y.go | 314 +++--- rules/rules_test.go | 197 +++- 8 files changed, 2070 insertions(+), 1164 deletions(-) diff --git a/rules/ast/ast.go b/rules/ast/ast.go index a3eb25788..84c4aa284 100644 --- a/rules/ast/ast.go +++ b/rules/ast/ast.go @@ -241,12 +241,24 @@ type ( // least one of the two operand Nodes must be a VectorNode. The other may be // a VectorNode or ScalarNode. Both criteria are checked at runtime. VectorArithExpr struct { - opType BinOpType - lhs Node - rhs Node + opType BinOpType + lhs Node + rhs Node + matchCardinality VectorMatchCardinality + matchOn clientmodel.LabelNames + includeLabels clientmodel.LabelNames } ) +type VectorMatchCardinality int + +const ( + MatchOneToOne VectorMatchCardinality = iota + MatchManyToOne + MatchOneToMany + MatchManyToMany +) + // ---------------------------------------------------------------------------- // MatrixNode types. @@ -371,14 +383,21 @@ func (node *ScalarFunctionCall) Eval(timestamp clientmodel.Timestamp) clientmode return node.function.callFn(timestamp, node.args).(clientmodel.SampleValue) } -func (node *VectorAggregation) labelsToGroupingKey(labels clientmodel.Metric) uint64 { - summer := fnv.New64a() - for _, label := range node.groupBy { - summer.Write([]byte(labels[label])) - summer.Write([]byte{clientmodel.SeparatorByte}) +// hashForLabels returns a hash value taken from the label/value pairs of the +// specified labels in the metric. +func hashForLabels(metric clientmodel.Metric, labels clientmodel.LabelNames) uint64 { + var result uint64 + s := fnv.New64a() + + for _, label := range labels { + s.Write([]byte(label)) + s.Write([]byte{clientmodel.SeparatorByte}) + s.Write([]byte(metric[label])) + result ^= s.Sum64() + s.Reset() } - return summer.Sum64() + return result } // EvalVectorInstant evaluates a VectorNode with an instant query. @@ -484,7 +503,7 @@ func (node *VectorAggregation) Eval(timestamp clientmodel.Timestamp) Vector { vector := node.vector.Eval(timestamp) result := map[uint64]*groupedAggregation{} for _, sample := range vector { - groupingKey := node.labelsToGroupingKey(sample.Metric.Metric) + groupingKey := hashForLabels(sample.Metric.Metric, node.groupBy) if groupedResult, ok := result[groupingKey]; ok { if node.keepExtraLabels { groupedResult.labels = labelIntersection(groupedResult.labels, sample.Metric) @@ -729,10 +748,6 @@ func evalVectorBinop(opType BinOpType, return lhs, true } return 0, false - case And: - return lhs, true - case Or: - return lhs, true // TODO: implement OR } panic("Not all enum values enumerated in switch") } @@ -749,55 +764,214 @@ func labelsEqual(labels1, labels2 clientmodel.Metric) bool { // Eval implements the VectorNode interface and returns the result of // the expression. func (node *VectorArithExpr) Eval(timestamp clientmodel.Timestamp) Vector { - result := Vector{} - if node.lhs.Type() == ScalarType && node.rhs.Type() == VectorType { - lhs := node.lhs.(ScalarNode).Eval(timestamp) - rhs := node.rhs.(VectorNode).Eval(timestamp) - for _, rhsSample := range rhs { - value, keep := evalVectorBinop(node.opType, lhs, rhsSample.Value) - if keep { - rhsSample.Value = value - if node.opType.shouldDropMetric() { - rhsSample.Metric.Delete(clientmodel.MetricNameLabel) - } - result = append(result, rhsSample) - } - } - return result - } else if node.lhs.Type() == VectorType && node.rhs.Type() == ScalarType { - lhs := node.lhs.(VectorNode).Eval(timestamp) - rhs := node.rhs.(ScalarNode).Eval(timestamp) - for _, lhsSample := range lhs { - value, keep := evalVectorBinop(node.opType, lhsSample.Value, rhs) - if keep { - lhsSample.Value = value - if node.opType.shouldDropMetric() { - lhsSample.Metric.Delete(clientmodel.MetricNameLabel) - } - result = append(result, lhsSample) - } - } - return result - } else if node.lhs.Type() == VectorType && node.rhs.Type() == VectorType { + // Calculate vector-to-vector operation. + if node.lhs.Type() == VectorType && node.rhs.Type() == VectorType { lhs := node.lhs.(VectorNode).Eval(timestamp) rhs := node.rhs.(VectorNode).Eval(timestamp) - for _, lhsSample := range lhs { - for _, rhsSample := range rhs { - if labelsEqual(lhsSample.Metric.Metric, rhsSample.Metric.Metric) { - value, keep := evalVectorBinop(node.opType, lhsSample.Value, rhsSample.Value) - if keep { - lhsSample.Value = value - if node.opType.shouldDropMetric() { - lhsSample.Metric.Delete(clientmodel.MetricNameLabel) - } - result = append(result, lhsSample) - } - } - } - } - return result + + return node.evalVectors(timestamp, lhs, rhs) } - panic("Invalid vector arithmetic expression operands") + + // Calculate vector-to-scalar operation. + var lhs Vector + var rhs clientmodel.SampleValue + swap := false + + if node.lhs.Type() == ScalarType && node.rhs.Type() == VectorType { + lhs = node.rhs.(VectorNode).Eval(timestamp) + rhs = node.lhs.(ScalarNode).Eval(timestamp) + swap = true + } else { + lhs = node.lhs.(VectorNode).Eval(timestamp) + rhs = node.rhs.(ScalarNode).Eval(timestamp) + } + + result := make(Vector, 0, len(lhs)) + + for _, lhsSample := range lhs { + lv, rv := lhsSample.Value, rhs + // lhs always contains the vector. If the original position was different + // swap for calculating the value. + if swap { + lv, rv = rv, lv + } + value, keep := evalVectorBinop(node.opType, lv, rv) + if keep { + lhsSample.Value = value + if node.opType.shouldDropMetric() { + lhsSample.Metric.Delete(clientmodel.MetricNameLabel) + } + result = append(result, lhsSample) + } + } + return result +} + +// evalVectors evaluates the binary operation for the given vectors. +func (node *VectorArithExpr) evalVectors(timestamp clientmodel.Timestamp, lhs, rhs Vector) Vector { + result := make(Vector, 0, len(rhs)) + // The control flow below handles one-to-one or many-to-one matching. + // For one-to-many, swap sidedness and account for the swap when calculating + // values. + if node.matchCardinality == MatchOneToMany { + lhs, rhs = rhs, lhs + } + // All samples from the rhs hashed by the matching label/values. + rm := make(map[uint64]*Sample) + // Maps the hash of the label values used for matching to the hashes of the label + // values of the include labels (if any). It is used to keep track of already + // inserted samples. + added := make(map[uint64][]uint64) + + // Add all rhs samples to a map so we can easily find matches later. + for _, rs := range rhs { + hash := node.hashForMetric(rs.Metric.Metric) + // The rhs is guaranteed to be the 'one' side. Having multiple samples + // with the same hash means that the matching is many-to-many, + // which is not supported. + if _, found := rm[hash]; node.matchCardinality != MatchManyToMany && found { + // Many-to-many matching not allowed. + // TODO(fabxc): Return a query error here once AST nodes support that. + return Vector{} + } + // In many-to-many matching the entry is simply overwritten. It can thus only + // be used to check whether any matching rhs entry exists but not retrieve them all. + rm[hash] = rs + } + + // For all lhs samples find a respective rhs sample and perform + // the binary operation. + for _, ls := range lhs { + hash := node.hashForMetric(ls.Metric.Metric) + // Any lhs sample we encounter in an OR operation belongs to the result. + if node.opType == Or { + ls.Metric = node.resultMetric(ls, nil) + result = append(result, ls) + added[hash] = nil // Ensure matching rhs sample is not added later. + continue + } + + rs, found := rm[hash] // Look for a match in the rhs vector. + if !found { + continue + } + var value clientmodel.SampleValue + var keep bool + + if node.opType == And { + value = ls.Value + keep = true + } else { + if _, exists := added[hash]; node.matchCardinality == MatchOneToOne && exists { + // Many-to-one matching must be explicit. + // TODO(fabxc): Return a query error here once AST nodes support that. + return Vector{} + } + // Account for potentially swapped sidedness. + vl, vr := ls.Value, rs.Value + if node.matchCardinality == MatchOneToMany { + vl, vr = vr, vl + } + value, keep = evalVectorBinop(node.opType, vl, vr) + } + + if keep { + metric := node.resultMetric(ls, rs) + // Check if the same label set has been added for a many-to-one matching before. + if node.matchCardinality == MatchManyToOne || node.matchCardinality == MatchOneToMany { + insHash := hashForLabels(metric.Metric, node.includeLabels) + if ihs, exists := added[hash]; exists { + for _, ih := range ihs { + if ih == insHash { + // TODO(fabxc): Return a query error here once AST nodes support that. + return Vector{} + } + } + added[hash] = append(ihs, insHash) + } else { + added[hash] = []uint64{insHash} + } + } + ns := &Sample{ + Metric: metric, + Value: value, + Timestamp: timestamp, + } + result = append(result, ns) + added[hash] = added[hash] // Set existance to true. + } + } + + // Add all remaining samples in the rhs in an OR operation if they + // have not been matched up with a lhs sample. + if node.opType == Or { + for hash, rs := range rm { + if _, exists := added[hash]; !exists { + rs.Metric = node.resultMetric(rs, nil) + result = append(result, rs) + } + } + } + return result +} + +// resultMetric returns the metric for the given sample(s) based on the vector +// binary operation and the matching options. If a label that has to be included is set on +// both sides an error is returned. +func (node *VectorArithExpr) resultMetric(ls, rs *Sample) clientmodel.COWMetric { + if len(node.matchOn) == 0 || node.opType == Or || node.opType == And { + if node.opType.shouldDropMetric() { + ls.Metric.Delete(clientmodel.MetricNameLabel) + } + return ls.Metric + } + + m := clientmodel.Metric{} + for _, ln := range node.matchOn { + m[ln] = ls.Metric.Metric[ln] + } + + for _, ln := range node.includeLabels { + // Included labels from the `group_x` modifier are taken from the "many"-side. + v, ok := ls.Metric.Metric[ln] + if ok { + m[ln] = v + } + } + return clientmodel.COWMetric{false, m} +} + +// hashForMetric calculates a hash value for the given metric based on the matching +// options for the binary operation. +func (node *VectorArithExpr) hashForMetric(metric clientmodel.Metric) uint64 { + var labels clientmodel.LabelNames + + if len(node.matchOn) > 0 { + var match bool + for _, ln := range node.matchOn { + if _, match = metric[ln]; !match { + break + } + } + // If the metric does not contain the labels to match on, build the hash + // over the whole metric to give it a unique hash. + if !match { + labels = make(clientmodel.LabelNames, 0, len(metric)) + for ln := range metric { + labels = append(labels, ln) + } + } else { + labels = node.matchOn + } + } else { + labels = make(clientmodel.LabelNames, 0, len(metric)) + for ln := range metric { + if ln != clientmodel.MetricNameLabel { + labels = append(labels, ln) + } + } + } + return hashForLabels(metric, labels) } // Eval implements the MatrixNode interface and returns the value of @@ -962,7 +1136,7 @@ func nodesHaveTypes(nodes Nodes, exprTypes []ExprType) bool { // NewArithExpr returns a (not yet evaluated) expression node (of type // VectorArithExpr or ScalarArithExpr). -func NewArithExpr(opType BinOpType, lhs Node, rhs Node) (Node, error) { +func NewArithExpr(opType BinOpType, lhs Node, rhs Node, matchCard VectorMatchCardinality, matchOn, include clientmodel.LabelNames) (Node, error) { if !nodesHaveTypes(Nodes{lhs, rhs}, []ExprType{ScalarType, VectorType}) { return nil, errors.New("binary operands must be of vector or scalar type") } @@ -971,13 +1145,25 @@ func NewArithExpr(opType BinOpType, lhs Node, rhs Node) (Node, error) { if lhs.Type() == ScalarType || rhs.Type() == ScalarType { return nil, errors.New("AND and OR operators may only be used between vectors") } + // Logical operations must never be used with group modifiers. + if len(include) > 0 { + return nil, errors.New("AND and OR operators must not have a group modifier") + } + } + if lhs.Type() != VectorType || rhs.Type() != VectorType { + if matchCard != MatchOneToOne || matchOn != nil || include != nil { + return nil, errors.New("binary scalar expressions cannot have vector matching options") + } } if lhs.Type() == VectorType || rhs.Type() == VectorType { return &VectorArithExpr{ - opType: opType, - lhs: lhs, - rhs: rhs, + opType: opType, + lhs: lhs, + rhs: rhs, + matchCardinality: matchCard, + matchOn: matchOn, + includeLabels: include, }, nil } diff --git a/rules/helpers.go b/rules/helpers.go index 1c6287dc1..7c99b5ac7 100644 --- a/rules/helpers.go +++ b/rules/helpers.go @@ -82,8 +82,40 @@ func NewVectorAggregation(aggrTypeStr string, vector ast.Node, groupBy clientmod return ast.NewVectorAggregation(aggrType, vector.(ast.VectorNode), groupBy, keepExtraLabels), nil } +// vectorMatching combines data used to match samples between vectors. +type vectorMatching struct { + matchCardinality ast.VectorMatchCardinality + matchOn clientmodel.LabelNames + includeLabels clientmodel.LabelNames +} + +// newVectorMatching is a convenience function to create a new vectorMatching. +func newVectorMatching(card string, matchOn, include clientmodel.LabelNames) (*vectorMatching, error) { + var matchCardinalities = map[string]ast.VectorMatchCardinality{ + "": ast.MatchOneToOne, + "GROUP_LEFT": ast.MatchManyToOne, + "GROUP_RIGHT": ast.MatchOneToMany, + } + matchCard, ok := matchCardinalities[card] + if !ok { + return nil, fmt.Errorf("invalid vector match cardinality %q", card) + } + if matchCard != ast.MatchOneToOne && len(include) == 0 { + return nil, fmt.Errorf("grouped vector matching must provide labels") + } + // There must be no overlap between both labelname lists. + for _, matchLabel := range matchOn { + for _, incLabel := range include { + if matchLabel == incLabel { + return nil, fmt.Errorf("use of label %s in ON and %s clauses not allowed", incLabel, card) + } + } + } + return &vectorMatching{matchCard, matchOn, include}, nil +} + // NewArithExpr is a convenience function to create a new AST arithmetic expression. -func NewArithExpr(opTypeStr string, lhs ast.Node, rhs ast.Node) (ast.Node, error) { +func NewArithExpr(opTypeStr string, lhs ast.Node, rhs ast.Node, vecMatching *vectorMatching) (ast.Node, error) { var opTypes = map[string]ast.BinOpType{ "+": ast.Add, "-": ast.Sub, @@ -103,7 +135,15 @@ func NewArithExpr(opTypeStr string, lhs ast.Node, rhs ast.Node) (ast.Node, error if !ok { return nil, fmt.Errorf("invalid binary operator %q", opTypeStr) } - expr, err := ast.NewArithExpr(opType, lhs, rhs) + var vm vectorMatching + if vecMatching != nil { + vm = *vecMatching + // And/or always do many-to-many matching. + if opType == ast.And || opType == ast.Or { + vm.matchCardinality = ast.MatchManyToMany + } + } + expr, err := ast.NewArithExpr(opType, lhs, rhs, vm.matchCardinality, vm.matchOn, vm.includeLabels) if err != nil { return nil, fmt.Errorf(err.Error()) } diff --git a/rules/helpers_test.go b/rules/helpers_test.go index fe5b81921..144e6a2b3 100644 --- a/rules/helpers_test.go +++ b/rules/helpers_test.go @@ -423,6 +423,63 @@ var testMatrix = ast.Matrix{ }, Values: getTestValueStream(0, 90, 9, testStartTime), }, + { + Metric: clientmodel.COWMetric{ + Metric: clientmodel.Metric{ + clientmodel.MetricNameLabel: "vector_matching_a", + "l": "x", + }, + }, + Values: getTestValueStream(0, 100, 1, testStartTime), + }, + { + Metric: clientmodel.COWMetric{ + Metric: clientmodel.Metric{ + clientmodel.MetricNameLabel: "vector_matching_a", + "l": "y", + }, + }, + Values: getTestValueStream(0, 100, 2, testStartTime), + }, + { + Metric: clientmodel.COWMetric{ + Metric: clientmodel.Metric{ + clientmodel.MetricNameLabel: "vector_matching_b", + "l": "x", + }, + }, + Values: getTestValueStream(0, 100, 4, testStartTime), + }, + { + Metric: clientmodel.COWMetric{ + Metric: clientmodel.Metric{ + clientmodel.MetricNameLabel: "cpu_count", + "instance": "0", + "type": "numa", + }, + }, + Values: getTestValueStream(0, 500, 30, testStartTime), + }, + { + Metric: clientmodel.COWMetric{ + Metric: clientmodel.Metric{ + clientmodel.MetricNameLabel: "cpu_count", + "instance": "0", + "type": "smp", + }, + }, + Values: getTestValueStream(0, 200, 10, testStartTime), + }, + { + Metric: clientmodel.COWMetric{ + Metric: clientmodel.Metric{ + clientmodel.MetricNameLabel: "cpu_count", + "instance": "1", + "type": "smp", + }, + }, + Values: getTestValueStream(0, 200, 20, testStartTime), + }, } var testVector = getTestVectorFromTestMatrix(testMatrix) diff --git a/rules/lexer.l b/rules/lexer.l index d896afc15..ef1885379 100644 --- a/rules/lexer.l +++ b/rules/lexer.l @@ -84,6 +84,9 @@ DESCRIPTION|description return DESCRIPTION PERMANENT|permanent return PERMANENT BY|by return GROUP_OP +ON|on return MATCH_OP +GROUP_LEFT|GROUP_RIGHT lval.str = lexer.token(); return MATCH_MOD +group_left|group_right lval.str = strings.ToUpper(lexer.token()); return MATCH_MOD KEEPING_EXTRA|keeping_extra return KEEPING_EXTRA OFFSET|offset return OFFSET AVG|SUM|MAX|MIN|COUNT lval.str = lexer.token(); return AGGR_OP diff --git a/rules/lexer.l.go b/rules/lexer.l.go index a1737193b..976314f00 100644 --- a/rules/lexer.l.go +++ b/rules/lexer.l.go @@ -56,7 +56,7 @@ yystate0: case 0: // start condition: INITIAL goto yystart1 case 1: // start condition: S_COMMENTS - goto yystart171 + goto yystart198 } goto yystate0 // silence unused label error @@ -95,61 +95,65 @@ yystart1: goto yystate43 case c == 'D': goto yystate47 - case c == 'E' || c == 'G' || c == 'H' || c == 'J' || c == 'L' || c == 'Q' || c == 'R' || c >= 'T' && c <= 'V' || c >= 'X' && c <= 'Z' || c == '_' || c == 'e' || c == 'g' || c == 'h' || c == 'j' || c == 'l' || c == 'q' || c == 'r' || c >= 't' && c <= 'v' || c >= 'x' && c <= 'z': + case c == 'E' || c == 'H' || c == 'J' || c == 'L' || c == 'Q' || c == 'R' || c >= 'T' && c <= 'V' || c >= 'X' && c <= 'Z' || c == '_' || c == 'e' || c == 'h' || c == 'j' || c == 'l' || c == 'q' || c == 'r' || c >= 't' && c <= 'v' || c >= 'x' && c <= 'z': goto yystate32 case c == 'F': goto yystate58 - case c == 'I': + case c == 'G': goto yystate61 + case c == 'I': + goto yystate74 case c == 'K': - goto yystate65 - case c == 'M': goto yystate78 + case c == 'M': + goto yystate91 case c == 'N' || c == 'n': - goto yystate81 + goto yystate94 case c == 'O': - goto yystate83 + goto yystate96 case c == 'P': - goto yystate89 + goto yystate103 case c == 'S': - goto yystate98 + goto yystate112 case c == 'W': - goto yystate105 + goto yystate119 case c == '\'': goto yystate9 case c == '\t' || c == '\n' || c == '\r' || c == ' ': goto yystate2 case c == 'a': - goto yystate109 + goto yystate123 case c == 'b': - goto yystate116 + goto yystate130 case c == 'c': - goto yystate117 - case c == 'd': - goto yystate121 - case c == 'f': goto yystate131 + case c == 'd': + goto yystate135 + case c == 'f': + goto yystate145 + case c == 'g': + goto yystate147 case c == 'i': - goto yystate133 + goto yystate160 case c == 'k': - goto yystate134 + goto yystate161 case c == 'm': - goto yystate146 + goto yystate173 case c == 'o': - goto yystate149 + goto yystate176 case c == 'p': - goto yystate154 + goto yystate181 case c == 's': - goto yystate162 + goto yystate189 case c == 'w': - goto yystate168 + goto yystate195 case c >= '0' && c <= '9': goto yystate26 } yystate2: c = lexer.getChar() - goto yyrule27 + goto yyrule30 yystate3: c = lexer.getChar() @@ -162,7 +166,7 @@ yystate3: yystate4: c = lexer.getChar() - goto yyrule18 + goto yyrule21 yystate5: c = lexer.getChar() @@ -179,7 +183,7 @@ yystate5: yystate6: c = lexer.getChar() - goto yyrule25 + goto yyrule28 yystate7: c = lexer.getChar() @@ -192,7 +196,7 @@ yystate7: yystate8: c = lexer.getChar() - goto yyrule20 + goto yyrule23 yystate9: c = lexer.getChar() @@ -218,13 +222,13 @@ yystate10: yystate11: c = lexer.getChar() - goto yyrule26 + goto yyrule29 yystate12: c = lexer.getChar() switch { default: - goto yyrule19 + goto yyrule22 case c == '.': goto yystate13 case c == 'I' || c == 'i': @@ -246,7 +250,7 @@ yystate14: c = lexer.getChar() switch { default: - goto yyrule21 + goto yyrule24 case c == 'E' || c == 'e': goto yystate15 case c >= '0' && c <= '9': @@ -277,7 +281,7 @@ yystate17: c = lexer.getChar() switch { default: - goto yyrule21 + goto yyrule24 case c >= '0' && c <= '9': goto yystate17 } @@ -286,7 +290,7 @@ yystate18: c = lexer.getChar() switch { default: - goto yyrule21 + goto yyrule24 case c == '.': goto yystate14 case c == 'E' || c == 'e': @@ -315,13 +319,13 @@ yystate20: yystate21: c = lexer.getChar() - goto yyrule21 + goto yyrule24 yystate22: c = lexer.getChar() switch { default: - goto yyrule20 + goto yyrule23 case c == '*': goto yystate23 case c == '/': @@ -351,7 +355,7 @@ yystate26: c = lexer.getChar() switch { default: - goto yyrule21 + goto yyrule24 case c == '.': goto yystate14 case c == 'E' || c == 'e': @@ -364,13 +368,13 @@ yystate26: yystate27: c = lexer.getChar() - goto yyrule22 + goto yyrule25 yystate28: c = lexer.getChar() switch { default: - goto yyrule24 + goto yyrule27 case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate28 } @@ -379,7 +383,7 @@ yystate29: c = lexer.getChar() switch { default: - goto yyrule17 + goto yyrule20 case c == '=': goto yystate4 } @@ -388,7 +392,7 @@ yystate30: c = lexer.getChar() switch { default: - goto yyrule26 + goto yyrule29 case c == '=' || c == '~': goto yystate4 } @@ -397,7 +401,7 @@ yystate31: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'L': @@ -414,7 +418,7 @@ yystate32: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': @@ -425,7 +429,7 @@ yystate33: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'E': @@ -438,7 +442,7 @@ yystate34: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'R': @@ -451,7 +455,7 @@ yystate35: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'T': @@ -475,7 +479,7 @@ yystate37: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'D': @@ -488,7 +492,7 @@ yystate38: c = lexer.getChar() switch { default: - goto yyrule17 + goto yyrule20 case c == ':': goto yystate28 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': @@ -499,7 +503,7 @@ yystate39: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'G': @@ -512,7 +516,7 @@ yystate40: c = lexer.getChar() switch { default: - goto yyrule15 + goto yyrule18 case c == ':': goto yystate28 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': @@ -523,7 +527,7 @@ yystate41: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'Y': @@ -547,7 +551,7 @@ yystate43: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'O': @@ -560,7 +564,7 @@ yystate44: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'U': @@ -573,7 +577,7 @@ yystate45: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'N': @@ -586,7 +590,7 @@ yystate46: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'T': @@ -599,7 +603,7 @@ yystate47: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'E': @@ -612,7 +616,7 @@ yystate48: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'S': @@ -625,7 +629,7 @@ yystate49: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'C': @@ -638,7 +642,7 @@ yystate50: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'R': @@ -651,7 +655,7 @@ yystate51: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'I': @@ -664,7 +668,7 @@ yystate52: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'P': @@ -677,7 +681,7 @@ yystate53: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'T': @@ -690,7 +694,7 @@ yystate54: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'I': @@ -703,7 +707,7 @@ yystate55: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'O': @@ -716,7 +720,7 @@ yystate56: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'N': @@ -740,7 +744,7 @@ yystate58: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'O': @@ -753,7 +757,7 @@ yystate59: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'R': @@ -777,18 +781,187 @@ yystate61: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'F': + case c == 'R': goto yystate62 - case c == 'N' || c == 'n': - goto yystate63 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } yystate62: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'O': + goto yystate63 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate63: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'U': + goto yystate64 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate64: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'P': + goto yystate65 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'O' || c >= 'Q' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate65: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == '_': + goto yystate66 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate66: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'L': + goto yystate67 + case c == 'R': + goto yystate71 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate67: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'E': + goto yystate68 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate68: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'F': + goto yystate69 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate69: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'T': + goto yystate70 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate70: + c = lexer.getChar() + switch { + default: + goto yyrule14 + case c == ':': + goto yystate28 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate71: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'I': + goto yystate72 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate72: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'G': + goto yystate73 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'H' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate73: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'H': + goto yystate69 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'G' || c >= 'I' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate74: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'F': + goto yystate75 + case c == 'N' || c == 'n': + goto yystate76 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate32 + } + +yystate75: c = lexer.getChar() switch { default: @@ -799,183 +972,16 @@ yystate62: goto yystate32 } -yystate63: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'F' || c == 'f': - goto yystate64 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'z': - goto yystate32 - } - -yystate64: - c = lexer.getChar() - switch { - default: - goto yyrule21 - case c == ':': - goto yystate28 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate65: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'E': - goto yystate66 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate66: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'E': - goto yystate67 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate67: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'P': - goto yystate68 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'O' || c >= 'Q' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate68: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'I': - goto yystate69 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate69: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'N': - goto yystate70 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate70: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'G': - goto yystate71 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'H' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate71: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == '_': - goto yystate72 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate72: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'E': - goto yystate73 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate73: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'X': - goto yystate74 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'W' || c == 'Y' || c == 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate74: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'T': - goto yystate75 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate75: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'R': - goto yystate76 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - yystate76: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'A': + case c == 'F' || c == 'f': goto yystate77 - case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'z': goto yystate32 } @@ -983,7 +989,7 @@ yystate77: c = lexer.getChar() switch { default: - goto yyrule13 + goto yyrule24 case c == ':': goto yystate28 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': @@ -994,14 +1000,12 @@ yystate78: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'A': + case c == 'E': goto yystate79 - case c == 'I': - goto yystate80 - case c >= '0' && c <= '9' || c >= 'B' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } @@ -1009,12 +1013,12 @@ yystate79: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'X': - goto yystate40 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'W' || c == 'Y' || c == 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c == 'E': + goto yystate80 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } @@ -1022,12 +1026,12 @@ yystate80: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'N': - goto yystate40 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c == 'P': + goto yystate81 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'O' || c >= 'Q' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } @@ -1035,12 +1039,12 @@ yystate81: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'A' || c == 'a': + case c == 'I': goto yystate82 - case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } @@ -1048,12 +1052,12 @@ yystate82: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'N' || c == 'n': - goto yystate64 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + case c == 'N': + goto yystate83 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } @@ -1061,14 +1065,12 @@ yystate83: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'F': + case c == 'G': goto yystate84 - case c == 'R': - goto yystate38 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'H' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } @@ -1076,12 +1078,12 @@ yystate84: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'F': + case c == '_': goto yystate85 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z': goto yystate32 } @@ -1089,12 +1091,12 @@ yystate85: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'S': + case c == 'E': goto yystate86 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } @@ -1102,12 +1104,12 @@ yystate86: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'E': + case c == 'X': goto yystate87 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'W' || c == 'Y' || c == 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } @@ -1115,7 +1117,7 @@ yystate87: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'T': @@ -1128,10 +1130,12 @@ yystate88: c = lexer.getChar() switch { default: - goto yyrule14 + goto yyrule26 case c == ':': goto yystate28 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c == 'R': + goto yystate89 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } @@ -1139,339 +1143,16 @@ yystate89: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'E': + case c == 'A': goto yystate90 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } yystate90: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'R': - goto yystate91 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate91: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'M': - goto yystate92 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate92: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'A': - goto yystate93 - case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate93: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'N': - goto yystate94 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate94: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'E': - goto yystate95 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate95: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'N': - goto yystate96 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate96: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'T': - goto yystate97 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate97: - c = lexer.getChar() - switch { - default: - goto yyrule11 - case c == ':': - goto yystate28 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate98: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'U': - goto yystate99 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate99: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'M': - goto yystate100 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate100: - c = lexer.getChar() - switch { - default: - goto yyrule15 - case c == ':': - goto yystate28 - case c == 'M': - goto yystate101 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate101: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'A': - goto yystate102 - case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate102: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'R': - goto yystate103 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate103: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'Y': - goto yystate104 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'X' || c == 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate104: - c = lexer.getChar() - switch { - default: - goto yyrule9 - case c == ':': - goto yystate28 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate105: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'I': - goto yystate106 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate106: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'T': - goto yystate107 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate107: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'H': - goto yystate108 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'G' || c >= 'I' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate108: - c = lexer.getChar() - switch { - default: - goto yyrule8 - case c == ':': - goto yystate28 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': - goto yystate32 - } - -yystate109: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'l': - goto yystate110 - case c == 'n': - goto yystate113 - case c == 'v': - goto yystate114 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c == 'm' || c >= 'o' && c <= 'u' || c >= 'w' && c <= 'z': - goto yystate32 - } - -yystate110: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'e': - goto yystate111 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': - goto yystate32 - } - -yystate111: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'r': - goto yystate112 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': - goto yystate32 - } - -yystate112: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 't': - goto yystate36 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': - goto yystate32 - } - -yystate113: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'd': - goto yystate38 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'c' || c >= 'e' && c <= 'z': - goto yystate32 - } - -yystate114: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'g': - goto yystate115 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': - goto yystate32 - } - -yystate115: c = lexer.getChar() switch { default: @@ -1482,11 +1163,516 @@ yystate115: goto yystate32 } +yystate91: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'A': + goto yystate92 + case c == 'I': + goto yystate93 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate92: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'X': + goto yystate40 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'W' || c == 'Y' || c == 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate93: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'N': + goto yystate40 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate94: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'A' || c == 'a': + goto yystate95 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate32 + } + +yystate95: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'N' || c == 'n': + goto yystate77 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate32 + } + +yystate96: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'F': + goto yystate97 + case c == 'N': + goto yystate102 + case c == 'R': + goto yystate38 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'M' || c >= 'O' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate97: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'F': + goto yystate98 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate98: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'S': + goto yystate99 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate99: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'E': + goto yystate100 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate100: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'T': + goto yystate101 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate101: + c = lexer.getChar() + switch { + default: + goto yyrule17 + case c == ':': + goto yystate28 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate102: + c = lexer.getChar() + switch { + default: + goto yyrule13 + case c == ':': + goto yystate28 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate103: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'E': + goto yystate104 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate104: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'R': + goto yystate105 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate105: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'M': + goto yystate106 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate106: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'A': + goto yystate107 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate107: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'N': + goto yystate108 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate108: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'E': + goto yystate109 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate109: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'N': + goto yystate110 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate110: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'T': + goto yystate111 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate111: + c = lexer.getChar() + switch { + default: + goto yyrule11 + case c == ':': + goto yystate28 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate112: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'U': + goto yystate113 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate113: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'M': + goto yystate114 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate114: + c = lexer.getChar() + switch { + default: + goto yyrule18 + case c == ':': + goto yystate28 + case c == 'M': + goto yystate115 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate115: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'A': + goto yystate116 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + yystate116: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'R': + goto yystate117 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate117: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'Y': + goto yystate118 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'X' || c == 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate118: + c = lexer.getChar() + switch { + default: + goto yyrule9 + case c == ':': + goto yystate28 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate119: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'I': + goto yystate120 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate120: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'T': + goto yystate121 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate121: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'H': + goto yystate122 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'G' || c >= 'I' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate122: + c = lexer.getChar() + switch { + default: + goto yyrule8 + case c == ':': + goto yystate28 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate123: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'l': + goto yystate124 + case c == 'n': + goto yystate127 + case c == 'v': + goto yystate128 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c == 'm' || c >= 'o' && c <= 'u' || c >= 'w' && c <= 'z': + goto yystate32 + } + +yystate124: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'e': + goto yystate125 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate32 + } + +yystate125: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'r': + goto yystate126 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate32 + } + +yystate126: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 't': + goto yystate36 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate32 + } + +yystate127: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'd': + goto yystate38 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'c' || c >= 'e' && c <= 'z': + goto yystate32 + } + +yystate128: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'g': + goto yystate129 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': + goto yystate32 + } + +yystate129: + c = lexer.getChar() + switch { + default: + goto yyrule19 + case c == ':': + goto yystate28 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate32 + } + +yystate130: + c = lexer.getChar() + switch { + default: + goto yyrule26 case c == ':': goto yystate28 case c == 'y': @@ -1495,193 +1681,11 @@ yystate116: goto yystate32 } -yystate117: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'o': - goto yystate118 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': - goto yystate32 - } - -yystate118: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'u': - goto yystate119 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': - goto yystate32 - } - -yystate119: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'n': - goto yystate120 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': - goto yystate32 - } - -yystate120: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 't': - goto yystate115 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': - goto yystate32 - } - -yystate121: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'e': - goto yystate122 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': - goto yystate32 - } - -yystate122: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 's': - goto yystate123 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': - goto yystate32 - } - -yystate123: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'c': - goto yystate124 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c == 'a' || c == 'b' || c >= 'd' && c <= 'z': - goto yystate32 - } - -yystate124: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'r': - goto yystate125 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': - goto yystate32 - } - -yystate125: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'i': - goto yystate126 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': - goto yystate32 - } - -yystate126: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'p': - goto yystate127 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'o' || c >= 'q' && c <= 'z': - goto yystate32 - } - -yystate127: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 't': - goto yystate128 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': - goto yystate32 - } - -yystate128: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'i': - goto yystate129 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': - goto yystate32 - } - -yystate129: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'o': - goto yystate130 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': - goto yystate32 - } - -yystate130: - c = lexer.getChar() - switch { - default: - goto yyrule23 - case c == ':': - goto yystate28 - case c == 'n': - goto yystate57 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': - goto yystate32 - } - yystate131: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'o': @@ -1694,12 +1698,12 @@ yystate132: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'r': - goto yystate60 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + case c == 'u': + goto yystate133 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': goto yystate32 } @@ -1707,14 +1711,12 @@ yystate133: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'N' || c == 'n': - goto yystate63 - case c == 'f': - goto yystate62 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'm' || c >= 'o' && c <= 'z': + case c == 'n': + goto yystate134 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': goto yystate32 } @@ -1722,12 +1724,12 @@ yystate134: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'e': - goto yystate135 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + case c == 't': + goto yystate129 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': goto yystate32 } @@ -1735,7 +1737,7 @@ yystate135: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 case c == 'e': @@ -1748,12 +1750,12 @@ yystate136: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'p': + case c == 's': goto yystate137 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'o' || c >= 'q' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': goto yystate32 } @@ -1761,12 +1763,12 @@ yystate137: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'i': + case c == 'c': goto yystate138 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c == 'a' || c == 'b' || c >= 'd' && c <= 'z': goto yystate32 } @@ -1774,12 +1776,12 @@ yystate138: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'n': + case c == 'r': goto yystate139 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': goto yystate32 } @@ -1787,12 +1789,12 @@ yystate139: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'g': + case c == 'i': goto yystate140 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': goto yystate32 } @@ -1800,12 +1802,12 @@ yystate140: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == '_': + case c == 'p': goto yystate141 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'o' || c >= 'q' && c <= 'z': goto yystate32 } @@ -1813,12 +1815,12 @@ yystate141: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'e': + case c == 't': goto yystate142 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': goto yystate32 } @@ -1826,12 +1828,12 @@ yystate142: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'x': + case c == 'i': goto yystate143 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'w' || c == 'y' || c == 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': goto yystate32 } @@ -1839,12 +1841,12 @@ yystate143: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 't': + case c == 'o': goto yystate144 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': goto yystate32 } @@ -1852,12 +1854,12 @@ yystate144: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'r': - goto yystate145 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + case c == 'n': + goto yystate57 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': goto yystate32 } @@ -1865,12 +1867,12 @@ yystate145: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'a': - goto yystate77 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + case c == 'o': + goto yystate146 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': goto yystate32 } @@ -1878,14 +1880,12 @@ yystate146: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'a': - goto yystate147 - case c == 'i': - goto yystate148 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'h' || c >= 'j' && c <= 'z': + case c == 'r': + goto yystate60 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': goto yystate32 } @@ -1893,12 +1893,12 @@ yystate147: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'x': - goto yystate115 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'w' || c == 'y' || c == 'z': + case c == 'r': + goto yystate148 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': goto yystate32 } @@ -1906,12 +1906,12 @@ yystate148: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'n': - goto yystate115 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + case c == 'o': + goto yystate149 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': goto yystate32 } @@ -1919,14 +1919,12 @@ yystate149: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'f': + case c == 'u': goto yystate150 - case c == 'r': - goto yystate38 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'q' || c >= 's' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': goto yystate32 } @@ -1934,12 +1932,12 @@ yystate150: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'f': + case c == 'p': goto yystate151 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'o' || c >= 'q' && c <= 'z': goto yystate32 } @@ -1947,12 +1945,12 @@ yystate151: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 's': + case c == '_': goto yystate152 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z': goto yystate32 } @@ -1960,12 +1958,14 @@ yystate152: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'e': + case c == 'l': goto yystate153 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + case c == 'r': + goto yystate157 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'q' || c >= 's' && c <= 'z': goto yystate32 } @@ -1973,12 +1973,12 @@ yystate153: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 't': - goto yystate88 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + case c == 'e': + goto yystate154 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate32 } @@ -1986,12 +1986,12 @@ yystate154: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'e': + case c == 'f': goto yystate155 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'z': goto yystate32 } @@ -1999,12 +1999,12 @@ yystate155: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'r': + case c == 't': goto yystate156 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': goto yystate32 } @@ -2012,12 +2012,10 @@ yystate156: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule15 case c == ':': goto yystate28 - case c == 'm': - goto yystate157 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate32 } @@ -2025,12 +2023,12 @@ yystate157: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'a': + case c == 'i': goto yystate158 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': goto yystate32 } @@ -2038,12 +2036,12 @@ yystate158: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'n': + case c == 'g': goto yystate159 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': goto yystate32 } @@ -2051,12 +2049,12 @@ yystate159: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'e': - goto yystate160 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + case c == 'h': + goto yystate155 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'g' || c >= 'i' && c <= 'z': goto yystate32 } @@ -2064,12 +2062,14 @@ yystate160: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'n': - goto yystate161 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + case c == 'N' || c == 'n': + goto yystate76 + case c == 'f': + goto yystate75 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'm' || c >= 'o' && c <= 'z': goto yystate32 } @@ -2077,12 +2077,12 @@ yystate161: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 't': - goto yystate97 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + case c == 'e': + goto yystate162 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate32 } @@ -2090,12 +2090,12 @@ yystate162: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'u': + case c == 'e': goto yystate163 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate32 } @@ -2103,12 +2103,12 @@ yystate163: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'm': + case c == 'p': goto yystate164 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'o' || c >= 'q' && c <= 'z': goto yystate32 } @@ -2116,12 +2116,12 @@ yystate164: c = lexer.getChar() switch { default: - goto yyrule16 + goto yyrule26 case c == ':': goto yystate28 - case c == 'm': + case c == 'i': goto yystate165 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': goto yystate32 } @@ -2129,12 +2129,12 @@ yystate165: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'a': + case c == 'n': goto yystate166 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': goto yystate32 } @@ -2142,12 +2142,12 @@ yystate166: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'r': + case c == 'g': goto yystate167 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': goto yystate32 } @@ -2155,12 +2155,12 @@ yystate167: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'y': - goto yystate104 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'x' || c == 'z': + case c == '_': + goto yystate168 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z': goto yystate32 } @@ -2168,12 +2168,12 @@ yystate168: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'i': + case c == 'e': goto yystate169 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate32 } @@ -2181,12 +2181,12 @@ yystate169: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 't': + case c == 'x': goto yystate170 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'w' || c == 'y' || c == 'z': goto yystate32 } @@ -2194,42 +2194,399 @@ yystate170: c = lexer.getChar() switch { default: - goto yyrule23 + goto yyrule26 case c == ':': goto yystate28 - case c == 'h': - goto yystate108 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'g' || c >= 'i' && c <= 'z': + case c == 't': + goto yystate171 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': goto yystate32 } - goto yystate171 // silence unused label error yystate171: c = lexer.getChar() -yystart171: switch { default: - goto yyabort - case c == '*': - goto yystate173 - case c >= '\x01' && c <= ')' || c >= '+' && c <= 'ÿ': + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'r': goto yystate172 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate32 } yystate172: c = lexer.getChar() - goto yyrule3 + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'a': + goto yystate90 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate32 + } yystate173: c = lexer.getChar() switch { default: - goto yyrule3 - case c == '/': + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'a': goto yystate174 + case c == 'i': + goto yystate175 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate32 } yystate174: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'x': + goto yystate129 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'w' || c == 'y' || c == 'z': + goto yystate32 + } + +yystate175: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'n': + goto yystate129 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate32 + } + +yystate176: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'f': + goto yystate177 + case c == 'n': + goto yystate102 + case c == 'r': + goto yystate38 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'm' || c >= 'o' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate32 + } + +yystate177: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'f': + goto yystate178 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'z': + goto yystate32 + } + +yystate178: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 's': + goto yystate179 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': + goto yystate32 + } + +yystate179: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'e': + goto yystate180 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate32 + } + +yystate180: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 't': + goto yystate101 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate32 + } + +yystate181: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'e': + goto yystate182 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate32 + } + +yystate182: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'r': + goto yystate183 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate32 + } + +yystate183: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'm': + goto yystate184 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': + goto yystate32 + } + +yystate184: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'a': + goto yystate185 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate32 + } + +yystate185: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'n': + goto yystate186 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate32 + } + +yystate186: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'e': + goto yystate187 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate32 + } + +yystate187: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'n': + goto yystate188 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate32 + } + +yystate188: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 't': + goto yystate111 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate32 + } + +yystate189: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'u': + goto yystate190 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': + goto yystate32 + } + +yystate190: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'm': + goto yystate191 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': + goto yystate32 + } + +yystate191: + c = lexer.getChar() + switch { + default: + goto yyrule19 + case c == ':': + goto yystate28 + case c == 'm': + goto yystate192 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': + goto yystate32 + } + +yystate192: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'a': + goto yystate193 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate32 + } + +yystate193: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'r': + goto yystate194 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate32 + } + +yystate194: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'y': + goto yystate118 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'x' || c == 'z': + goto yystate32 + } + +yystate195: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'i': + goto yystate196 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate32 + } + +yystate196: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 't': + goto yystate197 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate32 + } + +yystate197: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate28 + case c == 'h': + goto yystate122 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'g' || c >= 'i' && c <= 'z': + goto yystate32 + } + + goto yystate198 // silence unused label error +yystate198: + c = lexer.getChar() +yystart198: + switch { + default: + goto yyabort + case c == '*': + goto yystate200 + case c >= '\x01' && c <= ')' || c >= '+' && c <= 'ÿ': + goto yystate199 + } + +yystate199: + c = lexer.getChar() + goto yyrule3 + +yystate200: + c = lexer.getChar() + switch { + default: + goto yyrule3 + case c == '/': + goto yystate201 + } + +yystate201: c = lexer.getChar() goto yyrule2 @@ -2285,51 +2642,67 @@ yyrule12: // BY|by { return GROUP_OP } -yyrule13: // KEEPING_EXTRA|keeping_extra +yyrule13: // ON|on + { + return MATCH_OP + } +yyrule14: // GROUP_LEFT|GROUP_RIGHT + { + lval.str = lexer.token() + return MATCH_MOD + goto yystate0 + } +yyrule15: // group_left|group_right + { + lval.str = strings.ToUpper(lexer.token()) + return MATCH_MOD + goto yystate0 + } +yyrule16: // KEEPING_EXTRA|keeping_extra { return KEEPING_EXTRA } -yyrule14: // OFFSET|offset +yyrule17: // OFFSET|offset { return OFFSET } -yyrule15: // AVG|SUM|MAX|MIN|COUNT +yyrule18: // AVG|SUM|MAX|MIN|COUNT { lval.str = lexer.token() return AGGR_OP goto yystate0 } -yyrule16: // avg|sum|max|min|count +yyrule19: // avg|sum|max|min|count { lval.str = strings.ToUpper(lexer.token()) return AGGR_OP goto yystate0 } -yyrule17: // \<|>|AND|OR|and|or +yyrule20: // \<|>|AND|OR|and|or { lval.str = strings.ToUpper(lexer.token()) return CMP_OP goto yystate0 } -yyrule18: // ==|!=|>=|<=|=~|!~ +yyrule21: // ==|!=|>=|<=|=~|!~ { lval.str = lexer.token() return CMP_OP goto yystate0 } -yyrule19: // [+\-] +yyrule22: // [+\-] { lval.str = lexer.token() return ADDITIVE_OP goto yystate0 } -yyrule20: // [*/%] +yyrule23: // [*/%] { lval.str = lexer.token() return MULT_OP goto yystate0 } -yyrule21: // {FLOAT} +yyrule24: // {FLOAT} { num, err := strconv.ParseFloat(lexer.token(), 64) if err != nil && err.(*strconv.NumError).Err == strconv.ErrSyntax { @@ -2338,35 +2711,35 @@ yyrule21: // {FLOAT} lval.num = clientmodel.SampleValue(num) return NUMBER } -yyrule22: // {D}+{U} +yyrule25: // {D}+{U} { lval.str = lexer.token() return DURATION goto yystate0 } -yyrule23: // {L}({L}|{D})* +yyrule26: // {L}({L}|{D})* { lval.str = lexer.token() return IDENTIFIER goto yystate0 } -yyrule24: // {M}({M}|{D})* +yyrule27: // {M}({M}|{D})* { lval.str = lexer.token() return METRICNAME goto yystate0 } -yyrule25: // {STR} +yyrule28: // {STR} { lval.str = lexer.token()[1 : len(lexer.token())-1] return STRING goto yystate0 } -yyrule26: // [{}\[\]()=,] +yyrule29: // [{}\[\]()=,] { return int(lexer.buf[0]) } -yyrule27: // [\t\n\r ] +yyrule30: // [\t\n\r ] { /* gobble up any whitespace */ goto yystate0 diff --git a/rules/parser.y b/rules/parser.y index b0c11c1b9..9da0b8fe8 100644 --- a/rules/parser.y +++ b/rules/parser.y @@ -32,6 +32,7 @@ labelSet clientmodel.LabelSet labelMatcher *metric.LabelMatcher labelMatchers metric.LabelMatchers + vectorMatching *vectorMatching } /* We simulate multiple start symbols for closely-related grammars via dummy tokens. See @@ -42,8 +43,8 @@ %token IDENTIFIER STRING DURATION METRICNAME %token NUMBER -%token PERMANENT GROUP_OP KEEPING_EXTRA OFFSET -%token AGGR_OP CMP_OP ADDITIVE_OP MULT_OP +%token PERMANENT GROUP_OP KEEPING_EXTRA OFFSET MATCH_OP +%token AGGR_OP CMP_OP ADDITIVE_OP MULT_OP MATCH_MOD %token ALERT IF FOR WITH SUMMARY DESCRIPTION %type func_arg_list @@ -51,6 +52,7 @@ %type label_assign label_assign_list rule_labels %type label_match %type label_match_list label_matches +%type vector_matching %type rule_expr func_arg %type qualifier extra_labels_opts %type for_duration metric_name label_match_type offset_opts @@ -207,34 +209,50 @@ rule_expr : '(' rule_expr ')' } /* Yacc can only attach associativity to terminals, so we * have to list all operators here. */ - | rule_expr ADDITIVE_OP rule_expr + | rule_expr ADDITIVE_OP vector_matching rule_expr { var err error - $$, err = NewArithExpr($2, $1, $3) + $$, err = NewArithExpr($2, $1, $4, $3) if err != nil { yylex.Error(err.Error()); return 1 } } - | rule_expr MULT_OP rule_expr + | rule_expr MULT_OP vector_matching rule_expr { var err error - $$, err = NewArithExpr($2, $1, $3) + $$, err = NewArithExpr($2, $1, $4, $3) if err != nil { yylex.Error(err.Error()); return 1 } } - | rule_expr CMP_OP rule_expr + | rule_expr CMP_OP vector_matching rule_expr { var err error - $$, err = NewArithExpr($2, $1, $3) + $$, err = NewArithExpr($2, $1, $4, $3) if err != nil { yylex.Error(err.Error()); return 1 } } | NUMBER { $$ = ast.NewScalarLiteral($1)} ; -extra_labels_opts : +extra_labels_opts : /* empty */ { $$ = false } | KEEPING_EXTRA { $$ = true } ; +vector_matching : /* empty */ + { $$ = nil } + | MATCH_OP '(' label_list ')' + { + var err error + $$, err = newVectorMatching("", $3, nil) + if err != nil { yylex.Error(err.Error()); return 1 } + } + | MATCH_OP '(' label_list ')' MATCH_MOD '(' label_list ')' + { + var err error + $$, err = newVectorMatching($5, $3, $7) + if err != nil { yylex.Error(err.Error()); return 1 } + } + ; + grouping_opts : { $$ = clientmodel.LabelNames{} } | GROUP_OP '(' label_list ')' diff --git a/rules/parser.y.go b/rules/parser.y.go index e69abcd6a..95a4a592e 100644 --- a/rules/parser.y.go +++ b/rules/parser.y.go @@ -23,6 +23,7 @@ type yySymType struct { labelSet clientmodel.LabelSet labelMatcher *metric.LabelMatcher labelMatchers metric.LabelMatchers + vectorMatching *vectorMatching } const START_RULES = 57346 @@ -36,16 +37,18 @@ const PERMANENT = 57353 const GROUP_OP = 57354 const KEEPING_EXTRA = 57355 const OFFSET = 57356 -const AGGR_OP = 57357 -const CMP_OP = 57358 -const ADDITIVE_OP = 57359 -const MULT_OP = 57360 -const ALERT = 57361 -const IF = 57362 -const FOR = 57363 -const WITH = 57364 -const SUMMARY = 57365 -const DESCRIPTION = 57366 +const MATCH_OP = 57357 +const AGGR_OP = 57358 +const CMP_OP = 57359 +const ADDITIVE_OP = 57360 +const MULT_OP = 57361 +const MATCH_MOD = 57362 +const ALERT = 57363 +const IF = 57364 +const FOR = 57365 +const WITH = 57366 +const SUMMARY = 57367 +const DESCRIPTION = 57368 var yyToknames = []string{ "START_RULES", @@ -59,10 +62,12 @@ var yyToknames = []string{ "GROUP_OP", "KEEPING_EXTRA", "OFFSET", + "MATCH_OP", "AGGR_OP", "CMP_OP", "ADDITIVE_OP", "MULT_OP", + "MATCH_MOD", "ALERT", "IF", "FOR", @@ -77,7 +82,7 @@ const yyEofCode = 1 const yyErrCode = 2 const yyMaxDepth = 200 -//line parser.y:261 +//line parser.y:279 //line yacctab:1 var yyExca = []int{ @@ -89,97 +94,101 @@ var yyExca = []int{ -2, 10, } -const yyNprod = 52 +const yyNprod = 55 const yyPrivate = 57344 var yyTokenNames []string var yyStates []string -const yyLast = 142 +const yyLast = 155 var yyAct = []int{ - 58, 76, 55, 52, 51, 30, 45, 6, 24, 20, - 61, 22, 10, 53, 18, 13, 12, 84, 68, 83, - 67, 11, 18, 36, 37, 38, 21, 19, 20, 21, - 19, 20, 8, 54, 90, 7, 50, 21, 19, 20, - 92, 18, 10, 53, 18, 13, 12, 70, 63, 62, - 88, 11, 18, 57, 31, 21, 19, 20, 86, 87, - 66, 40, 8, 10, 78, 7, 13, 12, 79, 69, - 18, 29, 11, 80, 82, 81, 28, 85, 21, 19, - 20, 19, 20, 8, 91, 77, 7, 41, 40, 94, - 25, 23, 39, 18, 59, 18, 44, 98, 27, 73, - 101, 99, 60, 96, 17, 43, 75, 9, 46, 56, - 31, 47, 16, 33, 97, 102, 13, 65, 35, 48, - 100, 95, 64, 32, 77, 93, 72, 25, 34, 2, - 3, 14, 5, 4, 1, 42, 89, 15, 26, 74, - 71, 49, + 76, 59, 81, 56, 53, 52, 30, 46, 6, 24, + 10, 54, 22, 13, 12, 21, 19, 20, 19, 20, + 11, 62, 21, 19, 20, 20, 18, 90, 96, 111, + 99, 18, 8, 18, 55, 7, 51, 60, 18, 18, + 90, 63, 97, 65, 66, 21, 19, 20, 107, 75, + 68, 67, 10, 54, 64, 13, 12, 21, 19, 20, + 74, 18, 11, 31, 58, 85, 83, 90, 94, 89, + 84, 27, 40, 18, 8, 28, 23, 7, 112, 86, + 88, 87, 29, 91, 21, 19, 20, 82, 73, 10, + 72, 98, 13, 12, 92, 93, 101, 71, 41, 11, + 18, 42, 41, 25, 49, 106, 45, 78, 109, 108, + 80, 8, 103, 36, 7, 61, 44, 17, 105, 37, + 9, 47, 57, 31, 104, 33, 48, 16, 13, 70, + 35, 113, 110, 102, 38, 39, 32, 69, 77, 82, + 100, 25, 34, 2, 3, 14, 5, 4, 1, 43, + 95, 15, 26, 79, 50, } var yyPact = []int{ - 125, -1000, -1000, 57, 93, -1000, 21, 57, 121, 72, - 47, 42, -1000, -1000, -1000, 107, 122, -1000, 110, 57, - 57, 57, 62, 60, -1000, 80, 94, 84, 6, 57, - 96, 24, 68, -1000, 82, -22, -9, -17, 64, -1000, - 121, 94, 115, -1000, -1000, -1000, 109, -1000, 33, -10, - -1000, -1000, 21, -1000, 39, 18, -1000, 120, 74, 79, - 57, 94, -1000, -1000, -1000, -1000, -1000, -1000, 36, 98, - 57, -11, -1000, 57, 31, -1000, -1000, 25, 13, -1000, - -1000, 96, 10, -1000, 119, 21, -1000, 118, 114, 81, - 106, -1000, -1000, -1000, -1000, -1000, 68, -1000, 78, 113, - 76, 108, -1000, + 139, -1000, -1000, 83, 106, -1000, 67, 83, 135, 43, + 44, 51, -1000, -1000, -1000, 119, 136, -1000, 122, 104, + 104, 104, 40, 72, -1000, 89, 107, 97, 4, 83, + 109, 33, 9, -1000, 93, -13, 83, 23, 83, 83, + -1000, 135, 107, 130, -1000, -1000, -1000, 121, -1000, 68, + 58, -1000, -1000, 67, -1000, 28, 18, -1000, 132, 80, + 81, 83, 107, 6, 132, -7, 0, -1000, -1000, -1000, + -1000, -1000, -1000, 46, 111, 83, 37, -1000, 83, 65, + -1000, -1000, 41, 5, -1000, 10, -1000, 109, -2, -1000, + 134, 67, -1000, 133, 126, 88, 116, 98, -1000, -1000, + -1000, -1000, -1000, 9, -1000, 17, 84, 132, 125, -3, + 52, -1000, 124, -1000, } var yyPgo = []int{ - 0, 141, 140, 5, 1, 139, 0, 8, 91, 138, - 3, 4, 137, 2, 136, 107, 135, 6, 134, 133, - 132, 131, + 0, 154, 0, 6, 2, 153, 1, 9, 76, 152, + 113, 4, 5, 151, 3, 150, 120, 149, 7, 148, + 147, 146, 145, } var yyR1 = []int{ - 0, 18, 18, 19, 19, 20, 21, 21, 14, 14, - 12, 12, 15, 15, 6, 6, 6, 5, 5, 4, - 9, 9, 9, 8, 8, 7, 16, 16, 17, 17, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 13, 13, 3, 3, 2, 2, 1, 1, - 11, 11, + 0, 19, 19, 20, 20, 21, 22, 22, 15, 15, + 13, 13, 16, 16, 6, 6, 6, 5, 5, 4, + 9, 9, 9, 8, 8, 7, 17, 17, 18, 18, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 14, 14, 10, 10, 10, 3, 3, 2, + 2, 1, 1, 12, 12, } var yyR2 = []int{ 0, 2, 2, 0, 2, 1, 5, 11, 0, 2, 0, 1, 1, 1, 0, 3, 2, 1, 3, 3, 0, 2, 3, 1, 3, 3, 1, 1, 0, 2, - 3, 4, 3, 4, 3, 5, 6, 6, 3, 3, - 3, 1, 0, 1, 0, 4, 1, 3, 1, 3, - 1, 1, + 3, 4, 3, 4, 3, 5, 6, 6, 4, 4, + 4, 1, 0, 1, 0, 4, 8, 0, 4, 1, + 3, 1, 3, 1, 1, } var yyChk = []int{ - -1000, -18, 4, 5, -19, -20, -10, 29, 26, -15, - 6, 15, 10, 9, -21, -12, 19, 11, 31, 17, - 18, 16, -10, -8, -7, 6, -9, 26, 29, 29, - -3, 12, -15, 6, 6, 8, -10, -10, -10, 30, - 28, 27, -16, 25, 16, -17, 14, 27, -8, -1, - 30, -11, -10, 7, -10, -13, 13, 29, -6, 26, - 20, 32, -7, -17, 7, 8, 27, 30, 28, 30, - 29, -2, 6, 25, -5, 27, -4, 6, -10, -17, - -11, -3, -10, 30, 28, -10, 27, 28, 25, -14, - 21, -13, 30, 6, -4, 7, 22, 8, -6, 23, - 7, 24, 7, + -1000, -19, 4, 5, -20, -21, -11, 31, 28, -16, + 6, 16, 10, 9, -22, -13, 21, 11, 33, 18, + 19, 17, -11, -8, -7, 6, -9, 28, 31, 31, + -3, 12, -16, 6, 6, 8, -10, 15, -10, -10, + 32, 30, 29, -17, 27, 17, -18, 14, 29, -8, + -1, 32, -12, -11, 7, -11, -14, 13, 31, -6, + 28, 22, 34, -11, 31, -11, -11, -7, -18, 7, + 8, 29, 32, 30, 32, 31, -2, 6, 27, -5, + 29, -4, 6, -11, -18, -2, -12, -3, -11, 32, + 30, -11, 29, 30, 27, -15, 23, 32, -14, 32, + 6, -4, 7, 24, 8, 20, -6, 31, 25, -2, + 7, 32, 26, 7, } var yyDef = []int{ 0, -2, 3, 0, -2, 2, 5, 0, 0, 20, - 13, 44, 41, 12, 4, 0, 0, 11, 0, 0, - 0, 0, 0, 0, 23, 0, 28, 0, 0, 0, - 42, 0, 14, 13, 0, 0, 38, 39, 40, 30, - 0, 28, 0, 26, 27, 32, 0, 21, 0, 0, - 34, 48, 50, 51, 0, 0, 43, 0, 0, 0, - 0, 28, 24, 31, 25, 29, 22, 33, 0, 44, - 0, 0, 46, 0, 0, 16, 17, 0, 8, 35, - 49, 42, 0, 45, 0, 6, 15, 0, 0, 0, - 0, 36, 37, 47, 18, 19, 14, 9, 0, 0, - 0, 0, 7, + 13, 47, 41, 12, 4, 0, 0, 11, 0, 44, + 44, 44, 0, 0, 23, 0, 28, 0, 0, 0, + 42, 0, 14, 13, 0, 0, 0, 0, 0, 0, + 30, 0, 28, 0, 26, 27, 32, 0, 21, 0, + 0, 34, 51, 53, 54, 0, 0, 43, 0, 0, + 0, 0, 28, 38, 0, 39, 40, 24, 31, 25, + 29, 22, 33, 0, 47, 0, 0, 49, 0, 0, + 16, 17, 0, 8, 35, 0, 52, 42, 0, 48, + 0, 6, 15, 0, 0, 0, 0, 45, 36, 37, + 50, 18, 19, 14, 9, 0, 0, 0, 0, 0, + 0, 46, 0, 7, } var yyTok1 = []int{ @@ -187,21 +196,21 @@ var yyTok1 = []int{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 29, 30, 3, 3, 28, 3, 3, 3, 3, 3, + 31, 32, 3, 3, 30, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 25, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 27, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 31, 3, 32, 3, 3, 3, 3, 3, 3, + 3, 33, 3, 34, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 26, 3, 27, + 3, 3, 3, 28, 3, 29, } var yyTok2 = []int{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, + 22, 23, 24, 25, 26, } var yyTok3 = []int{ 0, @@ -433,12 +442,12 @@ yydefault: switch yynt { case 5: - //line parser.y:74 + //line parser.y:76 { yylex.(*RulesLexer).parsedExpr = yyS[yypt-0].ruleNode } case 6: - //line parser.y:79 + //line parser.y:81 { rule, err := CreateRecordingRule(yyS[yypt-3].str, yyS[yypt-2].labelSet, yyS[yypt-0].ruleNode, yyS[yypt-4].boolean) if err != nil { @@ -448,7 +457,7 @@ yydefault: yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule) } case 7: - //line parser.y:85 + //line parser.y:87 { rule, err := CreateAlertingRule(yyS[yypt-9].str, yyS[yypt-7].ruleNode, yyS[yypt-6].str, yyS[yypt-4].labelSet, yyS[yypt-2].str, yyS[yypt-0].str) if err != nil { @@ -458,94 +467,94 @@ yydefault: yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule) } case 8: - //line parser.y:93 + //line parser.y:95 { yyVAL.str = "0s" } case 9: - //line parser.y:95 + //line parser.y:97 { yyVAL.str = yyS[yypt-0].str } case 10: - //line parser.y:99 + //line parser.y:101 { yyVAL.boolean = false } case 11: - //line parser.y:101 + //line parser.y:103 { yyVAL.boolean = true } case 12: - //line parser.y:105 - { - yyVAL.str = yyS[yypt-0].str - } - case 13: //line parser.y:107 { yyVAL.str = yyS[yypt-0].str } + case 13: + //line parser.y:109 + { + yyVAL.str = yyS[yypt-0].str + } case 14: - //line parser.y:111 + //line parser.y:113 { yyVAL.labelSet = clientmodel.LabelSet{} } case 15: - //line parser.y:113 + //line parser.y:115 { yyVAL.labelSet = yyS[yypt-1].labelSet } case 16: - //line parser.y:115 + //line parser.y:117 { yyVAL.labelSet = clientmodel.LabelSet{} } case 17: - //line parser.y:118 + //line parser.y:120 { yyVAL.labelSet = yyS[yypt-0].labelSet } case 18: - //line parser.y:120 + //line parser.y:122 { for k, v := range yyS[yypt-0].labelSet { yyVAL.labelSet[k] = v } } case 19: - //line parser.y:124 + //line parser.y:126 { yyVAL.labelSet = clientmodel.LabelSet{clientmodel.LabelName(yyS[yypt-2].str): clientmodel.LabelValue(yyS[yypt-0].str)} } case 20: - //line parser.y:128 - { - yyVAL.labelMatchers = metric.LabelMatchers{} - } - case 21: //line parser.y:130 { yyVAL.labelMatchers = metric.LabelMatchers{} } - case 22: + case 21: //line parser.y:132 + { + yyVAL.labelMatchers = metric.LabelMatchers{} + } + case 22: + //line parser.y:134 { yyVAL.labelMatchers = yyS[yypt-1].labelMatchers } case 23: - //line parser.y:136 + //line parser.y:138 { yyVAL.labelMatchers = metric.LabelMatchers{yyS[yypt-0].labelMatcher} } case 24: - //line parser.y:138 + //line parser.y:140 { yyVAL.labelMatchers = append(yyVAL.labelMatchers, yyS[yypt-0].labelMatcher) } case 25: - //line parser.y:142 + //line parser.y:144 { var err error yyVAL.labelMatcher, err = newLabelMatcher(yyS[yypt-1].str, clientmodel.LabelName(yyS[yypt-2].str), clientmodel.LabelValue(yyS[yypt-0].str)) @@ -555,32 +564,32 @@ yydefault: } } case 26: - //line parser.y:150 + //line parser.y:152 { yyVAL.str = "=" } case 27: - //line parser.y:152 + //line parser.y:154 { yyVAL.str = yyS[yypt-0].str } case 28: - //line parser.y:156 + //line parser.y:158 { yyVAL.str = "0s" } case 29: - //line parser.y:158 + //line parser.y:160 { yyVAL.str = yyS[yypt-0].str } case 30: - //line parser.y:162 + //line parser.y:164 { yyVAL.ruleNode = yyS[yypt-1].ruleNode } case 31: - //line parser.y:164 + //line parser.y:166 { var err error yyVAL.ruleNode, err = NewVectorSelector(yyS[yypt-2].labelMatchers, yyS[yypt-0].str) @@ -590,7 +599,7 @@ yydefault: } } case 32: - //line parser.y:170 + //line parser.y:172 { var err error m, err := metric.NewLabelMatcher(metric.Equal, clientmodel.MetricNameLabel, clientmodel.LabelValue(yyS[yypt-2].str)) @@ -606,7 +615,7 @@ yydefault: } } case 33: - //line parser.y:179 + //line parser.y:181 { var err error yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-3].str, yyS[yypt-1].ruleNodeSlice) @@ -616,7 +625,7 @@ yydefault: } } case 34: - //line parser.y:185 + //line parser.y:187 { var err error yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-2].str, []ast.Node{}) @@ -626,7 +635,7 @@ yydefault: } } case 35: - //line parser.y:191 + //line parser.y:193 { var err error yyVAL.ruleNode, err = NewMatrixSelector(yyS[yypt-4].ruleNode, yyS[yypt-2].str, yyS[yypt-0].str) @@ -636,7 +645,7 @@ yydefault: } } case 36: - //line parser.y:197 + //line parser.y:199 { var err error yyVAL.ruleNode, err = NewVectorAggregation(yyS[yypt-5].str, yyS[yypt-3].ruleNode, yyS[yypt-1].labelNameSlice, yyS[yypt-0].boolean) @@ -646,7 +655,7 @@ yydefault: } } case 37: - //line parser.y:203 + //line parser.y:205 { var err error yyVAL.ruleNode, err = NewVectorAggregation(yyS[yypt-5].str, yyS[yypt-1].ruleNode, yyS[yypt-4].labelNameSlice, yyS[yypt-3].boolean) @@ -656,87 +665,112 @@ yydefault: } } case 38: - //line parser.y:211 + //line parser.y:213 { var err error - yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) + yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-2].str, yyS[yypt-3].ruleNode, yyS[yypt-0].ruleNode, yyS[yypt-1].vectorMatching) if err != nil { yylex.Error(err.Error()) return 1 } } case 39: - //line parser.y:217 + //line parser.y:219 { var err error - yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) + yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-2].str, yyS[yypt-3].ruleNode, yyS[yypt-0].ruleNode, yyS[yypt-1].vectorMatching) if err != nil { yylex.Error(err.Error()) return 1 } } case 40: - //line parser.y:223 + //line parser.y:225 { var err error - yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) + yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-2].str, yyS[yypt-3].ruleNode, yyS[yypt-0].ruleNode, yyS[yypt-1].vectorMatching) if err != nil { yylex.Error(err.Error()) return 1 } } case 41: - //line parser.y:229 + //line parser.y:231 { yyVAL.ruleNode = ast.NewScalarLiteral(yyS[yypt-0].num) } case 42: - //line parser.y:233 + //line parser.y:235 { yyVAL.boolean = false } case 43: - //line parser.y:235 + //line parser.y:237 { yyVAL.boolean = true } case 44: - //line parser.y:239 + //line parser.y:241 + { + yyVAL.vectorMatching = nil + } + case 45: + //line parser.y:243 + { + var err error + yyVAL.vectorMatching, err = newVectorMatching("", yyS[yypt-1].labelNameSlice, nil) + if err != nil { + yylex.Error(err.Error()) + return 1 + } + } + case 46: + //line parser.y:249 + { + var err error + yyVAL.vectorMatching, err = newVectorMatching(yyS[yypt-3].str, yyS[yypt-5].labelNameSlice, yyS[yypt-1].labelNameSlice) + if err != nil { + yylex.Error(err.Error()) + return 1 + } + } + case 47: + //line parser.y:257 { yyVAL.labelNameSlice = clientmodel.LabelNames{} } - case 45: - //line parser.y:241 + case 48: + //line parser.y:259 { yyVAL.labelNameSlice = yyS[yypt-1].labelNameSlice } - case 46: - //line parser.y:245 + case 49: + //line parser.y:263 { yyVAL.labelNameSlice = clientmodel.LabelNames{clientmodel.LabelName(yyS[yypt-0].str)} } - case 47: - //line parser.y:247 + case 50: + //line parser.y:265 { yyVAL.labelNameSlice = append(yyVAL.labelNameSlice, clientmodel.LabelName(yyS[yypt-0].str)) } - case 48: - //line parser.y:251 + case 51: + //line parser.y:269 { yyVAL.ruleNodeSlice = []ast.Node{yyS[yypt-0].ruleNode} } - case 49: - //line parser.y:253 + case 52: + //line parser.y:271 { yyVAL.ruleNodeSlice = append(yyVAL.ruleNodeSlice, yyS[yypt-0].ruleNode) } - case 50: - //line parser.y:257 + case 53: + //line parser.y:275 { yyVAL.ruleNode = yyS[yypt-0].ruleNode } - case 51: - //line parser.y:259 + case 54: + //line parser.y:277 { yyVAL.ruleNode = ast.NewStringLiteral(yyS[yypt-0].str) } diff --git a/rules/rules_test.go b/rules/rules_test.go index 611ac4a91..396b024f7 100644 --- a/rules/rules_test.go +++ b/rules/rules_test.go @@ -630,6 +630,12 @@ func TestExpressions(t *testing.T) { `request_duration_seconds_bucket{instance="ins2", job="job2", le="0.1"} => 40 @[%v]`, `request_duration_seconds_bucket{instance="ins2", job="job2", le="0.2"} => 70 @[%v]`, `request_duration_seconds_bucket{instance="ins2", job="job2", le="+Inf"} => 90 @[%v]`, + `vector_matching_a{l="x"} => 10 @[%v]`, + `vector_matching_a{l="y"} => 20 @[%v]`, + `vector_matching_b{l="x"} => 40 @[%v]`, + `cpu_count{instance="1", type="smp"} => 200 @[%v]`, + `cpu_count{instance="0", type="smp"} => 100 @[%v]`, + `cpu_count{instance="0", type="numa"} => 300 @[%v]`, }, }, { @@ -666,6 +672,191 @@ func TestExpressions(t *testing.T) { `{job="api-server"} => 1000 @[%v]`, }, }, + { + expr: `http_requests{group="canary"} and http_requests{instance="0"}`, + output: []string{ + `http_requests{group="canary", instance="0", job="api-server"} => 300 @[%v]`, + `http_requests{group="canary", instance="0", job="app-server"} => 700 @[%v]`, + }, + }, + { + expr: `(http_requests{group="canary"} + 1) and http_requests{instance="0"}`, + output: []string{ + `{group="canary", instance="0", job="api-server"} => 301 @[%v]`, + `{group="canary", instance="0", job="app-server"} => 701 @[%v]`, + }, + }, + { + expr: `(http_requests{group="canary"} + 1) and on(instance, job) http_requests{instance="0", group="production"}`, + output: []string{ + `{group="canary", instance="0", job="api-server"} => 301 @[%v]`, + `{group="canary", instance="0", job="app-server"} => 701 @[%v]`, + }, + }, + { + expr: `(http_requests{group="canary"} + 1) and on(instance) http_requests{instance="0", group="production"}`, + output: []string{ + `{group="canary", instance="0", job="api-server"} => 301 @[%v]`, + `{group="canary", instance="0", job="app-server"} => 701 @[%v]`, + }, + }, + { + expr: `http_requests{group="canary"} or http_requests{group="production"}`, + output: []string{ + `http_requests{group="canary", instance="0", job="api-server"} => 300 @[%v]`, + `http_requests{group="canary", instance="0", job="app-server"} => 700 @[%v]`, + `http_requests{group="canary", instance="1", job="api-server"} => 400 @[%v]`, + `http_requests{group="canary", instance="1", job="app-server"} => 800 @[%v]`, + `http_requests{group="production", instance="0", job="api-server"} => 100 @[%v]`, + `http_requests{group="production", instance="0", job="app-server"} => 500 @[%v]`, + `http_requests{group="production", instance="1", job="api-server"} => 200 @[%v]`, + `http_requests{group="production", instance="1", job="app-server"} => 600 @[%v]`, + }, + }, + { + // On overlap the rhs samples must be dropped. + expr: `(http_requests{group="canary"} + 1) or http_requests{instance="1"}`, + output: []string{ + `{group="canary", instance="0", job="api-server"} => 301 @[%v]`, + `{group="canary", instance="0", job="app-server"} => 701 @[%v]`, + `{group="canary", instance="1", job="api-server"} => 401 @[%v]`, + `{group="canary", instance="1", job="app-server"} => 801 @[%v]`, + `http_requests{group="production", instance="1", job="api-server"} => 200 @[%v]`, + `http_requests{group="production", instance="1", job="app-server"} => 600 @[%v]`, + }, + }, + { + // Matching only on instance excludes everything that has instance=0/1 but includes + // entries without the instance label. + expr: `(http_requests{group="canary"} + 1) or on(instance) (http_requests or cpu_count or vector_matching_a)`, + output: []string{ + `{group="canary", instance="0", job="api-server"} => 301 @[%v]`, + `{group="canary", instance="0", job="app-server"} => 701 @[%v]`, + `{group="canary", instance="1", job="api-server"} => 401 @[%v]`, + `{group="canary", instance="1", job="app-server"} => 801 @[%v]`, + `vector_matching_a{l="x"} => 10 @[%v]`, + `vector_matching_a{l="y"} => 20 @[%v]`, + }, + }, + { + expr: `http_requests{group="canary"} / on(instance,job) http_requests{group="production"}`, + output: []string{ + `{instance="0", job="api-server"} => 3 @[%v]`, + `{instance="0", job="app-server"} => 1.4 @[%v]`, + `{instance="1", job="api-server"} => 2 @[%v]`, + `{instance="1", job="app-server"} => 1.3333333333333333 @[%v]`, + }, + }, + { + // Include labels must guarantee uniquely identifiable time series. + expr: `http_requests{group="production"} / on(instance) group_left(group) cpu_count{type="smp"}`, + output: []string{}, // Empty result returned on error (see TODOs). + }, + { + // Many-to-many matching is not allowed. + expr: `http_requests{group="production"} / on(instance) group_left(job,type) cpu_count`, + output: []string{}, // Empty result returned on error (see TODOs). + }, + { + // Many-to-one matching must be explicit. + expr: `http_requests{group="production"} / on(instance) cpu_count{type="smp"}`, + output: []string{}, // Empty result returned on error (see TODOs). + }, + { + expr: `http_requests{group="production"} / on(instance) group_left(job) cpu_count{type="smp"}`, + output: []string{ + `{instance="1", job="api-server"} => 1 @[%v]`, + `{instance="0", job="app-server"} => 5 @[%v]`, + `{instance="1", job="app-server"} => 3 @[%v]`, + `{instance="0", job="api-server"} => 1 @[%v]`, + }, + }, + { + // Ensure sidedness of grouping preserves operand sides. + expr: `cpu_count{type="smp"} / on(instance) group_right(job) http_requests{group="production"}`, + output: []string{ + `{instance="1", job="app-server"} => 0.3333333333333333 @[%v]`, + `{instance="0", job="app-server"} => 0.2 @[%v]`, + `{instance="1", job="api-server"} => 1 @[%v]`, + `{instance="0", job="api-server"} => 1 @[%v]`, + }, + }, + { + // Include labels from both sides. + expr: `http_requests{group="production"} / on(instance) group_left(job) cpu_count{type="smp"}`, + output: []string{ + `{instance="1", job="api-server"} => 1 @[%v]`, + `{instance="0", job="app-server"} => 5 @[%v]`, + `{instance="1", job="app-server"} => 3 @[%v]`, + `{instance="0", job="api-server"} => 1 @[%v]`, + }, + }, + { + expr: `http_requests{group="production"} < on(instance,job) http_requests{group="canary"}`, + output: []string{ + `{instance="1", job="app-server"} => 600 @[%v]`, + `{instance="0", job="app-server"} => 500 @[%v]`, + `{instance="1", job="api-server"} => 200 @[%v]`, + `{instance="0", job="api-server"} => 100 @[%v]`, + }, + }, + { + expr: `http_requests{group="production"} > on(instance,job) http_requests{group="canary"}`, + output: []string{}, + }, + { + expr: `http_requests{group="production"} == on(instance,job) http_requests{group="canary"}`, + output: []string{}, + }, + { + expr: `http_requests > on(instance) group_left(group,job) cpu_count{type="smp"}`, + output: []string{ + `{group="canary", instance="0", job="app-server"} => 700 @[%v]`, + `{group="canary", instance="1", job="app-server"} => 800 @[%v]`, + `{group="canary", instance="0", job="api-server"} => 300 @[%v]`, + `{group="canary", instance="1", job="api-server"} => 400 @[%v]`, + `{group="production", instance="0", job="app-server"} => 500 @[%v]`, + `{group="production", instance="1", job="app-server"} => 600 @[%v]`, + }, + }, + { + expr: `http_requests / on(instance) 3`, + shouldFail: true, + }, + { + expr: `3 / on(instance) http_requests_total`, + shouldFail: true, + }, + { + expr: `3 / on(instance) 3`, + shouldFail: true, + }, + { + // Missing label list for grouping mod. + expr: `http_requests{group="production"} / on(instance) group_left cpu_count{type="smp"}`, + shouldFail: true, + }, + { + // No group mod allowed for logical operations. + expr: `http_requests{group="production"} or on(instance) group_left(type) cpu_count{type="smp"}`, + shouldFail: true, + }, + { + // No group mod allowed for logical operations. + expr: `http_requests{group="production"} and on(instance) group_left(type) cpu_count{type="smp"}`, + shouldFail: true, + }, + { + // No duplicate use of label. + expr: `http_requests{group="production"} + on(instance) group_left(job,instance) cpu_count{type="smp"}`, + shouldFail: true, + }, + { + expr: `{l="x"} + on(__name__) {l="y"}`, + output: []string{ + `vector_matching_a => 30 @[%v]`, + }, + }, { expr: `absent(nonexistent)`, output: []string{ @@ -975,10 +1166,14 @@ func TestExpressions(t *testing.T) { t.Errorf("%d. Test should fail, but didn't", i) } failed := false + resultStr := ast.EvalToString(testExpr, testEvalTime, ast.Text, storage, stats.NewTimerGroup()) resultLines := strings.Split(resultStr, "\n") - if len(exprTest.output) != len(resultLines) { + if len(exprTest.output) == 0 && strings.Trim(resultStr, "\n") == "" { + // expected and received empty vector, everything is fine + continue + } else if len(exprTest.output) != len(resultLines) { t.Errorf("%d. Number of samples in expected and actual output don't match", i) failed = true }