Проблема разделения правил 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.