Kaynağa Gözat

Partial fix for #10 , the lexer & parser can now handle curly brace, but target editor needs to be updated to support selecting multiple segment nodes

Torkel Ödegaard 12 yıl önce
ebeveyn
işleme
a6df1a9320

+ 1 - 1
src/app/dashboards/default.json

@@ -81,7 +81,7 @@
           ],
           "lines": true,
           "fill": 1,
-          "linewidth": 1,
+          "linewidth": 2,
           "points": false,
           "pointradius": 5,
           "bars": false,

+ 54 - 18
src/app/services/graphite/parser.js

@@ -29,12 +29,47 @@ define([
       }
     },
 
+    curlyBraceSegment: function() {
+      if (this.match('identifier', '{') || this.match('{')) {
+
+        var curlySegment = "";
+
+        while(!this.match('') && !this.match('}')) {
+          curlySegment += this.consumeToken().value;
+        }
+
+        if (!this.match('}')) {
+          this.errorMark("Expected closing '}'");
+        }
+
+        curlySegment += this.consumeToken().value;
+
+        // if curly segment is directly followed by identifier
+        // include it in the segment
+        if (this.match('identifier')) {
+          curlySegment += this.consumeToken().value;
+        }
+
+        return {
+          type: 'segment',
+          value: curlySegment
+        };
+      }
+      else {
+        return null;
+      }
+    },
+
     metricSegment: function() {
+      var curly = this.curlyBraceSegment();
+      if (curly) {
+        return curly;
+      }
+
       if (this.match('identifier')) {
-        this.index++;
         return {
           type: 'segment',
-          value: this.tokens[this.index-1].value
+          value: this.consumeToken().value
         };
       }
 
@@ -42,7 +77,7 @@ define([
         this.errorMark('Expected metric identifier');
       }
 
-      this.index++;
+      this.consumeToken();
 
       if (!this.match('identifier')) {
         this.errorMark('Expected identifier after templateStart');
@@ -50,16 +85,14 @@ define([
 
       var node = {
         type: 'template',
-        value: this.tokens[this.index].value
+        value: this.consumeToken().value
       };
 
-      this.index++;
-
       if (!this.match('templateEnd')) {
         this.errorMark('Expected templateEnd');
       }
 
-      this.index++;
+      this.consumeToken();
       return node;
     },
 
@@ -76,7 +109,7 @@ define([
       node.segments.push(this.metricSegment());
 
       while(this.match('.')) {
-        this.index++;
+        this.consumeToken();
 
         var segment = this.metricSegment();
         if (!segment) {
@@ -96,10 +129,11 @@ define([
 
       var node = {
         type: 'function',
-        name: this.tokens[this.index].value,
+        name: this.consumeToken().value,
       };
 
-      this.index += 2;
+      // consume left paranthesis
+      this.consumeToken();
 
       node.params = this.functionParameters();
 
@@ -107,7 +141,7 @@ define([
         this.errorMark('Expected closing paranthesis');
       }
 
-      this.index++;
+      this.consumeToken();
 
       return node;
     },
@@ -127,7 +161,7 @@ define([
         return [param];
       }
 
-      this.index++;
+      this.consumeToken();
       return [param].concat(this.functionParameters());
     },
 
@@ -136,11 +170,9 @@ define([
         return null;
       }
 
-      this.index++;
-
       return {
         type: 'number',
-        value: parseInt(this.tokens[this.index-1].value, 10)
+        value: parseInt(this.consumeToken().value, 10)
       };
     },
 
@@ -149,13 +181,11 @@ define([
         return null;
       }
 
-      var token = this.tokens[this.index];
+      var token = this.consumeToken();
       if (token.isUnclosed) {
         throw { message: 'Unclosed string parameter', pos: token.pos };
       }
 
-      this.index++;
-
       return {
         type: 'string',
         value: token.value
@@ -171,6 +201,12 @@ define([
       };
     },
 
+    // returns token value and incre
+    consumeToken: function() {
+      this.index++;
+      return this.tokens[this.index-1];
+    },
+
     matchToken: function(type, index) {
       var token = this.tokens[this.index + index];
       return (token === undefined && type === '') ||

+ 1 - 1
src/test/specs/gfunc-specs.js

@@ -60,7 +60,7 @@ define([
 
     it('should return function categories', function() {
       var catIndex = gfunc.getCategories();
-      expect(catIndex.Special.length).to.equal(7);
+      expect(catIndex.Special.length).to.equal(8);
     });
 
   });

+ 10 - 0
src/test/specs/lexer-specs.js

@@ -21,6 +21,16 @@ define([
       expect(tokens[4].value).to.be('se1-server-*');
     });
 
+    it('should tokenize metric expression with curly braces', function() {
+      var lexer = new Lexer('metric.se1-{first, second}.count');
+      var tokens = lexer.tokenize();
+      expect(tokens.length).to.be(10);
+      expect(tokens[3].type).to.be('{');
+      expect(tokens[4].value).to.be('first');
+      expect(tokens[5].value).to.be(',');
+      expect(tokens[6].value).to.be('second');
+    });
+
 
     it('should tokenize functions and args', function() {
       var lexer = new Lexer("sum(metric.test, 12, 'test')");

+ 18 - 0
src/test/specs/parser-specs.js

@@ -13,6 +13,24 @@ define([
       expect(rootNode.segments[0].value).to.be('metric');
     });
 
+    it('simple metric expression with curly braces', function() {
+      var parser = new Parser('metric.se1-{count, max}');
+      var rootNode = parser.getAst();
+
+      expect(rootNode.type).to.be('metric');
+      expect(rootNode.segments.length).to.be(2);
+      expect(rootNode.segments[1].value).to.be('se1-{count,max}');
+    });
+
+    it('simple metric expression with curly braces at start of segment and with post chars', function() {
+      var parser = new Parser('metric.{count, max}-something.count');
+      var rootNode = parser.getAst();
+
+      expect(rootNode.type).to.be('metric');
+      expect(rootNode.segments.length).to.be(3);
+      expect(rootNode.segments[1].value).to.be('{count,max}-something');
+    });
+
     it('simple function', function() {
       var parser = new Parser('sum(test)');
       var rootNode = parser.getAst();