首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Marpa语法中强制单词之间的间隔

在Marpa语法中强制单词之间的间隔
EN

Stack Overflow用户
提问于 2013-09-09 07:21:03
回答 1查看 201关注 0票数 1

我正在尝试建立一种语法,它要求如果[\w]字符不在同一词位中,它们不能直接相邻出现。也就是说,单词之间必须用空格或标点符号分隔。

考虑以下语法:

代码语言:javascript
复制
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');

这将成功解析。现在我想改变语法,强制在9september之间进行分隔。我想通过引入一个与[\w]+匹配的未使用的词位来实现这一点

代码语言:javascript
复制
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');

不幸的是,这个语法失败了:

代码语言:javascript
复制
A lexeme is not accessible from the start symbol: word
Marpa::R2 exception at marpa.pl line 3.

虽然这可以通过使用lexeme default语句来解决:

代码语言:javascript
复制
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');

这将产生以下输出:

代码语言:javascript
复制
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.

也就是说,解析失败了,因为9september之间没有差距,这正是我想要发生的。唯一的美中不足之处在于,标准错误记录器上有一个恼人的Inaccessible symbol: word消息,因为在实际的语法中并没有使用word词位。

我看到在Marpa::R2::Grammar中,我可以在构造函数选项中将word声明为inaccessible_ok,但在Marpa::R2::Scanless中不能这样做。

我也可以做一些类似以下的事情:

代码语言:javascript
复制
Rule ::= nine september
nine ~ word
september ~ word

然后使用pause使用自定义代码来检查实际的词位值,并根据值返回适当的词位。

构建使用关键字或数字和单词的语法,但不允许相邻的词位一起运行,而不使用空格或标点符号分隔它们,最好的方法是什么?

EN

回答 1

Stack Overflow用户

发布于 2013-09-09 07:35:35

嗯,显而易见的解决方案是在两者之间需要一些空格(在G1级别上)。当我们使用以下语法时

代码语言:javascript
复制
:default ::= action => ::array

:start ::= Rule
Rule ::= '9' (Ws) 'september'

Ws ::= [\s]+

:discard ~ whitespace
whitespace ~ [\s]+

然后9september会失败,但9 september会被解析。需要注意的要点:

  • 词位都是最长的标记时,它们既可以被丢弃,也可以是必需的。这就是为什么:discardWs规则不会相互干扰的原因。
  • 你通常不想使用像幻象词位这样的技巧来误导解析器。这样的话breakage.
  • When的每一点空格都很重要,你可能想去掉:discard ~ whitespace。例如,这是为了用于类似C的语言,在这些语言中,空格传统上并不重要。
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18689628

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档