From 89224401a9cf18c6ae9d4bd9161c5b2cccd6f79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 29 Jan 2014 11:00:25 +0100 Subject: [PATCH] Fixes #38, Lexer & parser now handles metrics segments that begin with numbers or only have numbers --- src/app/services/graphite/lexer.js | 8 ++++---- src/app/services/graphite/parser.js | 6 +++--- src/test/specs/lexer-specs.js | 28 ++++++++++++++++------------ src/test/specs/parser-specs.js | 11 +++++++++++ 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/app/services/graphite/lexer.js b/src/app/services/graphite/lexer.js index ac26463e0bb..88911c9c98f 100644 --- a/src/app/services/graphite/lexer.js +++ b/src/app/services/graphite/lexer.js @@ -116,6 +116,7 @@ define([ for (var i = 0; i < 128; i++) { identifierStartTable[i] = + i >= 48 && i <= 57 || // 0-9 i === 36 || // $ i >= 65 && i <= 90 || // A-Z i === 95 || // _ @@ -183,10 +184,10 @@ define([ } match = - this.scanIdentifier() || - this.scanTemplateSequence() || this.scanPunctuator() || - this.scanNumericLiteral(); + this.scanNumericLiteral() || + this.scanIdentifier() || + this.scanTemplateSequence(); if (match) { this.skip(match.value.length); @@ -402,7 +403,6 @@ define([ } // Numbers must start either with a decimal digit or a point. - if (char !== "." && !isDecimalDigit(char)) { return null; } diff --git a/src/app/services/graphite/parser.js b/src/app/services/graphite/parser.js index f263f01e2ac..f8c7dd80f05 100644 --- a/src/app/services/graphite/parser.js +++ b/src/app/services/graphite/parser.js @@ -66,7 +66,7 @@ define([ return curly; } - if (this.match('identifier')) { + if (this.match('identifier') || this.match('number')) { return { type: 'segment', value: this.consumeToken().value @@ -97,7 +97,7 @@ define([ }, metricExpression: function() { - if (!this.match('templateStart') && !this.match('identifier')) { + if (!this.match('templateStart') && !this.match('identifier') && !this.match('number')) { return null; } @@ -153,8 +153,8 @@ define([ var param = this.functionCall() || - this.metricExpression() || this.numericLiteral() || + this.metricExpression() || this.stringLiteral(); if (!this.match(',')) { diff --git a/src/test/specs/lexer-specs.js b/src/test/specs/lexer-specs.js index 7dd680b7f64..b3ba3a472b4 100644 --- a/src/test/specs/lexer-specs.js +++ b/src/test/specs/lexer-specs.js @@ -31,21 +31,25 @@ define([ expect(tokens[6].value).to.be('second'); }); - - it('should tokenize functions and args', function() { - var lexer = new Lexer("sum(metric.test, 12, 'test')"); + it('should tokenize metric expression with number segments', function() { + var lexer = new Lexer("metric.10.12_10.test"); var tokens = lexer.tokenize(); - expect(tokens[0].value).to.be('sum'); expect(tokens[0].type).to.be('identifier'); - expect(tokens[1].value).to.be('('); - expect(tokens[1].type).to.be('('); - expect(tokens[5].type).to.be(','); - expect(tokens[5].value).to.be(','); + expect(tokens[2].type).to.be('identifier'); + expect(tokens[2].value).to.be('10'); + expect(tokens[4].value).to.be('12_10'); + expect(tokens[4].type).to.be('identifier'); + }); + + it('should tokenize func call with numbered metric and number arg', function() { + var lexer = new Lexer("scale(metric.10, 15)"); + var tokens = lexer.tokenize(); + expect(tokens[0].type).to.be('identifier'); + expect(tokens[2].type).to.be('identifier'); + expect(tokens[2].value).to.be('metric'); + expect(tokens[4].value).to.be('10'); + expect(tokens[4].type).to.be('number'); expect(tokens[6].type).to.be('number'); - expect(tokens[6].value).to.be('12'); - expect(tokens[8].type).to.be('string'); - expect(tokens[8].value).to.be('test'); - expect(tokens[tokens.length - 1].value).to.be(')'); }); it('should tokenize metric with template parameter', function() { diff --git a/src/test/specs/parser-specs.js b/src/test/specs/parser-specs.js index 79f5a9fae4b..68dcb432199 100644 --- a/src/test/specs/parser-specs.js +++ b/src/test/specs/parser-specs.js @@ -13,6 +13,17 @@ define([ expect(rootNode.segments[0].value).to.be('metric'); }); + it('simple metric expression with numbers in segments', function() { + var parser = new Parser('metric.10.15_20.5'); + var rootNode = parser.getAst(); + + expect(rootNode.type).to.be('metric'); + expect(rootNode.segments.length).to.be(4); + expect(rootNode.segments[1].value).to.be('10'); + expect(rootNode.segments[2].value).to.be('15_20'); + expect(rootNode.segments[3].value).to.be('5'); + }); + it('simple metric expression with curly braces', function() { var parser = new Parser('metric.se1-{count, max}'); var rootNode = parser.getAst();