Я пытаюсь настроить грамматику, которая требует, чтобы символы [\w]
не могли отображаться непосредственно рядом друг с другом, если они не находятся в одной лексеме. То есть слова должны быть отделены друг от друга пробелом или пунктуацией.Формирование пробелов между словами в грамматике Марпы
Рассмотрим следующую грамматику:
use Marpa::R2; use Data::Dump;
my $grammar = Marpa::R2::Scanless::G->new({source => \<<'END_OF_GRAMMAR'});
:start ::= Rule
Rule ::= '9' 'september'
:discard ~ whitespace
whitespace ~ [\s]+
END_OF_GRAMMAR
my $recce = Marpa::R2::Scanless::R->new({grammar => $grammar});
dd $recce->read(\'9september');
Это разбирает успешно. Теперь я хочу изменить грамматику, чтобы заставить разделение между 9
и september
. Я думал об этом, вводя неиспользуемую лексему, которая соответствует [\w]+
:
use Marpa::R2; use Data::Dump;
my $grammar = Marpa::R2::Scanless::G->new({source => \<<'END_OF_GRAMMAR'});
:start ::= Rule
Rule ::= '9' 'september'
:discard ~ whitespace
whitespace ~ [\s]+
word ~ [\w]+ ### <== Add unused lexeme to match joined keywords
END_OF_GRAMMAR
my $recce = Marpa::R2::Scanless::R->new({grammar => $grammar});
dd $recce->read(\'9september');
К сожалению, эта грамматика терпит неудачу с:
A lexeme is not accessible from the start symbol: word
Marpa::R2 exception at marpa.pl line 3.
Хотя это может быть решена с помощью lexeme default
заявления:
use Marpa::R2; use Data::Dump;
my $grammar = Marpa::R2::Scanless::G->new({source => \<<'END_OF_GRAMMAR'});
lexeme default = action => [value] ### <== Fix exception by adding lexeme default statement
:start ::= Rule
Rule ::= '9' 'september'
:discard ~ whitespace
whitespace ~ [\s]+
word ~ [\w]+
END_OF_GRAMMAR
my $recce = Marpa::R2::Scanless::R->new({grammar => $grammar});
dd $recce->read(\'9september');
Это приводит к следующим выходам:
Inaccessible symbol: word
Error in SLIF parse: No lexemes accepted at line 1, column 1
* String before error:
* The error was at line 1, column 1, and at character 0x0039 '9', ...
* here: 9september
Marpa::R2 exception at marpa.pl line 16.
То есть, анализ не удался из-за того, что между 9
и september
нет разрыва, что я и хочу. Единственная муха в мазе состоит в том, что на STDERR есть раздражающее сообщение Inaccessible symbol: word
, потому что лексема word
не используется в фактической грамматике.
Я вижу, что в Marpa::R2::Grammar
я мог бы объявлен word
как inaccessible_ok
в опции конструктора, но я не могу сделать это в Marpa::R2::Scanless
.
я также мог бы сделать что-то вроде следующего:
Rule ::= nine september
nine ~ word
september ~ word
затем использовали pause
использовать пользовательский код для изучения фактического значения лексемы и возвращает соответствующую лексему в зависимости от значения.
Каков наилучший способ построения грамматики, которая использует ключевые слова или числа и слова, но запретит смежные лексемы, которые будут выполняться вместе без пробела или пунктуации, разделяющей их?
В P :: RD я бы сделал '/ \ w +/{$ item [0] eq 'keyword'}'. Там также '/ 9 \ b /' – ikegami