回答:
ほとんどの人は、構文カテゴリが何であるかを正確に説明することを避けます。すべての詳細で適切に行うと、必要な数学的洗練度に対する洞察の比率が非常に低くなるためです。ジョンレイノルズの著書 『プログラミング言語の理論』の第1章には、ロバートハーパーの『プログラミング言語の実践的基礎』と同様、より包括的な説明があります。
あなたが持つべき直感は、構文カテゴリは文脈自由文法によって生成されたツリーのセットであるということです。木の集合のために、このような定義を考えると、あなたが使用して、このセットに関数を定義することができ、構造再帰をし、使用してそれらについての性質を証明する構造誘導:ツリーを構築することができること、すなわち、ケース・分析することにより、すべてのさまざまな方法。
たとえば、次の文法で与えられる算術演算の言語があるとします。
e ::= zero | succ(e)| add(e, e)
次に、eval
項を構成して、整数を与える解釈関数を定義できます。
eval : Expr -> Int
eval zero = 0
eval succ(e) = 1 + eval e
eval add(e, e') = eval e + eval e'*
文法から式を生成する可能性のある方法ごとに1つの句を指定することにより、この関数を完全に定義したことに注意してください。これが関数の完全な定義であるという事実は、構造的再帰の原理と呼ばれています。
また、構造的帰納法を使用して、各ケースの帰納的分析を行うことにより、この関数の特性を証明することもできます。たとえば、、ごとe
にそれを証明できeval e ≥ 0
ます。
Proof. By structural induction on e.
- Case e = zero:
By the definition of eval, eval zero = 0.
We know 0 ≥ 0 by reflexivity of ≥.
- Case e = succ(e'):
By induction, we know that eval e' ≥ 0
So we also know that 1 + eval e' ≥ eval e'.
By transitivity, 1 + eval e' ≥ 0.
But eval succ(e') = 1 + eval e'.
So eval succ(e') ≥ 0.
- Case e = add(e', e'').
By induction, we know that eval e' ≥ 0.
By induction, we know that eval e'' ≥ 0.
By properties of addition, we know that eval e' + eval e'' ≥ 0.
By the definition of eval, eval add(e',e'') = eval e' + eval e''.
So eval add(e',e'') ≥ 0.
式がどのように形成されるかについてのケースのみを考慮することが証明を構成するという事実は、構造誘導の原理と呼ばれます。
今では、構造再帰によって関数を定義し、任意の文法の構造帰納法によってプロパティを証明できるのは事実です。ただし、これを厳密に証明するには、ある程度のカテゴリー理論が必要です。構文のカテゴリーをファンクターの特定のクラスの初期代数として形式化し、そのような初期代数がそのクラスに常に存在することを証明する必要があります。
これは、そのような「明白な」結果を証明するための非常に重いツールです。そのため、構造定義がどのように機能するかについてのあなたの直感を信頼し、プロの論理学者になることを決定した場合にのみ詳細なセマンティクスを気にすることをお勧めします。
私も明確な定義を見つけたことはありませんが、次のことを推測しました。
私が理解しているように、言語を構文ドメインに分割します。さらに、文法を書き留めるとき、構文ドメインは単一の異なるシンボルによって完全に生成されなければならないことを追加します。したがって、構文ドメインは言語のサブセットであり、各ドメインは単一のシンボルによって生成されます。
すべての表現は1つの構文ドメインであると言えます。
または、それらを分割することもできます。
したがって、使用する正確な構文ドメインを理解している限り、設計の問題です(つまり、言語の抽象構文を設計するときに行う決定を意味します)。しかし、それらは確かに言語のサブセットであり、各構文ドメインは異なるシンボルによって生成される必要があります。