使用语法解析可能嵌套的大括号项
Parsing a possibly nested braced item using a grammar
我开始编写 BibTeX 解析器。我想做的第一件事是解析一个支撑项。例如,花括号项可以是作者字段或标题。字段中可能有嵌套的大括号。以下代码 不 处理嵌套大括号:
use v6;
my $str = q:to/END/;
author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},
END
$str .= chomp;
grammar ExtractBraced {
rule TOP {
'author=' <braced-item> .*
}
rule braced-item { '{' <-[}]>* '}' }
}
ExtractBraced.parse( $str ).say;
输出:
「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」
braced-item => 「{Belayneh, M. and Geiger, S. and Matth{\"{a}」
现在,为了让解析器接受嵌套大括号,我想保留一个当前已解析的左大括号数量的计数器,当遇到右大括号时,我们将计数器递减。如果计数器达到零,我们假设我们已经解析了完整的项目。
为了遵循这个想法,我尝试拆分 braced-item
正则表达式,对每个字符执行一个语法操作。 (下面 braced-item-char
正则表达式的操作方法应该处理 brace-counter):
grammar ExtractBraced {
rule TOP {
'author=' <braced-item> .*
}
rule braced-item { '{' <braced-item-char>* '}' }
rule braced-item-char { <-[}]> }
}
但是,现在突然解析失败了。可能是一个愚蠢的错误,但我不明白为什么它现在会失败?
在不知道您希望结果数据如何显示的情况下,我会将其更改为如下所示:
my $str = 「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」;
grammar ExtractBraced {
token TOP {
'author='
$<author> = <.braced-item>
.*
}
token braced-item {
'{' ~ '}'
[
|| <- [{}] >+
|| <.before '{'> <.braced-item>
]*
}
}
ExtractBraced.parse( $str ).say;
「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」
author => 「{Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.}」
如果你想要更多的结构它可能看起来更像这样:
my $str = 「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」;
grammar ExtractBraced {
token TOP {
'author='
$<author> = <.braced-item>
.*
}
token braced-part {
|| <- [{}] >+
|| <.before '{'> <braced-item>
}
token braced-item {
'{' ~ '}'
<braced-part>*
}
}
class Print {
method TOP ($/){
make $<author>.made
}
method braced-part ($/){
make $<braced-item>.?made // ~$/
}
method braced-item ($/){
make [~] @<braced-part>».made
}
}
my $r = ExtractBraced.parse( $str, :actions(Print) );
say $r;
put();
say $r.made;
「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」
author => 「{Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.}」
braced-part => 「Belayneh, M. and Geiger, S. and Matth」
braced-part => 「{\"{a}}」
braced-item => 「{\"{a}}」
braced-part => 「\"」
braced-part => 「{a}」
braced-item => 「{a}」
braced-part => 「a」
braced-part => 「i, S.K.」
Belayneh, M. and Geiger, S. and Matth\"ai, S.K.
请注意 <-[{}]>+
上的 +
和 <before '{'>
一样是一种优化,两者都可以省略,它仍然有效。
我开始编写 BibTeX 解析器。我想做的第一件事是解析一个支撑项。例如,花括号项可以是作者字段或标题。字段中可能有嵌套的大括号。以下代码 不 处理嵌套大括号:
use v6;
my $str = q:to/END/;
author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},
END
$str .= chomp;
grammar ExtractBraced {
rule TOP {
'author=' <braced-item> .*
}
rule braced-item { '{' <-[}]>* '}' }
}
ExtractBraced.parse( $str ).say;
输出:
「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」
braced-item => 「{Belayneh, M. and Geiger, S. and Matth{\"{a}」
现在,为了让解析器接受嵌套大括号,我想保留一个当前已解析的左大括号数量的计数器,当遇到右大括号时,我们将计数器递减。如果计数器达到零,我们假设我们已经解析了完整的项目。
为了遵循这个想法,我尝试拆分 braced-item
正则表达式,对每个字符执行一个语法操作。 (下面 braced-item-char
正则表达式的操作方法应该处理 brace-counter):
grammar ExtractBraced {
rule TOP {
'author=' <braced-item> .*
}
rule braced-item { '{' <braced-item-char>* '}' }
rule braced-item-char { <-[}]> }
}
但是,现在突然解析失败了。可能是一个愚蠢的错误,但我不明白为什么它现在会失败?
在不知道您希望结果数据如何显示的情况下,我会将其更改为如下所示:
my $str = 「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」;
grammar ExtractBraced {
token TOP {
'author='
$<author> = <.braced-item>
.*
}
token braced-item {
'{' ~ '}'
[
|| <- [{}] >+
|| <.before '{'> <.braced-item>
]*
}
}
ExtractBraced.parse( $str ).say;
「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」
author => 「{Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.}」
如果你想要更多的结构它可能看起来更像这样:
my $str = 「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」;
grammar ExtractBraced {
token TOP {
'author='
$<author> = <.braced-item>
.*
}
token braced-part {
|| <- [{}] >+
|| <.before '{'> <braced-item>
}
token braced-item {
'{' ~ '}'
<braced-part>*
}
}
class Print {
method TOP ($/){
make $<author>.made
}
method braced-part ($/){
make $<braced-item>.?made // ~$/
}
method braced-item ($/){
make [~] @<braced-part>».made
}
}
my $r = ExtractBraced.parse( $str, :actions(Print) );
say $r;
put();
say $r.made;
「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」
author => 「{Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.}」
braced-part => 「Belayneh, M. and Geiger, S. and Matth」
braced-part => 「{\"{a}}」
braced-item => 「{\"{a}}」
braced-part => 「\"」
braced-part => 「{a}」
braced-item => 「{a}」
braced-part => 「a」
braced-part => 「i, S.K.」
Belayneh, M. and Geiger, S. and Matth\"ai, S.K.
请注意 <-[{}]>+
上的 +
和 <before '{'>
一样是一种优化,两者都可以省略,它仍然有效。