Monaco Editor分词器规则配置问题:全局与局部规则如何共存?
问题与解决方案
问题背景
需求如下:
- 编辑器仅允许使用0~71列,72列及以后的内容需标记为注释
- 若0~71列中出现逗号,逗号及其后的内容也需标记为注释
编写的分词器代码如下,但第一条规则从未触发,第二条规则始终优先匹配:
return { tokenizer: { root: [ [/(,\s+)(.*)/, ['default', 'comment']], [/^(.{0,71})(.*)/, ['default', 'comment']] ], }, };
调整规则顺序为[/,\s+/, { token: 'default', next: '@comment'}]放在第一行后,输入ddd,仍未匹配该规则,直接触发第二条规则。
问题原因
Monaco Editor的分词器规则是按顺序依次匹配,一旦某条规则匹配成功,就会停止后续规则的匹配。
你写的第二条规则/^(.{0,71})(.*)/会匹配整行内容:从行首开始,先匹配0~71个字符,再匹配剩下的所有内容。这条规则的匹配范围覆盖了整行,所以不管行内有没有逗号,它都会优先匹配成功,导致第一条规则永远没有触发的机会。
解决方案
需要调整规则顺序和正则表达式,让逗号的检查能在全局行规则之前匹配到,同时确保正则的匹配范围符合需求。
方案1:合并规则逻辑
通过正则分组,先检查0~71列内是否存在逗号,再处理72列及以后的内容:
return { tokenizer: { root: [ // 匹配0~71列内的逗号:逗号前内容为default,逗号及后续为comment [/^(.{0,70})(,.*)$/, ['default', 'comment']], // 无逗号时,0~71列为default,72列及以后为comment [/^(.{0,71})(.*)$/, ['default', 'comment']] ], }, };
- 第一条规则中,
.{0,70}确保逗号出现在0~71列(逗号本身占1列,所以前面最多70个字符),匹配后将逗号及后续内容标记为注释 - 第二条规则处理没有逗号的行,拆分0~71列和72列以后的内容
方案2:使用状态机
通过定义多状态的分词器,更清晰地处理注释逻辑:
return { tokenizer: { root: [ // 匹配到逗号,标记为comment并进入comment状态 [/,/, 'comment', '@comment'], // 匹配0~71列的内容,之后进入comment状态 [/^.{0,71}/, 'default', '@comment'], ], comment: [ // 匹配剩余所有内容为comment,行尾回到root状态 [/.*$/, 'comment', '@root'] ] }, };
root状态优先检查逗号,匹配后直接进入comment状态,将后续所有内容标记为注释- 无逗号时,先匹配0~71列的内容,再进入
comment状态处理72列及以后的内容 comment状态处理完当前行剩余内容后,回到root状态处理下一行
内容的提问来源于stack exchange,提问作者guoqing deng
相关产品推荐
相关产品推荐

