无法在语法中分离G0和G1规则

Nat*_*enn 4 perl parsing tokenize marpa

我试图得到一个看似非常基本的Marpa语法工作.我使用的代码如下:

use strict;
use warnings;
use Marpa::R2;
use Data::Dumper;
my $grammar = Marpa::R2::Scanless::G->new(
    {
        source => \(<<'END_OF_SOURCE'),
            :start ::= ExprSingle
            ExprSingle ::= Expr AndExpr

            Expr ~ word

            AndExpr ~ word*
            word ~ [\w]+

            :discard ~ ws
            ws ~ [\s]+
END_OF_SOURCE
    }
);
my $reader = Marpa::R2::Scanless::R->new(
    {
        grammar => $grammar,
    }
);
my $input = 'foo';
$reader->read(\$input);
my $value = $reader->value;
print Dumper $value;
Run Code Online (Sandbox Code Playgroud)

这打印$VAR1 = \'foo';.所以它认出一个字就好了.但我希望它能识别出一串词

my $input='foo bar'
Run Code Online (Sandbox Code Playgroud)

现在脚本打印:

Error in SLIF G1 read: Parse exhausted, but lexemes remain, at position 4
Run Code Online (Sandbox Code Playgroud)

我认为这是因为ExprSingle使用~(匹配)运算符,它使其成为标记化级别G0的一部分,而不是结构级别G1; 该:discard规则允许G1的规则,而不是G0者之间的空间.所以我改变语法是这样的:

ExprSingle ::= Expr AndExpr
Run Code Online (Sandbox Code Playgroud)

现在没有打印警告,但结果值undef不是包含'foo'和的东西'bar'.老实说,我不确定这意味着什么,因为在此之前,失败的解析会引发一个实际的错误.

我尝试改变语法,将我认为的G0和G1规则进一步分开,但仍然没有运气:

:start ::= ExprSingle
ExprSingle ::= Expr AndExpr

Expr ::= token

AndExpr ::= token*
token ~ word
word ~ [\w]+

:discard ~ ws
ws ~ [\s]+
Run Code Online (Sandbox Code Playgroud)

最终价值仍然是undef.trace_terminals显示'foo'和'bar'被接受为令牌.我需要做些什么来修复这个语法(我的意思是得到一个包含字符串'foo'和'bar'的值而不仅仅是undef)?

Jef*_*ler 5

规则默认返回undef值,因此在您的情况下从$ reader-> value()返回\ undef表示您的解析成功.也就是说,undef的返回意味着失败,而\ undef的返回意味着成功,其中解析被评估为undef.

从更有用的语义开始的一种好的,快速的方法是添加以下行:

:default :: = action => :: array

这会导致解析生成AST.