diff --git a/.github/contributing-zh.md b/.github/contributing-zh.md index cbff80cd19d..5924246fb46 100644 --- a/.github/contributing-zh.md +++ b/.github/contributing-zh.md @@ -994,7 +994,7 @@ jest 单元测试 | 快照测试 | Jest | | E2E 测试 | Playwright | -每一个组件都应该至少包含一个完整的 jest 单元测试,我们使用 preact 官房推荐的`@testing-library/preact`库来做 DOM 测试, +每一个组件都应该至少包含一个完整的 jest 单元测试,我们使用 preact 官方推荐的`@testing-library/preact`库来做 DOM 测试, > [preact 组件测试](https://preactjs.com/guide/v10/preact-testing-library/) diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000000..a256fb9d30d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "streetsidesoftware.code-spell-checker", + "intellsmi.comment-translate", + "Gruntfuggly.todo-tree" + ] +} \ No newline at end of file diff --git a/packages/base-formula-engine/src/Analysis/Lexer.ts b/packages/base-formula-engine/src/Analysis/Lexer.ts index 1421e4a0535..5394e4cdb1f 100644 --- a/packages/base-formula-engine/src/Analysis/Lexer.ts +++ b/packages/base-formula-engine/src/Analysis/Lexer.ts @@ -1,7 +1,8 @@ import { ErrorType } from '../Basics/ErrorType'; import { DEFAULT_TOKEN_TYPE_LAMBDA_PARAMETER, DEFAULT_TOKEN_TYPE_PARAMETER, DEFAULT_TOKEN_TYPE_ROOT } from '../Basics/TokenType'; import { LexerNode } from './LexerNode'; -import { operatorToken, matchToken, OPERATOR_TOKEN_SET, OPERATOR_TOKEN_PRIORITY, suffixToken, SUFFIX_TOKEN_SET } from '../Basics/Token'; +import { operatorToken, matchToken, OPERATOR_TOKEN_SET, OPERATOR_TOKEN_PRIORITY, suffixToken, SUFFIX_TOKEN_SET, prefixToken } from '../Basics/Token'; +import { Nullable } from '@univer/core'; enum bracketType { NORMAL, @@ -12,6 +13,8 @@ enum bracketType { export class LexerTreeMaker { private _currentLexerNode: LexerNode; + private _upLevel = 0; + private _segment = ''; private _bracketState: bracketType[] = []; // () @@ -39,6 +42,13 @@ export class LexerTreeMaker { private _pushNodeToChildren(value: LexerNode | string, isUnshift = false) { if (value !== '') { const children = this._currentLexerNode.getChildren(); + if (!(value instanceof LexerNode) && this.isColonOpen()) { + const subLexerNode_ref = new LexerNode(); + subLexerNode_ref.setToken(value); + subLexerNode_ref.setParent(this._currentLexerNode); + + value = subLexerNode_ref; + } if (isUnshift) { children.unshift(value); } else { @@ -48,7 +58,7 @@ export class LexerTreeMaker { if (this.isColonOpen()) { this._setAncestorCurrentLexerNode(); - this._closeColon(); + this._closeColon(); /* */ } } @@ -97,14 +107,20 @@ export class LexerTreeMaker { this._lambdaState = false; } - private _openColon() { + private _openColon(upLevel: number) { + this._upLevel = upLevel; this._colonState = true; } private _closeColon() { + this._upLevel = 0; this._colonState = false; } + getUpLevel() { + return this._upLevel; + } + isColonClose() { return this._colonState === false; } @@ -460,9 +476,57 @@ export class LexerTreeMaker { subLexerNode_op.getChildren().push(subLexerNode_left, subLexerNode_right); + let subLexerNode_main = subLexerNode_op; + let upLevel = 0; if (this._segmentCount() > 0) { // e.g. A1:B5 - subLexerNode_left.getChildren().push(this._segment); + + let subLexerNode_minus: Nullable; + let subLexerNode_at: Nullable; + let sliceLength = 0; + if (new RegExp(prefixToken.MINUS, 'g').test(this._segment)) { + subLexerNode_minus = new LexerNode(); + subLexerNode_minus.setToken(prefixToken.MINUS); + sliceLength++; + } + + if (new RegExp(prefixToken.AT, 'g').test(this._segment)) { + subLexerNode_at = new LexerNode(); + subLexerNode_at.setToken(prefixToken.AT); + + if (subLexerNode_minus) { + subLexerNode_minus.addChildren(subLexerNode_at); + subLexerNode_at.setParent(subLexerNode_minus); + } + + sliceLength++; + } + + if (sliceLength > 0) { + this._segment = this._segment.slice(sliceLength); + } + + upLevel = sliceLength; + + if (subLexerNode_at) { + subLexerNode_at.addChildren(subLexerNode_op); + subLexerNode_op.setParent(subLexerNode_at); + if (subLexerNode_at.getParent()) { + subLexerNode_main = subLexerNode_at.getParent(); + } else { + subLexerNode_main = subLexerNode_at; + } + } else if (subLexerNode_minus) { + subLexerNode_main = subLexerNode_minus; + subLexerNode_minus.addChildren(subLexerNode_op); + subLexerNode_op.setParent(subLexerNode_minus); + } + + const subLexerNode_ref = new LexerNode(); + subLexerNode_ref.setToken(this._segment); + subLexerNode_ref.setParent(subLexerNode_left); + + subLexerNode_left.getChildren().push(subLexerNode_ref); this._resetSegment(); } else { // e.g. indirect("A5"):B10 @@ -472,9 +536,9 @@ export class LexerTreeMaker { } } - this._setCurrentLexerNode(subLexerNode_op); + this._setCurrentLexerNode(subLexerNode_main); this._currentLexerNode = subLexerNode_right; - this._openColon(); + this._openColon(upLevel); } else if (SUFFIX_TOKEN_SET.has(currentString) && this.isSingleQuotationClose() && this.isDoubleQuotationClose()) { this._pushNodeToChildren(this._segment); diff --git a/packages/base-formula-engine/src/Analysis/LexerNode.ts b/packages/base-formula-engine/src/Analysis/LexerNode.ts index 2263b2c6296..88b7d429114 100644 --- a/packages/base-formula-engine/src/Analysis/LexerNode.ts +++ b/packages/base-formula-engine/src/Analysis/LexerNode.ts @@ -59,6 +59,10 @@ export class LexerNode { this._children = children; } + addChildren(children: LexerNode | string) { + this._children.push(children); + } + getToken() { return this._token; }