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 }