首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用PEG.js实现带修剪缩进的遗传

用PEG.js实现带修剪缩进的遗传
EN

Stack Overflow用户
提问于 2021-10-14 07:14:26
回答 2查看 64关注 0票数 0

我正在开发一种类似于ruby的语言,名为盖曼,我使用PEG.js来生成解析器。

你知道有没有办法用适当的压痕来实现遗传吗?

代码语言:javascript
复制
xxx =  <<<END
       hello
       world
       END

产出应是:

代码语言:javascript
复制
"hello
world"

我需要这个,因为这个代码看起来不太好:

代码语言:javascript
复制
def foo(arg) {
  if arg == "here" then
     return <<<END
xxx
  xxx
END
  end
end

这是一个用户希望返回的函数:

代码语言:javascript
复制
"xxx
  xxx"

我更希望代码看起来像这样:

代码语言:javascript
复制
def foo(arg) {
  if arg == "here" then
     return <<<END
            xxx
              xxx
            END
  end
end

如果我修剪所有行,用户将无法在他想要的时候使用带前导空格的字符串。有人知道PEG.js是否允许这样做吗?

我还没有任何遗传密码,只是想确定我想要的东西是否是可能的。

编辑:

所以我尝试实现遗传,问题是PEG不允许反向引用。

代码语言:javascript
复制
heredoc = "<<<" marker:[\w]+ "\n" text:[\s\S]+ marker {
    return text.join('');
}

它说没有定义标记。至于修整,我想我可以使用location()函数

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-10-15 09:59:52

下面是遗传在PEG.js的继承中的实现,它不再被维护。此代码基于GitHub问题

代码语言:javascript
复制
heredoc = "<<<" begin:marker "\n" text:($any_char+ "\n")+ _ end:marker (
    &{ return begin === end; }
  / '' { error(`Expected matched marker "${begin}", but marker "${end}" was found`); }
) {
    const loc = location();
    const min = loc.start.column - 1;
    const re = new RegExp(`\\s{${min}}`);
    return text.map(line => {
        return line[0].replace(re, '');
    }).join('\n');
}
any_char = (!"\n" .)
marker_char = (!" " !"\n" .)
marker "Marker" = $marker_char+

_ "whitespace"
  = [ \t\n\r]* { return []; }

编辑:上面的没有使用另一段代码,下面是更好的语法:

代码语言:javascript
复制
{ let heredoc_begin = null; }

heredoc = "<<<" beginMarker "\n" text:content endMarker {
    const loc = location();
    const min = loc.start.column - 1;
    const re = new RegExp(`^\\s{${min}}`, 'mg');
    return {
        type: 'Literal',
        value: text.replace(re, '')
    };
}
__ = (!"\n" !" " .)
marker 'Marker' = $__+
beginMarker = m:marker { heredoc_begin = m; }
endMarker = "\n" " "* end:marker &{ return heredoc_begin === end; }
content = $(!endMarker .)*
票数 0
EN

Stack Overflow用户

发布于 2021-10-14 17:44:26

我不认为这是对解析器生成器的合理期望;很少有语法分析器生成器能够胜任这一挑战。

首先,识别这里的字符串语法本质上是上下文敏感的,因为结束分隔符必须是<<<令牌之后提供的分隔符的精确副本。因此,您需要一个自定义词法分析器,这意味着您需要一个语法分析器生成器,它允许您使用自定义词法分析器。(因此,假设您想要一个没有扫描的解析器的解析器生成器可能不是最佳选择。)

识别这里-字符串标记的结尾应该不会太困难,尽管您不能用一个正则表达式来完成它。我的方法是使用一个自定义的扫描函数,它将这里的字符串分解成一系列的行,并将它们连接起来,直到到达只包含结束分隔符的行为止。

一旦您识别了文字的文本,您就需要以您想要的方式规范这些空格,只需要<<<开始时的列号。这样,您可以修剪字符串文字中的每一行。因此,您只需要一个准确地报告标记位置的词法扫描器。修整通常不会在生成的词法扫描器中完成;相反,它将是相关的语义操作。(同样,它也可能是语法中的语义动作。但它总是你编写的代码。)

当您修剪文字时,您将需要处理不可能的情况,因为用户没有遵守缩进要求。您需要对选项卡字符做一些事情;正确的选项卡字符可能意味着您需要一个词汇扫描器来计算可见的列位置,而不是字符偏移量。

我不知道peg.js是否符合这些要求,因为我不使用它。(我确实查看了文档,但没有看到任何关于如何合并自定义扫描功能的指示。但这并不意味着没有办法这样做。)我希望上面的讨论至少可以让您查看您想要使用的解析器生成器的详细文档,否则可以找到一个不同的解析器生成器,它将在这个用例中为您工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69566480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档