6

私は Marpa で新しい DSL を実装しており、(Regexp::Grammars から) 満足しています。私の言語は、一連の単項演算子と 2 項演算子、C スタイルの識別子を持つオブジェクト、おなじみのドット表記を使用したメソッド呼び出しをサポートしています。例えば:

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

Marpa の文法記述言語が提供する優先ルール機能を見つけて、それを大いに利用するようになったので、G1 ルールはほぼ 1 つしかありません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ルールを非キーワード識別子のみに制限する方法はありますか?

4

2 に答える 2

2

そんなことを文法で表現する方法がわかりません。ただし、条件をチェックする識別子の中間の非終端記号を導入できます。

#!/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
}
于 2014-11-24T17:39:41.393 に答える
2

そのようなことだけを意図した語彙素の優先順位を使用できます。例はMarpa ::R2 テスト スイートにあります。

基本的に、<AND keyword> ~ 'AND'lexeme を宣言し、優先度 1 を指定して、 よりも優先されるようにしIdentifierます。それはトリックを行う必要があります。

PS上記のスクリプトを少し変更して、例を示します— codeoutput

于 2014-11-25T06:35:05.660 に答える