Skip to content

Commit

Permalink
Partial fix for #10 , the lexer & parser can now handle curly brace, …
Browse files Browse the repository at this point in the history
…but target editor needs to be updated to support selecting multiple segment nodes
  • Loading branch information
torkelo committed Jan 21, 2014
1 parent 62edf0d commit a6df1a9
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/app/dashboards/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
],
"lines": true,
"fill": 1,
"linewidth": 1,
"linewidth": 2,
"points": false,
"pointradius": 5,
"bars": false,
Expand Down
72 changes: 54 additions & 18 deletions src/app/services/graphite/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,37 +29,70 @@ 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
};
}

if (!this.match('templateStart')) {
this.errorMark('Expected metric identifier');
}

this.index++;
this.consumeToken();

if (!this.match('identifier')) {
this.errorMark('Expected identifier after templateStart');
}

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;
},

Expand All @@ -76,7 +109,7 @@ define([
node.segments.push(this.metricSegment());

while(this.match('.')) {
this.index++;
this.consumeToken();

var segment = this.metricSegment();
if (!segment) {
Expand All @@ -96,18 +129,19 @@ 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();

if (!this.match(')')) {
this.errorMark('Expected closing paranthesis');
}

this.index++;
this.consumeToken();

return node;
},
Expand All @@ -127,7 +161,7 @@ define([
return [param];
}

this.index++;
this.consumeToken();
return [param].concat(this.functionParameters());
},

Expand All @@ -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)
};
},

Expand All @@ -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
Expand All @@ -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 === '') ||
Expand Down
2 changes: 1 addition & 1 deletion src/test/specs/gfunc-specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});

});
Expand Down
10 changes: 10 additions & 0 deletions src/test/specs/lexer-specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')");
Expand Down
18 changes: 18 additions & 0 deletions src/test/specs/parser-specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit a6df1a9

Please sign in to comment.