Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/parser/src/scriptParser/scriptParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const scriptParser = (
const commentSplit = sentenceRaw.split(/(?<!\\);/);
let newSentenceRaw = commentSplit[0];
newSentenceRaw = newSentenceRaw.replaceAll('\\;',';');
const sentenceComment = commentSplit[1] ?? '';
const sentenceComment = commentSplit.slice(1).join(';');
Comment on lines 40 to +43

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

使用 split 正则表达式然后 slice(1).join(';') 的做法效率较低,因为它会把整行文本按照所有未转义的分号全部切分,生成一个字符串数组,然后再把它们重新拼接起来。\n\n实际上,我们只需要找到第一个未转义的分号,然后将字符串一分为二即可。使用 RegExp.prototype.exec 找到第一个匹配项的索引,再通过 substring 截取,可以完全避免不必要的数组分配和字符串拼接,从而提升解析器的性能(特别是在注释中包含较多分号的情况下)。

  const match = /(?<!\\);/.exec(sentenceRaw);\n  let newSentenceRaw = match ? sentenceRaw.substring(0, match.index) : sentenceRaw;\n  newSentenceRaw = newSentenceRaw.replaceAll('\\;', ';');\n  const sentenceComment = match ? sentenceRaw.substring(match.index + 1) : '';

if (newSentenceRaw.trim() === '') {
// 注释提前返回
return {
Expand Down
38 changes: 38 additions & 0 deletions packages/parser/test/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,25 @@ test("escaped semicolon is preserved in content and inline comment is preserved"
expect(result.sentenceList).toContainEqual(expectSentenceItem);
});

test("inline comment preserves following semicolons", async () => {
const parser = new SceneParser((assetList) => {
}, (fileName, assetType) => {
return fileName;
}, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG);

const result = parser.parse(`say:123; first; second; third`, 'test', 'test');
const expectSentenceItem: ISentence = {
command: commandType.say,
commandRaw: "say",
content: "123",
args: [],
sentenceAssets: [],
subScene: [],
inlineComment: "first; second; third"
};
expect(result.sentenceList).toContainEqual(expectSentenceItem);
});

test("comment-only line keeps comment in content", async () => {
const parser = new SceneParser((assetList) => {
}, (fileName, assetType) => {
Expand All @@ -344,3 +363,22 @@ test("comment-only line keeps comment in content", async () => {
};
expect(result.sentenceList).toContainEqual(expectSentenceItem);
});

test("comment-only line preserves following semicolons", async () => {
const parser = new SceneParser((assetList) => {
}, (fileName, assetType) => {
return fileName;
}, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG);

const result = parser.parse(`; first; second; third`, 'test', 'test');
const expectSentenceItem: ISentence = {
command: commandType.comment,
commandRaw: "comment",
content: "first; second; third",
args: [{ key: 'next', value: true }],
sentenceAssets: [],
subScene: [],
inlineComment: ""
};
expect(result.sentenceList).toContainEqual(expectSentenceItem);
});
Loading