Просмотр исходного кода

parser and lexer is working ok

Torkel Ödegaard 12 лет назад
Родитель
Сommit
e19d3a531c

+ 16 - 16
grafana.sublime-project

@@ -1,18 +1,18 @@
 {
 {
-	"folders":
-	[
-		{
-			"follow_symlinks": true,
-			"path": ".",
-			"folder_exclude_patterns": [
-				"node_modules"
-			]
-		}
-	],
-	"settings":
-	{
-		"tab_size": 2,
-		"translate_tabs_to_spaces": true,
-		"trim_trailing_white_space_on_save": true
-	}
+  "folders":
+  [
+    {
+      "follow_symlinks": true,
+      "path": ".",
+      "folder_exclude_patterns": [
+        "node_modules"
+      ]
+    }
+  ],
+  "settings":
+  {
+    "tab_size": 2,
+    "translate_tabs_to_spaces": true,
+    "trim_trailing_white_space_on_save": true
+  }
 }
 }

+ 11 - 5
src/app/services/graphite/lexer.js

@@ -339,7 +339,8 @@ define([
 
 
       return {
       return {
         type: type,
         type: type,
-        value: id
+        value: id,
+        pos: this.char
       };
       };
 
 
     },
     },
@@ -407,7 +408,8 @@ define([
               return {
               return {
                 type: 'number',
                 type: 'number',
                 value: value,
                 value: value,
-                isMalformed: true
+                isMalformed: true,
+                pos: this.char
               };
               };
             }
             }
 
 
@@ -422,7 +424,8 @@ define([
               type: 'number',
               type: 'number',
               value: value,
               value: value,
               base: 16,
               base: 16,
-              isMalformed: false
+              isMalformed: false,
+              pos: this.char
             };
             };
           }
           }
 
 
@@ -538,6 +541,7 @@ define([
         type: 'number',
         type: 'number',
         value: value,
         value: value,
         base: 10,
         base: 10,
+        pos: this.char,
         isMalformed: !isFinite(value)
         isMalformed: !isFinite(value)
       };
       };
     },
     },
@@ -554,7 +558,8 @@ define([
       case "}":
       case "}":
         return {
         return {
           type: ch1,
           type: ch1,
-          value: ch1
+          value: ch1,
+          pos: this.char
         };
         };
       }
       }
 
 
@@ -658,7 +663,8 @@ define([
         type: 'string',
         type: 'string',
         value: value,
         value: value,
         isUnclosed: false,
         isUnclosed: false,
-        quote: quote
+        quote: quote,
+        pos: this.char
       };
       };
     },
     },
 
 

+ 23 - 30
src/app/services/graphite/parser.js

@@ -54,23 +54,17 @@ define([
       if (this.match('.')) {
       if (this.match('.')) {
         this.index++;
         this.index++;
         var rest = this.metricExpression();
         var rest = this.metricExpression();
+        if (!rest) {
+          this.errorMark('Expected metric identifier');
+          return null;
+        }
+
         node.segments = node.segments.concat(rest.segments)
         node.segments = node.segments.concat(rest.segments)
       }
       }
 
 
       return node;
       return node;
     },
     },
 
 
-    matchToken: function(type, index) {
-      var token = this.tokens[this.index + index];
-      return (token === undefined && type === '') ||
-             token && token.type === type;
-    },
-
-    match: function(token1, token2) {
-      return this.matchToken(token1, 0) &&
-        (!token2 || this.matchToken(token2, 1))
-    },
-
     functionCall: function() {
     functionCall: function() {
       if (!this.match('identifier', '(')) {
       if (!this.match('identifier', '(')) {
         return null;
         return null;
@@ -86,7 +80,7 @@ define([
       node.params = this.functionParameters();
       node.params = this.functionParameters();
 
 
       if (!this.match(')')) {
       if (!this.match(')')) {
-        this.error = 'missing closing paranthesis';
+        this.errorMark('Expected closing paranthesis');
         return null;
         return null;
       }
       }
 
 
@@ -140,27 +134,26 @@ define([
       };
       };
     },
     },
 
 
-    isUnexpectedToken: function (expected, value) {
-      if (this.token === null) {
-        this.error = "Expected token: " + expected + " instead found end of string";
-        return true;
-      }
-
-      if (this.token.type === expected) {
-        return false;
-      }
-
-      if (value && this.token.value === value) {
-        return false;
-      }
+    errorMark: function(text) {
+      var currentToken = this.tokens[this.index];
+      var type = currentToken ? currentToken.type : 'end of string';
+      this.error = {
+        text: text + " instead found " + type,
+        pos: currentToken ? currentToken.pos : this.lexer.char
+      };
+    },
 
 
-      this.error = "Expected  token " + expected +
-          ' instead found token ' + this.token.type +
-          ' ("'  + this.token.value + '")' +
-          " at position: " + this.lexer.char;
+    matchToken: function(type, index) {
+      var token = this.tokens[this.index + index];
+      return (token === undefined && type === '') ||
+             token && token.type === type;
+    },
 
 
-      return true;
+    match: function(token1, token2) {
+      return this.matchToken(token1, 0) &&
+        (!token2 || this.matchToken(token2, 1))
     },
     },
+
   };
   };
 
 
   return Parser;
   return Parser;

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

@@ -11,6 +11,7 @@ define([
       expect(tokens[1].value).to.be('.');
       expect(tokens[1].value).to.be('.');
       expect(tokens[2].type).to.be('identifier');
       expect(tokens[2].type).to.be('identifier');
       expect(tokens[4].type).to.be('identifier');
       expect(tokens[4].type).to.be('identifier');
+      expect(tokens[4].pos).to.be(13);
     });
     });
 
 
     it('should tokenize functions and args', function() {
     it('should tokenize functions and args', function() {

+ 17 - 2
src/test/specs/parser-specs.js

@@ -2,7 +2,7 @@ define([
   '../../app/services/graphite/Parser'
   '../../app/services/graphite/Parser'
 ], function(Parser) {
 ], function(Parser) {
 
 
-  describe('when parsing graphite expression', function() {
+  describe('when parsing', function() {
 
 
     it('simple metric expression', function() {
     it('simple metric expression', function() {
       var parser = new Parser('metric.test.*.asd.count');
       var parser = new Parser('metric.test.*.asd.count');
@@ -12,7 +12,6 @@ define([
       expect(rootNode.type).to.be('metric');
       expect(rootNode.type).to.be('metric');
       expect(rootNode.segments.length).to.be(5);
       expect(rootNode.segments.length).to.be(5);
       expect(rootNode.segments[0].value).to.be('metric');
       expect(rootNode.segments[0].value).to.be('metric');
-
     });
     });
 
 
     it('simple function', function() {
     it('simple function', function() {
@@ -60,6 +59,22 @@ define([
       expect(rootNode.params[1].type).to.be('metric');
       expect(rootNode.params[1].type).to.be('metric');
     });
     });
 
 
+    it('invalid metric expression', function() {
+      var parser = new Parser('metric.test.*.asd.');
+      var rootNode = parser.getAst();
+
+      expect(parser.error.text).to.be('Expected metric identifier instead found end of string');
+      expect(parser.error.pos).to.be(19);
+    });
+
+    it('invalid function expression missing closing paranthesis', function() {
+      var parser = new Parser('sum(test');
+      var rootNode = parser.getAst();
+
+      expect(parser.error.text).to.be('Expected closing paranthesis instead found end of string');
+      expect(parser.error.pos).to.be(9);
+    });
+
   });
   });
 
 
 });
 });