如何匹配块的开始和结束 [英] How to match the start and end of a block
问题描述
我想定义一个特殊的代码块,它可以由 {[<#
]的字符的任意组合开始,结束将是
{
block-content
}
{##
block-content
##}
#[[< {###
block-content
###}>]]#
可以使用 petitparser-dart 吗?
是的,可以回引用,但不是那么简单。
首先,我们需要一个可以反转分隔符的函数。我想出了以下:
String reverseDelimiter token $ {
return token.split('')。reversed.map((char){
if(char =='[')return']';
if(char = ='{')return'}';
if(char =='<')return'>';
return char;
})。
}
然后我们必须声明 stopDelimiter
解析器。它在这一点上是未定义的,但是一旦我们知道它就会被真正的解析器替换。
var stopDelimiter = undefined();
在 startDelimiter
的操作中, stopDelimiter
与动态创建的解析器如下:
var startDelimiter = pattern('#< {[')。plus()。flatten()。map((String start){
stopDelimiter.set(string ());
return start;
});
其余部分不重要,但取决于您的确切需求:
var blockContents = any()。starLazy(stopDelimiter).flatten
var parser = startDelimiter& blockContents& stopDelimiter;
上面的代码定义了 blockContents
它读取任何东西,直到遇到匹配的 stopDelimiter
。提供的示例通过:
print(parser.parse('{block-content}') );
/ pre>
// Success [1:18]:[{,block-content,}]
print(parser.parse('{## block-content ##}'));
//成功[1:22]:[{##,block-content,##}]
print(parser.parse('#[[< {### block-content ###}>]]#'));
// Success [1:32]:[#[[< {###,block-content,###}>]]#]
如果你想嵌套解析器,上面的代码不工作。如果需要,可以通过记住上一个
stopDelimiter
并恢复该问题来避免该问题。I want to define a special code block, which may starts by any combination of characters of
{[<#
, and the end will be}]>#
.Some example:
{ block-content } {## block-content ##} #[[<{### block-content ###}>]]#
Is it possible with petitparser-dart?
解决方案Yes, back-references are possible, but it is not that straight-forward.
First we need a function that can reverse our delimiter. I came up with the following:
String reverseDelimiter(String token) { return token.split('').reversed.map((char) { if (char == '[') return ']'; if (char == '{') return '}'; if (char == '<') return '>'; return char; }).join(); }
Then we have to declare the
stopDelimiter
parser. It is undefined at this point, but will be replaced with the real parser as soon as we know it.var stopDelimiter = undefined();
In the action of the
startDelimiter
we replace thestopDelimiter
with a dynamically created parser as follows:var startDelimiter = pattern('#<{[').plus().flatten().map((String start) { stopDelimiter.set(string(reverseDelimiter(start)).flatten()); return start; });
The rest is trivial, but depends on your exact requirements:
var blockContents = any().starLazy(stopDelimiter).flatten(); var parser = startDelimiter & blockContents & stopDelimiter;
The code above defines the
blockContents
parser so that it reads through anything until the matchingstopDelimiter
is encountered. The provided examples pass:print(parser.parse('{ block-content }')); // Success[1:18]: [{, block-content , }] print(parser.parse('{## block-content ##}')); // Success[1:22]: [{##, block-content , ##}] print(parser.parse('#[[<{### block-content ###}>]]#')); // Success[1:32]: [#[[<{###, block-content , ###}>]]#]
The above code doesn't work if you want to nest the parser. If necessary, that problem can be avoided by remembering the previous
stopDelimiter
and restoring it.这篇关于如何匹配块的开始和结束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!