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

This commit is contained in:
Torkel Ödegaard 2014-01-21 12:43:32 +01:00
parent 62edf0d266
commit a6df1a9320
5 changed files with 86 additions and 22 deletions

View File

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

View File

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

View File

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

View File

@ -21,6 +21,16 @@ define([
expect(tokens[4].value).to.be('se1-server-*'); 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() { it('should tokenize functions and args', function() {
var lexer = new Lexer("sum(metric.test, 12, 'test')"); var lexer = new Lexer("sum(metric.test, 12, 'test')");

View File

@ -13,6 +13,24 @@ define([
expect(rootNode.segments[0].value).to.be('metric'); 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() { it('simple function', function() {
var parser = new Parser('sum(test)'); var parser = new Parser('sum(test)');
var rootNode = parser.getAst(); var rootNode = parser.getAst();