Commit 2acfa83b by Torkel Ödegaard

fixed sorting of functions, and lexing parsing fix for unclosed string params

parent 38609fb9
...@@ -27,8 +27,8 @@ function (angular, _, config, graphiteFuncs, Parser) { ...@@ -27,8 +27,8 @@ function (angular, _, config, graphiteFuncs, Parser) {
var parser = new Parser($scope.target.target); var parser = new Parser($scope.target.target);
var astNode = parser.getAst(); var astNode = parser.getAst();
if (parser.error) { if (astNode.type === 'error') {
$scope.parserError = parser.error.text + " at position: " + parser.error.pos; $scope.parserError = astNode.message + " at position: " + astNode.pos;
$scope.showTextEditor = true; $scope.showTextEditor = true;
return; return;
} }
......
...@@ -124,6 +124,10 @@ function (_) { ...@@ -124,6 +124,10 @@ function (_) {
defaultParams: ['1d'] defaultParams: ['1d']
}); });
_.each(categories, function(funcList, catName) {
categories[catName] = _.sortBy(funcList, 'name');
});
function FuncInstance(funcDef) { function FuncInstance(funcDef) {
this.def = funcDef; this.def = funcDef;
this.params = funcDef.defaultParams.slice(0); this.params = funcDef.defaultParams.slice(0);
......
...@@ -591,6 +591,15 @@ define([ ...@@ -591,6 +591,15 @@ define([
this.skip(); this.skip();
while (this.peek() !== quote) { while (this.peek() !== quote) {
if (this.peek() === "") { // End Of Line
return {
type: 'string',
value: value,
isUnclosed: true,
quote: quote,
pos: this.char
};
}
var char = this.peek(); var char = this.peek();
var jump = 1; // A length of a jump, after we're done var jump = 1; // A length of a jump, after we're done
......
...@@ -3,25 +3,13 @@ define([ ...@@ -3,25 +3,13 @@ define([
], function (Lexer) { ], function (Lexer) {
'use strict'; 'use strict';
var NodeTypes = {
MetricExpression: 1,
MetricNode: 2,
FunctionCall: 4,
NumericLiteral: 5,
StringLiteral: 6
};
function Parser(expression) { function Parser(expression) {
this.expression = expression; this.expression = expression;
this.lexer = new Lexer(expression); this.lexer = new Lexer(expression);
this.state = "start";
this.error = null;
this.tokens = this.lexer.tokenize(); this.tokens = this.lexer.tokenize();
this.index = 0; this.index = 0;
} }
Parser.Nodes = NodeTypes;
Parser.prototype = { Parser.prototype = {
getAst: function () { getAst: function () {
...@@ -29,7 +17,16 @@ define([ ...@@ -29,7 +17,16 @@ define([
}, },
start: function () { start: function () {
try {
return this.functionCall() || this.metricExpression(); return this.functionCall() || this.metricExpression();
}
catch(e) {
return {
type: 'error',
message: e.message,
pos: e.pos
};
}
}, },
metricExpression: function() { metricExpression: function() {
...@@ -52,7 +49,6 @@ define([ ...@@ -52,7 +49,6 @@ define([
var rest = this.metricExpression(); var rest = this.metricExpression();
if (!rest) { if (!rest) {
this.errorMark('Expected metric identifier'); this.errorMark('Expected metric identifier');
return null;
} }
node.segments = node.segments.concat(rest.segments); node.segments = node.segments.concat(rest.segments);
...@@ -77,7 +73,6 @@ define([ ...@@ -77,7 +73,6 @@ define([
if (!this.match(')')) { if (!this.match(')')) {
this.errorMark('Expected closing paranthesis'); this.errorMark('Expected closing paranthesis');
return null;
} }
this.index++; this.index++;
...@@ -122,19 +117,24 @@ define([ ...@@ -122,19 +117,24 @@ define([
return null; return null;
} }
var token = this.tokens[this.index];
if (token.isUnclosed) {
throw { message: 'Unclosed string parameter', pos: token.pos };
}
this.index++; this.index++;
return { return {
type: 'string', type: 'string',
value: this.tokens[this.index-1].value value: token.value
}; };
}, },
errorMark: function(text) { errorMark: function(text) {
var currentToken = this.tokens[this.index]; var currentToken = this.tokens[this.index];
var type = currentToken ? currentToken.type : 'end of string'; var type = currentToken ? currentToken.type : 'end of string';
this.error = { throw {
text: text + " instead found " + type, message: text + " instead found " + type,
pos: currentToken ? currentToken.pos : this.lexer.char pos: currentToken ? currentToken.pos : this.lexer.char
}; };
}, },
......
...@@ -30,6 +30,19 @@ define([ ...@@ -30,6 +30,19 @@ define([
expect(tokens[tokens.length - 1].value).to.be(')'); expect(tokens[tokens.length - 1].value).to.be(')');
}); });
it('should handle error with unterminated string', function() {
var lexer = new Lexer("alias(metric, 'asd)");
var tokens = lexer.tokenize();
expect(tokens[0].value).to.be('alias');
expect(tokens[1].value).to.be('(');
expect(tokens[2].value).to.be('metric');
expect(tokens[3].value).to.be(',');
expect(tokens[4].type).to.be('string');
expect(tokens[4].isUnclosed).to.be(true);
expect(tokens[4].pos).to.be(20);
});
}); });
}); });
...@@ -8,7 +8,6 @@ define([ ...@@ -8,7 +8,6 @@ define([
var parser = new Parser('metric.test.*.asd.count'); var parser = new Parser('metric.test.*.asd.count');
var rootNode = parser.getAst(); var rootNode = parser.getAst();
expect(parser.error).to.be(null);
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');
...@@ -17,7 +16,6 @@ define([ ...@@ -17,7 +16,6 @@ define([
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();
expect(parser.error).to.be(null);
expect(rootNode.type).to.be('function'); expect(rootNode.type).to.be('function');
expect(rootNode.params.length).to.be(1); expect(rootNode.params.length).to.be(1);
}); });
...@@ -26,7 +24,6 @@ define([ ...@@ -26,7 +24,6 @@ define([
var parser = new Parser("sum(test, 1, 'test')"); var parser = new Parser("sum(test, 1, 'test')");
var rootNode = parser.getAst(); var rootNode = parser.getAst();
expect(parser.error).to.be(null);
expect(rootNode.type).to.be('function'); expect(rootNode.type).to.be('function');
expect(rootNode.params.length).to.be(3); expect(rootNode.params.length).to.be(3);
expect(rootNode.params[0].type).to.be('metric'); expect(rootNode.params[0].type).to.be('metric');
...@@ -38,7 +35,6 @@ define([ ...@@ -38,7 +35,6 @@ define([
var parser = new Parser("sum(scaleToSeconds(test, 1))"); var parser = new Parser("sum(scaleToSeconds(test, 1))");
var rootNode = parser.getAst(); var rootNode = parser.getAst();
expect(parser.error).to.be(null);
expect(rootNode.type).to.be('function'); expect(rootNode.type).to.be('function');
expect(rootNode.params.length).to.be(1); expect(rootNode.params.length).to.be(1);
expect(rootNode.params[0].type).to.be('function'); expect(rootNode.params[0].type).to.be('function');
...@@ -52,7 +48,6 @@ define([ ...@@ -52,7 +48,6 @@ define([
var parser = new Parser("sum(test.test.*.count, test.timers.*.count)"); var parser = new Parser("sum(test.test.*.count, test.timers.*.count)");
var rootNode = parser.getAst(); var rootNode = parser.getAst();
expect(parser.error).to.be(null);
expect(rootNode.type).to.be('function'); expect(rootNode.type).to.be('function');
expect(rootNode.params.length).to.be(2); expect(rootNode.params.length).to.be(2);
expect(rootNode.params[0].type).to.be('metric'); expect(rootNode.params[0].type).to.be('metric');
...@@ -63,16 +58,24 @@ define([ ...@@ -63,16 +58,24 @@ define([
var parser = new Parser('metric.test.*.asd.'); var parser = new Parser('metric.test.*.asd.');
var rootNode = parser.getAst(); var rootNode = parser.getAst();
expect(parser.error.text).to.be('Expected metric identifier instead found end of string'); expect(rootNode.message).to.be('Expected metric identifier instead found end of string');
expect(parser.error.pos).to.be(19); expect(rootNode.pos).to.be(19);
}); });
it('invalid function expression missing closing paranthesis', function() { it('invalid function expression missing closing paranthesis', function() {
var parser = new Parser('sum(test'); var parser = new Parser('sum(test');
var rootNode = parser.getAst(); var rootNode = parser.getAst();
expect(parser.error.text).to.be('Expected closing paranthesis instead found end of string'); expect(rootNode.message).to.be('Expected closing paranthesis instead found end of string');
expect(parser.error.pos).to.be(9); expect(rootNode.pos).to.be(9);
});
it('unclosed string in function', function() {
var parser = new Parser("sum('test)");
var rootNode = parser.getAst();
expect(rootNode.message).to.be('Unclosed string parameter');
expect(rootNode.pos).to.be(11);
}); });
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment