我正在尝试设置一种语法,该语法要求如果[\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
这正是我想要发生的。唯一美中不足的是,Inaccessible symbol: word
STDERR 上有一条烦人的消息,因为word
在实际语法中没有使用词位。
我看到Marpa::R2::Grammar
我可以在构造函数选项中声明word
,inaccessible_ok
但我不能在Marpa::R2::Scanless
.
我也可以做类似以下的事情:
Rule ::= nine september
nine ~ word
september ~ word
然后使用 apause
使用自定义代码检查实际的词位值并根据值返回适当的词位。
构建使用关键字或数字和单词但不允许相邻词位一起运行而没有空格或标点符号分隔它们的语法的最佳方法是什么?