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) {
var parser = new Parser($scope.target.target);
var astNode = parser.getAst();
if (parser.error) {
$scope.parserError = parser.error.text + " at position: " + parser.error.pos;
if (astNode.type === 'error') {
$scope.parserError = astNode.message + " at position: " + astNode.pos;
$scope.showTextEditor = true;
return;
}
......
......@@ -124,6 +124,10 @@ function (_) {
defaultParams: ['1d']
});
_.each(categories, function(funcList, catName) {
categories[catName] = _.sortBy(funcList, 'name');
});
function FuncInstance(funcDef) {
this.def = funcDef;
this.params = funcDef.defaultParams.slice(0);
......
......@@ -591,6 +591,15 @@ define([
this.skip();
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 jump = 1; // A length of a jump, after we're done
......
......@@ -3,25 +3,13 @@ define([
], function (Lexer) {
'use strict';
var NodeTypes = {
MetricExpression: 1,
MetricNode: 2,
FunctionCall: 4,
NumericLiteral: 5,
StringLiteral: 6
};
function Parser(expression) {
this.expression = expression;
this.lexer = new Lexer(expression);
this.state = "start";
this.error = null;
this.tokens = this.lexer.tokenize();
this.index = 0;
}
Parser.Nodes = NodeTypes;
Parser.prototype = {
getAst: function () {
......@@ -29,7 +17,16 @@ define([
},
start: function () {
try {
return this.functionCall() || this.metricExpression();
}
catch(e) {
return {
type: 'error',
message: e.message,
pos: e.pos
};
}
},
metricExpression: function() {
......@@ -52,7 +49,6 @@ define([
var rest = this.metricExpression();
if (!rest) {
this.errorMark('Expected metric identifier');
return null;
}
node.segments = node.segments.concat(rest.segments);
......@@ -77,7 +73,6 @@ define([
if (!this.match(')')) {
this.errorMark('Expected closing paranthesis');
return null;
}
this.index++;
......@@ -122,19 +117,24 @@ define([
return null;
}
var token = this.tokens[this.index];
if (token.isUnclosed) {
throw { message: 'Unclosed string parameter', pos: token.pos };
}
this.index++;
return {
type: 'string',
value: this.tokens[this.index-1].value
value: token.value
};
},
errorMark: function(text) {
var currentToken = this.tokens[this.index];
var type = currentToken ? currentToken.type : 'end of string';
this.error = {
text: text + " instead found " + type,
throw {
message: text + " instead found " + type,
pos: currentToken ? currentToken.pos : this.lexer.char
};
},
......
......@@ -30,6 +30,19 @@ define([
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([
var parser = new Parser('metric.test.*.asd.count');
var rootNode = parser.getAst();
expect(parser.error).to.be(null);
expect(rootNode.type).to.be('metric');
expect(rootNode.segments.length).to.be(5);
expect(rootNode.segments[0].value).to.be('metric');
......@@ -17,7 +16,6 @@ define([
it('simple function', function() {
var parser = new Parser('sum(test)');
var rootNode = parser.getAst();
expect(parser.error).to.be(null);
expect(rootNode.type).to.be('function');
expect(rootNode.params.length).to.be(1);
});
......@@ -26,7 +24,6 @@ define([
var parser = new Parser("sum(test, 1, 'test')");
var rootNode = parser.getAst();
expect(parser.error).to.be(null);
expect(rootNode.type).to.be('function');
expect(rootNode.params.length).to.be(3);
expect(rootNode.params[0].type).to.be('metric');
......@@ -38,7 +35,6 @@ define([
var parser = new Parser("sum(scaleToSeconds(test, 1))");
var rootNode = parser.getAst();
expect(parser.error).to.be(null);
expect(rootNode.type).to.be('function');
expect(rootNode.params.length).to.be(1);
expect(rootNode.params[0].type).to.be('function');
......@@ -52,7 +48,6 @@ define([
var parser = new Parser("sum(test.test.*.count, test.timers.*.count)");
var rootNode = parser.getAst();
expect(parser.error).to.be(null);
expect(rootNode.type).to.be('function');
expect(rootNode.params.length).to.be(2);
expect(rootNode.params[0].type).to.be('metric');
......@@ -63,16 +58,24 @@ define([
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);
expect(rootNode.message).to.be('Expected metric identifier instead found end of string');
expect(rootNode.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);
expect(rootNode.message).to.be('Expected closing paranthesis instead found end of string');
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