我正在开发一种类似于ruby的语言,名为盖曼,我使用PEG.js来生成解析器。
你知道有没有办法用适当的压痕来实现遗传吗?
xxx = <<<END
hello
world
END产出应是:
"hello
world"我需要这个,因为这个代码看起来不太好:
def foo(arg) {
if arg == "here" then
return <<<END
xxx
xxx
END
end
end这是一个用户希望返回的函数:
"xxx
xxx"我更希望代码看起来像这样:
def foo(arg) {
if arg == "here" then
return <<<END
xxx
xxx
END
end
end如果我修剪所有行,用户将无法在他想要的时候使用带前导空格的字符串。有人知道PEG.js是否允许这样做吗?
我还没有任何遗传密码,只是想确定我想要的东西是否是可能的。
编辑:
所以我尝试实现遗传,问题是PEG不允许反向引用。
heredoc = "<<<" marker:[\w]+ "\n" text:[\s\S]+ marker {
return text.join('');
}它说没有定义标记。至于修整,我想我可以使用location()函数
发布于 2021-10-15 09:59:52
下面是遗传在PEG.js的继承中的实现,它不再被维护。此代码基于GitHub问题。
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 []; }编辑:上面的没有使用另一段代码,下面是更好的语法:
{ 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 .)*发布于 2021-10-14 17:44:26
我不认为这是对解析器生成器的合理期望;很少有语法分析器生成器能够胜任这一挑战。
首先,识别这里的字符串语法本质上是上下文敏感的,因为结束分隔符必须是<<<令牌之后提供的分隔符的精确副本。因此,您需要一个自定义词法分析器,这意味着您需要一个语法分析器生成器,它允许您使用自定义词法分析器。(因此,假设您想要一个没有扫描的解析器的解析器生成器可能不是最佳选择。)
识别这里-字符串标记的结尾应该不会太困难,尽管您不能用一个正则表达式来完成它。我的方法是使用一个自定义的扫描函数,它将这里的字符串分解成一系列的行,并将它们连接起来,直到到达只包含结束分隔符的行为止。
一旦您识别了文字的文本,您就需要以您想要的方式规范这些空格,只需要<<<开始时的列号。这样,您可以修剪字符串文字中的每一行。因此,您只需要一个准确地报告标记位置的词法扫描器。修整通常不会在生成的词法扫描器中完成;相反,它将是相关的语义操作。(同样,它也可能是语法中的语义动作。但它总是你编写的代码。)
当您修剪文字时,您将需要处理不可能的情况,因为用户没有遵守缩进要求。您需要对选项卡字符做一些事情;正确的选项卡字符可能意味着您需要一个词汇扫描器来计算可见的列位置,而不是字符偏移量。
我不知道peg.js是否符合这些要求,因为我不使用它。(我确实查看了文档,但没有看到任何关于如何合并自定义扫描功能的指示。但这并不意味着没有办法这样做。)我希望上面的讨论至少可以让您查看您想要使用的解析器生成器的详细文档,否则可以找到一个不同的解析器生成器,它将在这个用例中为您工作。
https://stackoverflow.com/questions/69566480
复制相似问题