diff --git a/dist/lib/common.js b/dist/lib/common.js index 018e89b..0e08ca7 100644 --- a/dist/lib/common.js +++ b/dist/lib/common.js @@ -46,6 +46,7 @@ function getExpectTypeByToken(prevTokenItem) { switch (curSubType) { // 查看起始和结束 case token_1.TokenSubType.SUBTYPE_START: expectTypeList = [ + [token_1.TokenType.TYPE_SUBEXPR, token_1.TokenSubType.SUBTYPE_STOP], [token_1.TokenType.TYPE_SUBEXPR, token_1.TokenSubType.SUBTYPE_START], [token_1.TokenType.TYPE_SET, token_1.TokenSubType.SUBTYPE_START], [token_1.TokenType.TYPE_FUNCTION, null], diff --git a/dist/lib/token.js b/dist/lib/token.js index 0257819..222b3d3 100644 --- a/dist/lib/token.js +++ b/dist/lib/token.js @@ -112,12 +112,12 @@ function parseLineToken(formulaStr, line, lastTokenItem, lastParentTokenTypeList * @return {ITokenItem} 令牌对象 */ function parseType(formula, prevTokenItem) { - var curParentType = prevTokenItem.parentType; var expectTypeList = common_1.getExpectTypeByToken(prevTokenItem); var tokenItem = parseFormulaStr(formula, expectTypeList); // 如果是结束符时,设置当前类型为父类型 if (tokenItem && tokenItem.subType === token_1.TokenSubType.SUBTYPE_STOP) { - tokenItem.type = curParentType; + // 检测前一个类型是否为闭合直接设置父类型或 + tokenItem.type = isParentToken(prevTokenItem) ? prevTokenItem.type : prevTokenItem.parentType; } return { expectTypeList: expectTypeList, @@ -212,6 +212,16 @@ function isClosedToken(tokenItem) { } return false; } +// 是否为父级元素 +function isParentToken(tokenItem) { + switch (tokenItem.type) { + // 以下类型需要特殊判断 + case token_1.TokenType.TYPE_FUNCTION: + case token_1.TokenType.TYPE_SUBEXPR: + return true; + } + return false; +} /** * 以下为各个匹配数据类型函数 */ diff --git a/package.json b/package.json index 3753e84..62272a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "func-formula-parser", - "version": "0.1.3", + "version": "0.1.4", "description": "a AST parser for formula & formula function", "main": "dist/index.js", "types": "src/index.d.ts", diff --git a/src/lib/common.ts b/src/lib/common.ts index 9cef634..4cfa51b 100644 --- a/src/lib/common.ts +++ b/src/lib/common.ts @@ -48,6 +48,7 @@ export function getExpectTypeByToken(prevTokenItem: ITokenItem): ExpectType[] { switch (curSubType) { // 查看起始和结束 case TokenSubType.SUBTYPE_START: expectTypeList = [ + [TokenType.TYPE_SUBEXPR, TokenSubType.SUBTYPE_STOP], // 函数结束符,空函数 [TokenType.TYPE_SUBEXPR, TokenSubType.SUBTYPE_START], // 子表达式 [TokenType.TYPE_SET, TokenSubType.SUBTYPE_START], // 集合起始 [TokenType.TYPE_FUNCTION, null], diff --git a/src/lib/token.ts b/src/lib/token.ts index 28d69e3..caa54d3 100644 --- a/src/lib/token.ts +++ b/src/lib/token.ts @@ -121,12 +121,12 @@ function parseType(formula: string, prevTokenItem: ITokenItem): { expectTypeList: ExpectType[], item: ITokenItem } { - const curParentType = prevTokenItem.parentType; const expectTypeList: ExpectType[] = getExpectTypeByToken(prevTokenItem); const tokenItem = parseFormulaStr(formula, expectTypeList); // 如果是结束符时,设置当前类型为父类型 if (tokenItem && tokenItem.subType === TokenSubType.SUBTYPE_STOP) { - tokenItem.type = curParentType; + // 检测前一个类型是否为闭合直接设置父类型或 + tokenItem.type = isParentToken(prevTokenItem) ? prevTokenItem.type : prevTokenItem.parentType; } return { expectTypeList, @@ -226,6 +226,17 @@ function isClosedToken(tokenItem: ITokenItem): boolean { return false; } +// 是否为父级元素 +function isParentToken(tokenItem: ITokenItem): boolean { + switch (tokenItem.type) { + // 以下类型需要特殊判断 + case TokenType.TYPE_FUNCTION: + case TokenType.TYPE_SUBEXPR: + return true; + } + return false; +} + /** * 以下为各个匹配数据类型函数 */ diff --git a/test/lib/node.test.js b/test/lib/node.test.js index ddcb83d..2eca611 100644 --- a/test/lib/node.test.js +++ b/test/lib/node.test.js @@ -264,6 +264,45 @@ module.exports = function() { }); }); describe('Function', function() { + it('IF(Empty(),-count(3,4,5),5%)', function() { + formulaParser.setFormula('IF(Empty(),-count(3,4,5),5%)'); + const assertNodeTree = { + token: 'IF', + children: [ + { + token: 'Empty' + }, + { + token: '-', + children: [ + { + token: 'count', + children: [ + { + token: '3' + }, + { + token: '4' + }, + { + token: '5' + } + ] + } + ] + }, + { + token: '%', + children: [ + { + token: '5' + } + ] + } + ] + }; + validTokenReulst(formulaParser.getNodeTree(), assertNodeTree); + }); it('IF(a>=0,-count(3,4,5),5%)', function() { formulaParser.setFormula('IF(a>=0,-count(3,4,5),5%)'); const assertNodeTree = { diff --git a/test/lib/token.test.js b/test/lib/token.test.js index 89cd08e..53345a9 100644 --- a/test/lib/token.test.js +++ b/test/lib/token.test.js @@ -388,6 +388,34 @@ module.exports = function() { }); }); describe('Function', function() { + it('Empty()', function() { + const tokenList = formulaParser.setFormula('Empty()'); + const assertResult = [ + { + parentType: null, + type: TOKEN.TokenType.TYPE_FUNCTION, + subType: TOKEN.TokenSubType.SUBTYPE_START, + token: 'Empty', + row: 1, + start: 0, + end: 6, + sourceStart: 0, + sourceEnd: 6 + }, + { + parentType: null, + type: TOKEN.TokenType.TYPE_FUNCTION, + subType: TOKEN.TokenSubType.SUBTYPE_STOP, + token: '', + row: 1, + start: 6, + end: 7, + sourceStart: 6, + sourceEnd: 7 + } + ]; + validTokenReulst(tokenList, assertResult); + }); it('Round(-1, -5%)', function() { const tokenList = formulaParser.setFormula('Round(-1, -5%)'); const assertResult = [