首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Marpa:我可以明确禁止关键字作为标识符吗?

Marpa:我可以明确禁止关键字作为标识符吗?
EN

Stack Overflow用户
提问于 2014-11-24 16:47:50
回答 2查看 230关注 0票数 6

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

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

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

代码语言:javascript
复制
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)。我的问题是,这也分析了,例如:

代码语言:javascript
复制
foo.AND(5)

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

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-11-24 17:39:41

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

代码语言:javascript
复制
#!/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
}
票数 2
EN

Stack Overflow用户

发布于 2014-11-25 06:35:05

您可以使用lexeme优先级来处理这类事情,示例是Marpa::R2测试套件中的这里

基本上,您可以声明<AND keyword> ~ 'AND' lexeme并给予它优先级1,这样它就比Identifier更受欢迎。那一定很管用。

我稍微修改了上面的脚本,给出了一个例子-- 代码输出

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27109840

复制
相关文章

相似问题

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