You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于PEG.js实现支持缩进修剪的heredoc功能方案咨询

结论

PEG.js完全可以实现你需要的带智能缩进修剪的heredoc功能,你遇到的两个核心问题都有成熟的解决方案。


解决marker反向引用问题

你原来的写法报错是因为PEG.js的静态规则不能直接引用前面捕获的变量作为匹配条件,需要用语义谓词(&{} 或前置动态校验)实现运行时的marker匹配,基础规则示例如下:

// 基础词法规则
word_char = [a-zA-Z0-9_]
eol = "\r\n" / "\n" / "\r"
sp = " " / "\t"
line = $([^\r\n]* eol)

// heredoc核心规则
heredoc
  = "<<<" marker:$(word_char+) eol
    text:line*
    // 先捕获结束行的前导空格,再校验后面是marker标记(不消耗输入)
    end_prefix:$(sp*) &(marker eol?)
    // 正式匹配结束标记行,消耗输入
    marker eol?
    {
      // 这里写缩进处理逻辑
    }

语义谓词的作用是在运行时动态校验当前位置是否符合匹配条件,此时你已经可以拿到前面捕获的marker变量,完全解决了反向引用的问题。


实现智能缩进修剪

你提到用位置信息处理的思路是可行的,更简单的方案是直接拿结束标记前的空格长度作为全局修剪长度,完全符合你的需求:结束标记缩进到哪一级,所有内容行就统一砍掉相同长度的前导空格,用户如果需要保留字符串前置空格,只要内容行的缩进比结束标记更深即可。
完整的动作逻辑示例如下:

heredoc
  = "<<<" marker:$(word_char+) eol
    text:line*
    end_prefix:$(sp*) &(marker eol?)
    marker eol?
    {
      const trim_len = end_prefix.length;
      const processedText = text.map(line => {
        // 计算当前行的前导空格长度
        const linePrefixLen = line.match(/^[ \t]*/)[0].length;
        // 最多砍掉trim_len长度的前导空格,避免截断用户主动保留的缩进
        return line.slice(Math.min(linePrefixLen, trim_len));
      }).join('');
      // 可选:去掉末尾多余的换行
      return processedText.replace(/\n$/, '');
    }

这套逻辑运行后完全符合你给出的示例效果,不会误删用户需要保留的前置空格,代码格式也足够美观。


内容的提问来源于stack exchange,提问作者jcubic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 08:15:02