首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使Marpa的序列规则变得贪婪?

如何使Marpa的序列规则变得贪婪?
EN

Stack Overflow用户
提问于 2014-08-31 15:05:23
回答 2查看 227关注 0票数 3

我正在研究一种Marpa::R2语法,它可以对文本中的项目进行分组。每个组只能包含某种类型的项,但不能显式分隔。这会导致问题,因为x...x ( .表示可以成为组一部分的项)可以分组为x(...)xx(..)(.)xx(.)(..)xx(.)(.)(.)x。换句话说,语法是非常模糊的。

如果我只想要x(...)x解析,即如果我想强迫一个+量词只表现为“贪婪”(就像它在Perl中所做的那样),我如何消除这个歧义?

在下面的语法中,我尝试在序列规则中添加rank副词,以便将Group优先于Sequence,但这似乎行不通。

下面是练习这种行为的测试用例。

代码语言:javascript
复制
use strict;
use warnings;

use Marpa::R2;
use Test::More;

my $grammar_source = <<'END_GRAMMAR';
inaccessible is fatal by default
:discard ~ space
:start ::= Sequence

Sequence
    ::= SequenceItem+  action => ::array
SequenceItem
    ::= WORD    action => ::first
    |   Group   action => ::first
Group
    ::= GroupItem+  action => [name, values]
GroupItem
    ::= ('[') Sequence (']')  action => ::first

WORD    ~ [a-z]+
space   ~ [\s]+
END_GRAMMAR

my $input = "foo [a] [b] bar";

diag "perl $^V";
diag "Marpa::R2 " . Marpa::R2->VERSION;

my $grammar = Marpa::R2::Scanless::G->new({ source => \$grammar_source });
my $recce = Marpa::R2::Scanless::R->new({ grammar => $grammar });

$recce->read(\$input);

my $parse_count = 0;
while (my $value = $recce->value) {
    is_deeply $$value, ['foo', [Group => ['a'], ['b']], 'bar'], 'expected structure'
        or diag explain $$value;
    $parse_count++;
}
is $parse_count, 1, 'expected number of parses';

done_testing;

测试用例的输出(失败):

代码语言:javascript
复制
# perl v5.18.2
# Marpa::R2 2.09
ok 1 - expected structure
not ok 2 - expected structure
#   Failed test 'expected structure'
#   at - line 38.
#     Structures begin differing at:
#          $got->[1][2] = Does not exist
#     $expected->[1][2] = ARRAY(0x981bd68)
# [
#   'foo',
#   [
#     'Group',
#     [
#       'a'
#     ]
#   ],
#   [
#     ${\$VAR1->[1][0]},
#     [
#       'b'
#     ]
#   ],
#   'bar'
# ]
not ok 3 - expected number of parses
#   Failed test 'expected number of parses'
#   at - line 41.
#          got: '2'
#     expected: '1'
1..3
# Looks like you failed 2 tests of 3.
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-08-31 17:25:13

序列规则是为非棘手的情况设计的。当执行变得棘手时,序列规则总是可以重写为BNF规则,这就是我在这里建议的。以下是您的测试工作:

代码语言:javascript
复制
use strict;
use warnings;

use Marpa::R2;
use Test::More;

my $grammar_source = <<'END_GRAMMAR';
inaccessible is fatal by default
:discard ~ space

# Three cases
# 1.) Just one group.
# 2.) Group follows by alternating words and groups.
# 3.) Alternating words and groups, starting with words
Sequence ::= Group action => ::first
Sequence ::= Group Subsequence action => [values]
Sequence ::= Subsequence action => ::first

Subsequence ::= Words action => ::first

# "action => [values]" makes the test work unchanged.
# The action for the next rule probably should be
# action => [name, values] in order to handle the general case.
Subsequence ::= Subsequence Group Words action => [values]

Words ::= WORD+ action => ::first
Group
::= GroupItem+  action => [name, values]
GroupItem
::= ('[') Sequence (']')  action => [value]

WORD    ~ [a-z]+
space   ~ [\s]+
END_GRAMMAR

my $input = "foo [a] [b] bar";

diag "perl $^V";
diag "Marpa::R2 " . Marpa::R2->VERSION;

my $grammar = Marpa::R2::Scanless::G->new( { source  => \$grammar_source } );
my $recce   = Marpa::R2::Scanless::R->new( { grammar => $grammar } );

$recce->read( \$input );

my $parse_count = 0;
while ( my $value = $recce->value ) {
is_deeply $$value, [ 'foo', [ Group => ['a'], ['b'] ], 'bar' ],
    'expected structure'
    or diag explain $$value;
$parse_count++;
} ## end while ( my $value = $recce->value )
is $parse_count, 1, 'expected number of parses';

done_testing;
票数 4
EN

Stack Overflow用户

发布于 2014-09-01 04:45:31

不可靠的语法:

代码语言:javascript
复制
Sequence           : WORD+ SequenceAfterWords
                   | Group SequenceAfterGroup

SequenceAfterWords : Group SequenceAfterGroup
                   |

SequenceAfterGroup : WORD+ SequenceAfterWords
                   |

Jeffrey说,在Marpa中使用递归更有效地处理领导。同样的方法,上面可以采取回到前面,以产生这一点。

代码语言:javascript
复制
Sequence            : SequenceBeforeWords WORD+
                    | SequenceBeforeGroup Group

SequenceBeforeWords : SequenceBeforeGroup Group
                    |

SequenceBeforeGroup : SequenceBeforeWords WORD+
                    |

在这两种情况下

代码语言:javascript
复制
Group     : GroupItem+

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

https://stackoverflow.com/questions/25593241

复制
相关文章

相似问题

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