玛尔巴:我可以明确禁止关键字作为标识符吗?



我正在Marpa中实现一个新的DSL,并且(来自Regexp::Grammars)我非常满意。我的语言支持一元和二进制运算符,带有C样式标识符的对象以及使用熟悉的点表示法的方法调用。例如:

foo.has(bar == 42 AND baz == 23)

我发现了 Marpa 的语法描述语言提供的优先规则功能,并且非常依赖它,所以我几乎只有一个 G1 规则Expression。摘录(许多替代项,为简洁起见省略了语义操作):

Expression ::=
      NumLiteral
    | '(' Expression ')'             assoc => group
   || Expression ('.') Identifier
   || Expression ('.') Identifier Args
    | Expression ('==') Expression
   || Expression ('AND') Expression
Args     ::= ('(') ArgsList (')')
ArgsList ::= Expression+             separator => [,]
Identifier         ~ IdentifierHeadChar IdentifierBody
IdentifierBody     ~ IdentifierBodyChar*
IdentifierHeadChar ~ [a-zA-Z_]
IdentifierBodyChar ~ [a-zA-Z0-9_]
NumLiteral ~ [0-9]+

如您所见,我使用的是无扫描界面(SLIF)。我的问题是这也解析,例如:

foo.AND(5)

Marpa 知道点后面只能有一个标识符,所以它甚至没有考虑AND可能是一个关键字的事实。我知道我可以通过做一个单独的词法分析阶段来避免这个问题,该阶段明确地将AND标识为关键字,但是这个小小的剪纸并不值得付出努力。

SLIF 中是否有办法将Identifier规则限制为仅非关键字标识符?

我不知道

如何在语法中表达这样的事情。不过,您可以为标识符引入一个中间非终端来检查条件:

#!/usr/bin/perl
use warnings;
use strict;
use Syntax::Construct qw{ // };
use Marpa::R2;
my %reserved = map { $_ => 1 } qw( AND );
my $grammar = 'Marpa::R2::Scanless::G'->new(
    { bless_package => 'main',
      source => ( << '__GRAMMAR__'),
:default ::= action => store
:start ::= S
S ::= Id
  | Id NumLiteral
Id ::= Identifier action => allowed
Identifier         ~ IdentifierHeadChar IdentifierBody
IdentifierBody     ~ IdentifierBodyChar*
IdentifierHeadChar ~ [a-zA-Z_]
IdentifierBodyChar ~ [a-zA-Z0-9_]
NumLiteral ~ [0-9]+
:discard ~ whitespace
whitespace ~ [s]+
__GRAMMAR__
    });
for my $value ('ABC', 'ABC 42', 'AND 1') {
    my $value = $grammar->parse($value, 'main');
    print $$value, "n";
}

sub store {
    my (undef, $id, $arg) = @_;
    $arg //= 'null';
    return "$id $arg";
}
sub allowed {
    my (undef, $id) = @_;
    die "Reserved keyword $id" if $reserved{$id};
    return $id
}

您可以使用仅用于此类事情的词法优先级,示例在 Marpa::R2 测试套件中。

基本上,您声明<AND keyword> ~ 'AND'词法并赋予其优先级 1,以便它优先于 Identifier 。这必须奏效。

附言我稍微修改了上面的脚本以给出一个示例 — 代码、输出。

相关内容

  • 没有找到相关文章

最新更新