同じ優先順位の2つの二項演算子、左結合および右結合を持つ言語


11

2つの2項演算子をopl持ちopr同じ優先順位でopl左結合およびopr右結合であるプログラミング(またはスクリプト)言語(またはドメイン固有の言語)はありますか?

(そのような例を見つけることはできませんが、その奇妙なケースを処理するのに十分な一般的なパーサーをコーディングしようとしています)

x opl y opr zまたはx opr y opl zの形式の式はどのように解析されますか?より一般的には、さらに多くのオペランドを使用しますか?


4
痛い場合は、それをしないでください。
CodesInChaos

1
Haskellでは、独自のインフィックス演算子を独自の優先順位で定義できます。この場合、エラーが発生します。あなたが持っている場合x <@ y @> z<@されている左結合と@>右結合され、GHCはあなたに「優先順位解析エラー」を与える:「『混在させることはできませんが<@』 [infixl 0]と『@>』 [infixr 0]同じ中置式で」私は定義されました(例ではレベル0のこれらの演算子)。
アンタルスペクターザブスキー

@ AntalSpector-Zabusky:それは素晴らしい答えでしょう!
バジルスタリンケビッチ

@ AntalSpector-Zabusky:Swiftでも同じです。実際に演算子を定義できると思いますが、式では、すべての左結合演算子またはすべての右結合演算子を同じ優先順位で使用する必要があります。したがって、x leftop y leftop zまたはx rightop y rightop zを使用できますが、x leftop y rightop zは使用できません。
gnasher729

@BasileStarynkevitch:お望み通り!あなたは「柔軟なパーサを」述べたので、私が持っているより多くの無名の言語のカップル含ま非常に柔軟なパーサは(今まで望んでいたif_then_else_[1;2;3]のライブラリで定義するの?)。
アンタルスペクター-ザブスキー

回答:


10

以下に、独自の演算子を定義できる3つの言語を示します。これらの言語は2つ半の異なる処理を行います。HaskellとCoqはどちらもこれらの種類のシェナンガンを許可しませんが、異なる方法ですが、Agdaはこのような関連性の混合を許可します。


まず、Haskellでは、単にこれを行うことは許可されていません。 独自の演算子を定義して、優先順位(0〜9)および選択した結合性を与えることができます。 ただし、Haskellレポートでは、関連性の混在は許可されていません

同じ優先順位を持つ連続した括弧なしの演算子は、構文エラーを回避するために、左または右の両方の連想演算子でなければなりません。[Haskell 2010レポート、Ch。3]

したがって、GHCでは、同じ優先順位レベル(たとえば0 infixl)で左結合()演算子<@と右結合演算子を定義すると、@>評価x <@ y @> zによりエラーが発生します

優先順位解析エラー
    は、同じ中置式で' <@' [ infixl 0]と ' @>' [ infixr 0]を混在させることはできません

(実際、演算子を挿入子として宣言することもできますが==、これx == y == zは構文エラーです!)。


一方、依存型の言語/定理の証明者であるAgdaがあります(確かに、かなり主流ではありません)。Agdaには、mixfix演算子をサポートする、私が知っている言語の中で最も順応性のある構文がいくつかあります。標準ライブラリには、関数が含まれています

if_then_else_ : ∀ {a} {A : Set a} → Bool → A → A → A

呼び出されたときに書き込まれます

if b then t else f

引数にアンダースコアを記入してください!これは非常に柔軟な解析をサポートする必要があることを意味するため、これについて言及します。当然のことながら、(その優先レベルを超える任意の自然数の範囲で、通常は0〜100であるが)Agdaはまた、結合性宣言を持っている、とAgdaはありません同じ優先順位が異なるfixitiesのオペレータをミックスすることを許可します。ただし、ドキュメントでこれに関する情報を見つけることができないため、実験する必要がありました。

<@@>を上から再利用しましょう。2つの単純なケースでは、

  • x <@ y @> zとして解析x <@ (y @> z); そして
  • x @> y <@ zとして解析し(x @> y) <@ zます。

私が考えて、私は間違ったことを考えている場合を除き- -何Agdaが行うことはグループが「左結合」と「右結合」チャンク、およびにラインで右結合チャンクは、隣接する引数をつかんで「優先順位」を取得します。だからそれは私たちに与えます

a <@ b <@ c @> d @> e @> f <@ g

として解析

(((a <@ b) <@ (c @> (d @> (e @> f)))) <@ g

または

<code>(((a <@ b)<@(c @>(d </ code> @>(e @> f))))の構文解析ツリー<@ g

しかし、私の実験にもかかわらず、私が最初にそれを書いたときに間違ったことを推測しました。これは有益かもしれません:-)

(そして、HaskellのようなAgdaには、解析エラーを正しく与える非連想演算子があります。そのため、混合結合性が解析エラーを引き起こす可能性があります。)


最後に、定理証明/依存型言語Coqがあります。これは、Agdaよりもさらに柔軟な構文を持っています。これは、構文拡張が実際に新しい構文構造の仕様を指定し、コア言語(漠然とマクロのように書き換えることで実装されているためです) 、 私は考えます)。Coqでは、リスト構文[1; 2; 3]は標準ライブラリからのオプションのインポートです。新しい構文でも変数をバインドできます!

繰り返しになりますが、Coqでは、独自の挿入演算子を定義し、それらに優先順位レベル(主に0〜99)と結合性を与えることができます。ただし、Coqでは、各優先レベルに設定できる結合性は1つのみです。したがって、<@左結合@>として定義してから、同じレベル(たとえば50)で右結合として定義しようとすると、

エラー:レベル50は既に左結合と宣言されていますが、現在は右結合と想定されています

Coqのほとんどの演算子は、10で割り切れるレベルにあります。アソシエティビティの問題がある場合(これらのレベルアソシエティビティはグローバルです)、通常、いずれかの方向(通常は上)にレベルを1つ上げました。


2
(うーん、言語の奇妙な選択。プログラミング言語の理論を勉強していると言ってもらえますか?:
-Antal Spector-Zabusky

詳細な回答をありがとうございます。ところで、どのように絵を描きましたか(どのツールでgraphviz??)
バジル・スタリンケビッチ

ところで、なぜ「優先順位」ではなく「固定性」なのでしょうか?
バジルスタリンケビッチ

@BasileStarynkevitch:それはあなたが意味するところに依存します。Coqセクションで言うなら、それはただの間違いでした:
Antal Spector-Zabusky

1
@BasileStarynkevitch:また、写真に関するあなたの質問を逃しました!LaTeXパッケージqtreeでそれを描き、Mac用のLaTeXスニペットレンダラーであるLaTeXitでレンダリングしました。関連するソースコードは\ttfamily \Tree[.<@ [.<@ [.<@ a b ] [.@> c [.@> d [.@> e f ]]]] g ]です。
アンタルスペクター-ザブスキー

2

ダグラスクロックフォードによって普及したので、プラットパーサー(またはトップダウンオペレーター優先順位パーサー)がより一般的になり始めました。これらのパーサーは、ルールを固定文法に組み込むのではなく、演算子の優先順位と結合性のテーブルから機能するため、ユーザーが独自の演算子を定義できる言語に役立ちます。

最初に式の左端の項を解析し、次に適切にバインドする限り、新しい演算子と右辺の項を再帰的にバインドすることで機能する解析関数を持っています。左結合演算子は、同じ優先順位までの優先順位を持つ右辺の用語をバインドしますが、右結合演算子は優先順位レベルまでしかバインドせず、それを含めません。これにより、上記で引用したAgdaと同じ解析ツリーが得られると思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.