@feedloop/expression-parser
Advanced tools
Comparing version 0.1.5 to 0.1.7
@@ -87,8 +87,15 @@ "use strict"; | ||
return expression.value; | ||
case "string": | ||
return expression.parts | ||
.slice(1) | ||
.reduce(function (string, part, i) { | ||
return string.concat((0, exports.evaluate)(expression.expressions[i], configs, true), part.value); | ||
case "string": { | ||
var concatFn_1 = configs.functions.find(function (fn) { | ||
return fn.name === "Concatenate" && | ||
fn.parameters.every(function (param) { return param.type === "string"; }) && | ||
fn.return.type === "string"; | ||
}); | ||
return expression.parts.slice(1).reduce(function (string, part, i) { | ||
var concat = concatFn_1 | ||
? concatFn_1.evaluate.bind(null, string) | ||
: string.concat.bind(string); | ||
return concat((0, exports.evaluate)(expression.expressions[i], configs, true), part.value); | ||
}, expression.parts[0].value); | ||
} | ||
} | ||
@@ -95,0 +102,0 @@ }; |
@@ -61,8 +61,25 @@ "use strict"; | ||
return "".concat(expression.value); | ||
case "string": | ||
return JSON.stringify(expression.parts | ||
.slice(1) | ||
.reduce(function (string, part, i) { | ||
return string.concat((0, exports.generate)(expression.expressions[i], configs), part.value); | ||
}, expression.parts[0].value)); | ||
case "string": { | ||
var concatFn = configs.functions.find(function (fn) { | ||
return fn.name === "Concatenate" && | ||
fn.parameters.every(function (param) { return param.type === "string"; }) && | ||
fn.return.type === "string"; | ||
}); | ||
return concatFn | ||
? expression.parts | ||
.slice(0, -1) | ||
.map(function (part, i) { return [ | ||
part.value, | ||
(0, exports.generate)(expression.expressions[i], configs), | ||
]; }) | ||
.reduce(function (prevPart, _a) { | ||
var _b = __read(_a, 2), part = _b[0], expr = _b[1]; | ||
return "Concatenate('".concat(part, "', Concatenate(").concat(expr, ", ").concat(prevPart, "))"); | ||
}, "'".concat(expression.parts[expression.parts.length - 1].value, "'")) | ||
: "\"".concat(expression.parts | ||
.slice(1) | ||
.reduce(function (string, part, i) { | ||
return string.concat("{{".concat((0, exports.generate)(expression.expressions[i], configs), "}}"), "".concat(part.value)); | ||
}, "".concat(expression.parts[0].value)), "\""); | ||
} | ||
case "expression": | ||
@@ -69,0 +86,0 @@ return "(".concat((0, exports.generate)(expression.expression, configs), ")"); |
@@ -94,9 +94,17 @@ "use strict"; | ||
var buildExpressionSyntaxParser = function (operatorConfigs) { | ||
var operator = (0, parser_utils_1.oneOf)(operatorConfigs.map(function (config) { | ||
return (0, parser_utils_1.map)((0, exports.text)(config.name), function (name) { return ({ | ||
kind: "operator", | ||
name: name, | ||
unary: !config.left, | ||
}); }); | ||
})); | ||
var binaryOperator = (0, parser_utils_1.map)((0, parser_utils_1.oneOf)(operatorConfigs | ||
.filter(function (config) { return !!config.left; }) | ||
.map(function (config) { return (0, exports.text)(config.name); }) | ||
.concat(exports.nonspaces)), function (name) { return ({ | ||
kind: "operator", | ||
name: name, | ||
unary: false, | ||
}); }); | ||
var unaryOperator = (0, parser_utils_1.map)((0, parser_utils_1.oneOf)(operatorConfigs | ||
.filter(function (config) { return !config.left; }) | ||
.map(function (config) { return (0, exports.text)(config.name); })), function (name) { return ({ | ||
kind: "operator", | ||
name: name, | ||
unary: true, | ||
}); }); | ||
var functionParser = (0, parser_utils_1.chain)(exports.nonspaces, function (name) { | ||
@@ -132,3 +140,3 @@ return (0, parser_utils_1.map)((0, parser_utils_1.between)((0, exports.text)("("), (0, parser_utils_1.sepBy)((0, exports.lexeme)(expression), (0, exports.text)(",")), (0, exports.text)(")")), function (args) { return ({ | ||
subExpression, | ||
operator, | ||
unaryOperator, | ||
string, | ||
@@ -148,4 +156,4 @@ (0, parser_utils_1.map)(exports.number, function (value) { return ({ kind: "number", value: value }); }), | ||
.entries()), false).sort(function (a, b) { return a[0] - b[0]; }); | ||
var reoderTerms = function (termsAndOperators) { | ||
var firstOpIndex = operatorPrecedenceGroup.reduce(function (operator, _a) { | ||
var reorderTerms = function (termsAndOperators) { | ||
var firstValidOperatorIndex = operatorPrecedenceGroup.reduce(function (operator, _a) { | ||
var _b = __read(_a, 2), group = _b[1]; | ||
@@ -158,3 +166,6 @@ return operator === -1 | ||
: operator; | ||
}, -1) || termsAndOperators.findIndex(function (to) { return to.kind === "operator"; }); | ||
}, -1); | ||
var firstOpIndex = firstValidOperatorIndex !== -1 | ||
? firstValidOperatorIndex | ||
: termsAndOperators.findIndex(function (to) { return to.kind === "operator"; }); | ||
if (firstOpIndex === -1) { | ||
@@ -169,10 +180,15 @@ return termsAndOperators[0]; | ||
return firstOpIndex !== 0 && !op.unary | ||
? __assign(__assign({}, op), { left: reoderTerms(leftTermsAndOperators), right: reoderTerms(rightTermsAndOperators) }) : __assign(__assign({}, op), { right: reoderTerms(rightTermsAndOperators) }); | ||
? __assign(__assign({}, op), { left: reorderTerms(leftTermsAndOperators), right: reorderTerms(rightTermsAndOperators) }) : __assign(__assign({}, op), { right: reorderTerms(rightTermsAndOperators) }); | ||
}; | ||
function expression() { | ||
return (0, parser_utils_1.map)((0, parser_utils_1.chain)((0, parser_utils_1.sepBy)(termParser, exports.spaces), function (terms) { | ||
return (0, parser_utils_1.chain)((0, parser_utils_1.chainRec)(termParser, function (expression, expressions) { return [ | ||
(0, exports.lexeme)(expression.kind !== "operator" | ||
? (0, parser_utils_1.spanned)(binaryOperator) | ||
: termParser), | ||
expressions.concat(expression), | ||
]; }, []), function (terms) { | ||
return terms.length | ||
? (0, parser_utils_1.pure)(terms) | ||
: (0, parser_utils_1.map)((0, parser_utils_1.spanned)((0, parser_utils_1.pure)({ kind: "placeholder" })), function (exp) { return [exp]; }); | ||
}), reoderTerms); | ||
? (0, parser_utils_1.pure)(reorderTerms(terms)) | ||
: (0, parser_utils_1.spanned)((0, parser_utils_1.pure)({ kind: "placeholder" })); | ||
}); | ||
} | ||
@@ -179,0 +195,0 @@ return function (input) { return (0, parser_utils_1.parse)((0, parser_utils_1.applyFirst)(expression, exports.eof), input, 0); }; |
{ | ||
"name": "@feedloop/expression-parser", | ||
"version": "0.1.5", | ||
"version": "0.1.7", | ||
"main": "lib/index.js", | ||
@@ -16,3 +16,3 @@ "types": "lib/index.d.ts", | ||
}, | ||
"gitHead": "fcfa6dc6a723b4e64b2fb328f23b1e72dea7e6c4" | ||
"gitHead": "ae0ab03c577bcb92e961fc3656fb81621cdb106a" | ||
} |
@@ -99,13 +99,19 @@ import { VariableConfig } from "."; | ||
case "string": | ||
return expression.parts | ||
.slice(1) | ||
.reduce( | ||
(string, part, i) => | ||
string.concat( | ||
evaluate(expression.expressions[i], configs, true), | ||
part.value | ||
), | ||
expression.parts[0].value | ||
case "string": { | ||
const concatFn = configs.functions.find( | ||
(fn) => | ||
fn.name === "Concatenate" && | ||
fn.parameters.every((param) => param.type === "string") && | ||
fn.return.type === "string" | ||
); | ||
return expression.parts.slice(1).reduce((string, part, i) => { | ||
const concat = concatFn | ||
? concatFn.evaluate.bind(null, string) | ||
: string.concat.bind(string); | ||
return concat( | ||
evaluate(expression.expressions[i], configs, true), | ||
part.value | ||
); | ||
}, expression.parts[0].value); | ||
} | ||
} | ||
@@ -112,0 +118,0 @@ }; |
@@ -66,15 +66,34 @@ import { VariableConfig } from "."; | ||
case "string": | ||
return JSON.stringify( | ||
expression.parts | ||
.slice(1) | ||
.reduce( | ||
(string, part, i) => | ||
string.concat( | ||
generate(expression.expressions[i], configs), | ||
part.value | ||
), | ||
expression.parts[0].value | ||
) | ||
case "string": { | ||
const concatFn = configs.functions.find( | ||
(fn) => | ||
fn.name === "Concatenate" && | ||
fn.parameters.every((param) => param.type === "string") && | ||
fn.return.type === "string" | ||
); | ||
return concatFn | ||
? expression.parts | ||
.slice(0, -1) | ||
.map((part, i) => [ | ||
part.value, | ||
generate(expression.expressions[i], configs), | ||
]) | ||
.reduce( | ||
(prevPart, [part, expr]): string => | ||
`Concatenate('${part}', Concatenate(${expr}, ${prevPart}))`, | ||
`'${ | ||
expression.parts[expression.parts.length - 1].value | ||
}'` as string | ||
) | ||
: `"${expression.parts | ||
.slice(1) | ||
.reduce( | ||
(string, part, i) => | ||
string.concat( | ||
`{{${generate(expression.expressions[i], configs)}}}`, | ||
`${part.value}` | ||
), | ||
`${expression.parts[0].value}` | ||
)}"`; | ||
} | ||
@@ -81,0 +100,0 @@ case "expression": |
@@ -158,14 +158,27 @@ import { | ||
) => { | ||
const operator = oneOf( | ||
operatorConfigs.map((config) => | ||
map( | ||
text(config.name), | ||
(name): OperatorSyntax => ({ | ||
kind: "operator", | ||
name, | ||
unary: !config.left, | ||
}) | ||
) | ||
) | ||
const binaryOperator = map( | ||
oneOf( | ||
operatorConfigs | ||
.filter((config) => !!config.left) | ||
.map((config) => text(config.name)) | ||
.concat(nonspaces) | ||
), | ||
(name): OperatorSyntax => ({ | ||
kind: "operator", | ||
name, | ||
unary: false, | ||
}) | ||
); | ||
const unaryOperator = map( | ||
oneOf( | ||
operatorConfigs | ||
.filter((config) => !config.left) | ||
.map((config) => text(config.name)) | ||
), | ||
(name): OperatorSyntax => ({ | ||
kind: "operator", | ||
name, | ||
unary: true, | ||
}) | ||
); | ||
const functionParser: Parser<FunctionSyntax> = chain(nonspaces, (name) => | ||
@@ -224,3 +237,3 @@ map( | ||
subExpression, | ||
operator, | ||
unaryOperator, | ||
string, | ||
@@ -248,17 +261,20 @@ map(number, (value) => ({ kind: "number", value })), | ||
].sort((a, b) => a[0] - b[0]); | ||
const reoderTerms = ( | ||
const reorderTerms = ( | ||
termsAndOperators: ExpressionSyntax[] | ||
): ExpressionSyntax => { | ||
const firstValidOperatorIndex = operatorPrecedenceGroup.reduce( | ||
(operator, [, group]) => | ||
operator === -1 | ||
? termsAndOperators.findIndex( | ||
(to) => | ||
to.kind === "operator" && | ||
group.map((op) => op.name).includes(to.name) | ||
) | ||
: operator, | ||
-1 | ||
); | ||
const firstOpIndex = | ||
operatorPrecedenceGroup.reduce( | ||
(operator, [, group]) => | ||
operator === -1 | ||
? termsAndOperators.findIndex( | ||
(to) => | ||
to.kind === "operator" && | ||
group.map((op) => op.name).includes(to.name) | ||
) | ||
: operator, | ||
-1 | ||
) || termsAndOperators.findIndex((to) => to.kind === "operator"); | ||
firstValidOperatorIndex !== -1 | ||
? firstValidOperatorIndex | ||
: termsAndOperators.findIndex((to) => to.kind === "operator"); | ||
if (firstOpIndex === -1) { | ||
@@ -276,8 +292,8 @@ return termsAndOperators[0]; | ||
...op, | ||
left: reoderTerms(leftTermsAndOperators), | ||
right: reoderTerms(rightTermsAndOperators), | ||
left: reorderTerms(leftTermsAndOperators), | ||
right: reorderTerms(rightTermsAndOperators), | ||
} | ||
: { | ||
...op, | ||
right: reoderTerms(rightTermsAndOperators), | ||
right: reorderTerms(rightTermsAndOperators), | ||
}; | ||
@@ -287,14 +303,19 @@ }; | ||
function expression() { | ||
return map( | ||
chain( | ||
sepBy(termParser, spaces), | ||
(terms): Parser<ExpressionSyntax[]> => | ||
terms.length | ||
? pure(terms) | ||
: map( | ||
spanned(pure({ kind: "placeholder" } as PlaceholderSyntax)), | ||
(exp) => [exp] | ||
) | ||
return chain( | ||
chainRec( | ||
termParser, | ||
(expression, expressions) => [ | ||
lexeme( | ||
expression.kind !== "operator" | ||
? spanned(binaryOperator as Parser<ExpressionSyntax>) | ||
: termParser | ||
), | ||
expressions.concat(expression), | ||
], | ||
[] as ExpressionSyntax[] | ||
), | ||
reoderTerms | ||
(terms): Parser<ExpressionSyntax> => | ||
terms.length | ||
? pure(reorderTerms(terms)) | ||
: spanned(pure({ kind: "placeholder" } as PlaceholderSyntax)) | ||
) as EagerParser<ExpressionSyntax>; | ||
@@ -301,0 +322,0 @@ } |
@@ -10,3 +10,3 @@ import { generateFromExpression } from "./parseHelpers"; | ||
expect(generateFromExpression('upper("hello world")')).toEqual( | ||
'UPPER("hello world")' | ||
"UPPER('hello world')" | ||
); | ||
@@ -34,2 +34,8 @@ }); | ||
}); | ||
it("should convert string interpolation with concat function", () => { | ||
expect(generateFromExpression('"Hello {{"World"}}"')).toEqual( | ||
"Concatenate('Hello ', Concatenate('World', ''))" | ||
); | ||
}); | ||
}); |
@@ -7,58 +7,53 @@ import { parseExpressionWithoutSuggestions } from "./parseHelpers"; | ||
.toMatchInlineSnapshot(` | ||
Object { | ||
"ast": Object { | ||
"end": 6, | ||
"kind": "operator", | ||
"left": Object { | ||
"end": 4, | ||
"kind": "boolean", | ||
"start": 0, | ||
"type": "boolean", | ||
"value": true, | ||
}, | ||
"name": "&", | ||
"right": Object { | ||
"end": 8, | ||
Object { | ||
"ast": Object { | ||
"end": 6, | ||
"kind": "operator", | ||
"left": undefined, | ||
"name": "!", | ||
"right": Object { | ||
"end": 13, | ||
"left": Object { | ||
"end": 4, | ||
"kind": "boolean", | ||
"start": 8, | ||
"start": 0, | ||
"type": "boolean", | ||
"value": false, | ||
"value": true, | ||
}, | ||
"start": 7, | ||
"name": "&", | ||
"right": Object { | ||
"end": 8, | ||
"kind": "operator", | ||
"left": undefined, | ||
"name": "!", | ||
"right": Object { | ||
"end": 13, | ||
"kind": "boolean", | ||
"start": 8, | ||
"type": "boolean", | ||
"value": false, | ||
}, | ||
"start": 7, | ||
"type": "boolean", | ||
"unary": true, | ||
}, | ||
"start": 5, | ||
"type": "boolean", | ||
"unary": true, | ||
"unary": false, | ||
}, | ||
"start": 5, | ||
"type": "boolean", | ||
"unary": false, | ||
}, | ||
"errors": Array [], | ||
} | ||
`); | ||
"errors": Array [], | ||
} | ||
`); | ||
expect(parseExpressionWithoutSuggestions("true & !!false")) | ||
.toMatchInlineSnapshot(` | ||
Object { | ||
"ast": Object { | ||
"end": 6, | ||
"kind": "operator", | ||
"left": Object { | ||
"end": 4, | ||
"kind": "boolean", | ||
"start": 0, | ||
"type": "boolean", | ||
"value": true, | ||
}, | ||
"name": "&", | ||
"right": Object { | ||
"end": 8, | ||
Object { | ||
"ast": Object { | ||
"end": 6, | ||
"kind": "operator", | ||
"left": undefined, | ||
"name": "!", | ||
"left": Object { | ||
"end": 4, | ||
"kind": "boolean", | ||
"start": 0, | ||
"type": "boolean", | ||
"value": true, | ||
}, | ||
"name": "&", | ||
"right": Object { | ||
"end": 9, | ||
"end": 8, | ||
"kind": "operator", | ||
@@ -68,23 +63,28 @@ "left": undefined, | ||
"right": Object { | ||
"end": 14, | ||
"kind": "boolean", | ||
"start": 9, | ||
"end": 9, | ||
"kind": "operator", | ||
"left": undefined, | ||
"name": "!", | ||
"right": Object { | ||
"end": 14, | ||
"kind": "boolean", | ||
"start": 9, | ||
"type": "boolean", | ||
"value": false, | ||
}, | ||
"start": 8, | ||
"type": "boolean", | ||
"value": false, | ||
"unary": true, | ||
}, | ||
"start": 8, | ||
"start": 7, | ||
"type": "boolean", | ||
"unary": true, | ||
}, | ||
"start": 7, | ||
"start": 5, | ||
"type": "boolean", | ||
"unary": true, | ||
"unary": false, | ||
}, | ||
"start": 5, | ||
"type": "boolean", | ||
"unary": false, | ||
}, | ||
"errors": Array [], | ||
} | ||
`); | ||
"errors": Array [], | ||
} | ||
`); | ||
}); | ||
@@ -94,133 +94,158 @@ | ||
expect(parseExpressionWithoutSuggestions('1 + "2"')).toMatchInlineSnapshot(` | ||
Object { | ||
"ast": Object { | ||
"end": 3, | ||
"kind": "operator", | ||
"left": Object { | ||
"end": 1, | ||
"kind": "number", | ||
"start": 0, | ||
Object { | ||
"ast": Object { | ||
"end": 3, | ||
"kind": "operator", | ||
"left": Object { | ||
"end": 1, | ||
"kind": "number", | ||
"start": 0, | ||
"type": "number", | ||
"value": 1, | ||
}, | ||
"name": "+", | ||
"right": Object { | ||
"end": 7, | ||
"expressions": Array [], | ||
"kind": "string", | ||
"parts": Array [ | ||
Object { | ||
"end": 6, | ||
"start": 5, | ||
"value": "2", | ||
}, | ||
], | ||
"start": 4, | ||
"type": "string", | ||
}, | ||
"start": 2, | ||
"type": "number", | ||
"value": 1, | ||
"unary": false, | ||
}, | ||
"name": "+", | ||
"right": Object { | ||
"end": 7, | ||
"expressions": Array [], | ||
"kind": "string", | ||
"parts": Array [ | ||
Object { | ||
"end": 6, | ||
"start": 5, | ||
"value": "2", | ||
}, | ||
], | ||
"start": 4, | ||
"type": "string", | ||
}, | ||
"start": 2, | ||
"type": "number", | ||
"unary": false, | ||
}, | ||
"errors": Array [ | ||
Object { | ||
"end": 7, | ||
"id": 0, | ||
"message": "expected type of number", | ||
"start": 4, | ||
}, | ||
], | ||
} | ||
`); | ||
"errors": Array [ | ||
Object { | ||
"end": 7, | ||
"id": 0, | ||
"message": "expected type of number", | ||
"start": 4, | ||
}, | ||
], | ||
} | ||
`); | ||
expect(parseExpressionWithoutSuggestions('1 + lower("UPPER")')) | ||
.toMatchInlineSnapshot(` | ||
Object { | ||
"ast": Object { | ||
"end": 3, | ||
"kind": "operator", | ||
"left": Object { | ||
"end": 1, | ||
"kind": "number", | ||
"start": 0, | ||
Object { | ||
"ast": Object { | ||
"end": 3, | ||
"kind": "operator", | ||
"left": Object { | ||
"end": 1, | ||
"kind": "number", | ||
"start": 0, | ||
"type": "number", | ||
"value": 1, | ||
}, | ||
"name": "+", | ||
"right": Object { | ||
"arguments": Array [ | ||
Object { | ||
"end": 17, | ||
"expressions": Array [], | ||
"kind": "string", | ||
"parts": Array [ | ||
Object { | ||
"end": 16, | ||
"start": 11, | ||
"value": "UPPER", | ||
}, | ||
], | ||
"start": 10, | ||
"type": "string", | ||
}, | ||
], | ||
"end": 18, | ||
"kind": "function", | ||
"name": "lower", | ||
"start": 4, | ||
"type": "string", | ||
}, | ||
"start": 2, | ||
"type": "number", | ||
"value": 1, | ||
"unary": false, | ||
}, | ||
"name": "+", | ||
"right": Object { | ||
"arguments": Array [ | ||
Object { | ||
"end": 17, | ||
"expressions": Array [], | ||
"kind": "string", | ||
"parts": Array [ | ||
Object { | ||
"end": 16, | ||
"start": 11, | ||
"value": "UPPER", | ||
}, | ||
], | ||
"start": 10, | ||
"type": "string", | ||
}, | ||
], | ||
"end": 18, | ||
"kind": "function", | ||
"name": "lower", | ||
"start": 4, | ||
"type": "string", | ||
}, | ||
"start": 2, | ||
"type": "number", | ||
"unary": false, | ||
}, | ||
"errors": Array [ | ||
Object { | ||
"end": 18, | ||
"id": 1, | ||
"message": "expected return type of number but got string", | ||
"start": 4, | ||
}, | ||
], | ||
} | ||
`); | ||
"errors": Array [ | ||
Object { | ||
"end": 18, | ||
"id": 1, | ||
"message": "expected return type of number but got string", | ||
"start": 4, | ||
}, | ||
], | ||
} | ||
`); | ||
expect(parseExpressionWithoutSuggestions('lower("UPPER") + 2')) | ||
.toMatchInlineSnapshot(` | ||
Object { | ||
"ast": Object { | ||
"end": 16, | ||
"kind": "operator", | ||
"left": Object { | ||
"arguments": Array [ | ||
Object { | ||
"end": 13, | ||
"expressions": Array [], | ||
"kind": "string", | ||
"parts": Array [ | ||
Object { | ||
"end": 12, | ||
"start": 7, | ||
"value": "UPPER", | ||
}, | ||
], | ||
"start": 6, | ||
"type": "string", | ||
}, | ||
], | ||
"end": 14, | ||
"kind": "function", | ||
"name": "lower", | ||
"start": 0, | ||
"type": "string", | ||
}, | ||
"name": "+", | ||
"right": Object { | ||
"end": 18, | ||
"kind": "number", | ||
"start": 17, | ||
"type": "number", | ||
"value": 2, | ||
}, | ||
"start": 15, | ||
"type": "number", | ||
"unary": false, | ||
}, | ||
"errors": Array [ | ||
Object { | ||
"end": 14, | ||
"id": 2, | ||
"message": "expected return type of number but got string", | ||
"start": 0, | ||
}, | ||
], | ||
} | ||
`); | ||
}); | ||
it("should parse undefined binary operator", () => { | ||
expect(parseExpressionWithoutSuggestions("1 ^ 2")).toMatchInlineSnapshot(` | ||
Object { | ||
"ast": Object { | ||
"end": 16, | ||
"end": 3, | ||
"kind": "operator", | ||
"left": Object { | ||
"arguments": Array [ | ||
Object { | ||
"end": 13, | ||
"expressions": Array [], | ||
"kind": "string", | ||
"parts": Array [ | ||
Object { | ||
"end": 12, | ||
"start": 7, | ||
"value": "UPPER", | ||
}, | ||
], | ||
"start": 6, | ||
"type": "string", | ||
}, | ||
], | ||
"end": 14, | ||
"kind": "function", | ||
"name": "lower", | ||
"start": 0, | ||
"type": "string", | ||
}, | ||
"name": "+", | ||
"right": Object { | ||
"end": 18, | ||
"kind": "number", | ||
"start": 17, | ||
"type": "number", | ||
"value": 2, | ||
}, | ||
"start": 15, | ||
"type": "number", | ||
"left": undefined, | ||
"name": "^", | ||
"right": undefined, | ||
"start": 2, | ||
"type": "any", | ||
"unary": false, | ||
@@ -230,6 +255,6 @@ }, | ||
Object { | ||
"end": 14, | ||
"id": 2, | ||
"message": "expected return type of number but got string", | ||
"start": 0, | ||
"end": 3, | ||
"id": 3, | ||
"message": "operator ^ is not defined", | ||
"start": 2, | ||
}, | ||
@@ -236,0 +261,0 @@ ], |
@@ -111,2 +111,24 @@ import { | ||
}, | ||
{ | ||
name: "Concatenate", | ||
description: "concatenate 2 strings together", | ||
parameters: [ | ||
{ | ||
name: "part", | ||
description: "part of string", | ||
type: "string", | ||
}, | ||
{ | ||
name: "part", | ||
description: "part of string", | ||
type: "string", | ||
}, | ||
], | ||
return: { | ||
type: "string", | ||
}, | ||
examples: [], | ||
evaluate: (str1: string, str2: string) => str1.concat(str2), | ||
generate: (str1: string, str2: string) => `CONCATENATE(${str1}, ${str2})`, | ||
}, | ||
]; | ||
@@ -113,0 +135,0 @@ |
138627
4305