Проблема разделения правил G0 и G1 в грамматике

Я пытаюсь получить то, что похоже на основную грамматику Марпы. Код, который я использую ниже:

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;

Это печатает $VAR1 = \'foo';, Таким образом, он распознает одно слово просто отлично. Но я хочу, чтобы он распознал цепочку слов

my $input='foo bar'

Теперь скрипт печатает:

Error in SLIF G1 read: Parse exhausted, but lexemes remain, at position 4

Я думаю это потому что ExprSingle использует ~ оператор (match), который делает его частью уровня токенизации G0 вместо структурного уровня G1; :discard Правило позволяет пространство между правилами G1, а не G0. Поэтому я меняю грамматику так:

ExprSingle ::= Expr AndExpr

Теперь предупреждение не выводится, но полученное значение undef вместо чего-то содержащего 'foo' а также 'bar', Я, честно говоря, не уверен, что это значит, так как до этого неудачный анализ приводил к реальной ошибке.

Я попытался изменить грамматику, чтобы отделить то, что я считаю правилами G0 и G1, но все же не повезло:

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

Expr ::= token

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

:discard ~ ws
ws ~ [\s]+

Окончательное значение по-прежнему undef, trace_terminals показывает, что 'foo' и 'bar' принимаются как токены. Что мне нужно сделать, чтобы исправить эту грамматику (под которой я имею в виду получить значение, содержащее строки 'foo' и 'bar' вместо просто undef)?

1 ответ

Решение

Правила по умолчанию возвращают значение undef, поэтому в вашем случае возврат \undef из $reader->value() означает, что ваш анализ выполнен успешно. То есть возврат undef означает неудачу, в то время как возврат \undef означает успех, когда разбор оценивается как undef.

Хороший, быстрый способ начать с более полезной семантики - добавить следующую строку:

: default:: = action =>:: array

Это заставляет анализ генерировать AST.

Другие вопросы по тегам