コンピュータサイエンスにおいて、Van Wijngaarden文法(vW文法またはW文法[1]とも呼ばれる)は、形式言語を定義するための形式論である。この名前は、 Adriaan van Wijngaarden [2]がALGOL 68 プログラミング言語を 定義する目的で発明した形式論に由来する。結果として得られた仕様[3]は、その最も注目すべき応用例である。
ヴァン・ウィンガールデン文法は、文脈自由文法では文の2つの異なる部分が何らかの形で互いに一致しなければならない一致や参照を表現できないという問題に対処している。例えば、「鳥は食べていた」という文は数について一致していないため標準英語ではない。文脈自由文法では、「鳥は食べていた」と「鳥は食べていた」と「鳥は食べていた」を同じように解析する。しかし、文脈自由文法は単純さという利点があるのに対し、ヴァン・ウィンガールデン文法は非常に複雑であると考えられている。[4]
2つのレベル
W 文法は2 レベルの文法です。異なるレベルで動作する 1 組の文法によって定義されます。
- ハイパー文法は属性文法、すなわち非終端記号が属性を持つことができる文脈自由文法規則の集合である。
- メタ文法は、これらの属性の可能な値を定義する文脈自由文法です。
W 文法によって生成される文字列のセットは、2 段階のプロセスによって定義されます。
- 各ハイパールール内で、その中に出現する各属性に対して、メタ文法によって生成された値を選択します。結果は通常の文脈自由文法ルールです。これをあらゆる可能な方法で実行します。
- 結果として得られる(おそらく無限の)文脈自由文法を使用して、通常の方法で文字列を生成します。
最初のステップで使用される一貫した置換は、述語論理における置換と同じであり、実際に論理プログラミングをサポートします。これは、 Alain Colmerauer [ where? ]が指摘したように、Prologにおける統一に対応します。
W文法はチューリング完全である。[5] したがって、W文法が生成する言語に関するすべての決定問題、例えば
- W文法が与えられた文字列を生成するかどうか
- W文法が文字列を全く生成しないかどうか
決定不可能です。
接辞文法として知られる短縮版が開発され、コンパイラの構築や自然言語の記述に適用されました。
確定論理プログラム、つまり否定を使わない論理プログラムは、W文法のサブクラスとして考えることができる。[6]
動機と歴史
1950 年代には、英語やロシア語などの自然言語の認識、解釈、翻訳にコンピューターを適用する試みが始まりました。これには、文章を解析、解釈し、生成するために使用できる、機械可読な文節構造の記述が必要です。構造言語学の概念である文脈自由文法がこの目的のために採用されました。文脈自由文法の規則は、名詞句や動詞句などの品詞、そして最終的には名詞、動詞、代名詞などの単語から文章がどのように再帰的に構築されるかを表現できます。
この研究はプログラミング言語の設計と実装に影響を与え、最も顕著なのはバッカス・ナウア記法による構文記述を導入したALGOL 60です。
ただし、文脈自由規則では、文の 2 つの異なる部分が何らかの形で互いに一致しなければならない 一致や参照 (照応) を表現することはできません。
これらは W 文法で簡単に表現できます。(以下の例を参照してください。)
プログラミング言語には、型付けとスコープという類似の概念があります。言語のコンパイラまたはインタープリタは、変数のどの使用が一緒に属するか(同じ変数を参照するか)を認識する必要があります。これには通常、次のような制約があります。
- 変数は、その値を使用する前に初期化する必要があります。
- 強く型付けされた言語では、各変数に型が割り当てられ、変数のすべての使用はその型を尊重する必要があります。
- 多くの場合、使用する前にその型を明示的に宣言する必要があります。
W 文法は、文脈自由文法の非終端記号に、構文を制約し、意味を指定するために使用される、解析ツリーのノード間で情報を渡す属性(または接辞) を提供するというアイデアに基づいています。
このアイデアは当時よく知られていました。例えば、ドナルド・クヌースは、 ALGOL 68の設計委員会を訪れ、独自のバージョンである属性文法を開発していました。[7]
構文記述に属性を追加することで、上記のような制約をチェックし、コンパイル時に多くの無効なプログラムを除外することができます。Van Wijngaardenは序文で次のように書いています。[2]
私の主な反対意見は、不必要な制限と、構文と意味の定義でした。実際、MR 75 で見た構文では多数のプログラムが生成されますが、意味のあるプログラムのサブセットをできるだけ大きくしたいので、より厳格な構文が必要です。[...] すぐに、Backus 記法よりも優れたツールが有利になる可能性があることが明らかになりました [...]。私は、言語の設計で、通常よりも多くの情報を構文で伝達できるようにするスキームを開発しました [...]。
W 文法の非常に独特な点は、属性を文字列として厳密に扱うことです。これは文脈自由文法によって定義され、連結のみが実行可能な操作です。複雑なデータ構造と操作はパターン マッチングによって定義できます。(以下の例を参照してください。)
1968 年のALGOL 68「最終報告書」で導入されて以来、W 文法は強力すぎて制約がないため実用的ではないと広く考えられてきました。[引用が必要]
これは部分的には、W 文法の適用方法による結果でした。1973 年の ALGOL 68「改訂レポート」には、W 文法の形式自体を変更することなく、はるかに読みやすい文法が含まれています。
一方、W文法は、その汎用性を十分に発揮すると、パーサジェネレータの入力として使用するなどの実用的な目的には強力すぎることが明らかになりました。W文法は、再帰的に列挙可能なすべての言語を正確に記述しますが、[8]一般に構文解析は不可能です。つまり、与えられた文字列が与えられたW文法によって生成できるかどうかを判断することは、決定不可能な問題です。
したがって、自動構文解析や翻訳に使用する場合は、その使用は厳しく制限される必要がある。これに対処するために、W文法の制限付きおよび修正版が開発された。例えば、
- 拡張接辞文法(EAG) は、英語やスペイン語などの自然言語の文法を記述するために使用されます。
- Q システム、自然言語処理にも適用されます。
- プログラミング言語のコンパイラ構築言語として適用されるCDLシリーズの言語。
1970年代以降、このアプローチへの関心は薄れ、時折、新たな研究が発表されるようになった。[9]
例
英語の文法における一致
英語では、名詞、代名詞、動詞には文法上の数、性別、人称などの属性があり、これらは主語、主動詞、主語を指す代名詞の間で一致する必要があります。
- 私は自分自身を洗います。
- 彼女は体を洗います。
- 私たちは自分たちを洗います。
これらは有効な文です。無効な文の例は次のとおりです。
- *私は自分たちで洗います。
- *彼女は自分自身を洗いました。
- *私たちは自分自身を洗います。
ここで、一致は、両方の代名詞(例:Iとmyself)が同じ人物を指していることを強調するのに役立ちます。
このようなすべての文を生成する文脈自由文法:
<文> ::= <主語> <動詞> <目的語>
<主語> ::= I | You | He | She | We | They
<動詞> ::= wash | washes
<目的語> ::= myself | yourself | himself | himself | themselves | themselves | yourselves | themselves
から<sentence>、すべての組み合わせを生成できます。
私は自分自身を洗う 私は自分自身を洗う 私は自分自身を洗う [...] 彼らは身を洗う 彼らは自分自身を洗う
有効な文のみを生成する W 文法:
<文<番号> <性別> <人> >
::= <主語<番号> <性別> <人> >
<動詞<数> <人> >
<オブジェクト<番号> <性別> <人> >
<主語単数<性別> 1番目> ::=私
<主語<数> <性別> 2番目> ::=あなた
<主語 単数 男性 3番目> ::=彼
<主語 単数 女性 3番目> ::=彼女
<主語複数<性別> 1番目> ::=私たち
<主語単数<性別> 3番目> ::=彼ら
<動詞単数第一形> ::= wash
<動詞単数第二形> ::= wash
<動詞単数第三形> ::= washs
<動詞複数形<人> > ::=洗う
<目的語単数<性別> 1番目> ::=私自身
<目的語単数<性別> 2番目> ::=あなた自身
<目的語単数男性 3番目> ::=彼自身
<目的語単数女性 3番目> ::=彼女自身
<目的語複数<性別> 1番目> ::=私たち自身
<目的語複数<性別> 2番目> ::=あなた自身
<目的語複数<性別> 3番目> ::=彼ら自身
<数> ::= = 単数 | 複数
<性別> ::= = 男性 | 女性
<人> ::= = 1 人目 | 2 人目 | 3 人目
標準的な非文脈自由言語
よく知られている非文脈自由言語は
この言語の2レベルの文法はメタ文法である。
- N ::= 1 | N1
- X ::= a | b
文法スキーマとともに
- 開始 ::= ⟨a N ⟩ ⟨b N ⟩ ⟨a N ⟩
- ⟨X N1 ⟩ ::= ⟨X N ⟩ X
- ⟨X 1 ⟩ ::= X
質問です。N1 を新しい文字、たとえば C に置き換えた場合、文法によって生成された言語は保持されますか? それとも、N1 は 2 つの記号の文字列、つまり N の後に 1 が続くものとして読み取られるべきでしょうか? 質問はこれで終わりです。
ALGOL での変数の有効な使用を要求する
アルゴリズム言語Algol 60の改訂報告書[10]は、 言語の完全な文脈自由構文を定義しています。
割り当ては次のように定義されます(セクション 4.2.1)。
<左側部分>
::= <変数> :=
| <プロシージャ識別子> :=
<左部分リスト>
::= <左部分>
| <左部分リスト> <左部分>
<代入文>
::= <左部分リスト> <算術式>
| <左部分リスト> <ブール式>
A は<variable>(他のものの中でも) であり<identifier>、次のように定義されます。
<識別子> ::= <文字> | <識別子> <文字> | <識別子> <数字>
例(セクション4.2.2):
s:=p[0]:=n:=n+1+s n:=n+1 A:=B/Cvq×S S[v,k+2]:=3-arctan(sTIMESzeta) V:=Q>Y^Z
式と代入は型チェックされなければならない。例えば、
- において
n:=n+1、n は数値(整数または実数)でなければなりません。 - では
A:=B/C-v-q×S、すべての変数は数値でなければなりません。 - では
V:=Q>Y^Z、すべての変数はブール型である必要があります。
上記の規則は<arithmetic expression>とを区別します<Boolean expression>が、同じ変数が常に同じ型を持つかどうかを検証することはできません。
この(非文脈自由)要件は、使用または割り当てられた各変数の名前と型を記録する属性を使用して規則に注釈を付けることで、W 文法で表現できます。
このレコードは、型を一致させる必要がある文法のすべての場所に持ち込まれ、型チェックを実装できます。
同様に、使用前の変数の初期化のチェックなどにも使用できます。
データ構造とその操作の形式論が明示的にサポートされていない状態で、このようなデータ構造を作成および操作するにはどうすればよいのか疑問に思う人もいるかもしれません。これは、メタ文法を使用してデータ構造の文字列表現を定義し、パターン マッチングを使用して操作を定義することで実現できます。
<左側の部分は<TYPED> <NAME> > ::
= <変数は<TYPED> <NAME> > : = | <TYPED> <NAME>を持つ
プロシージャ識別子: =
<左部分リスト< TYPEMAP1 > >
::= <左部分< TYPED > < NAME > ><TYPEMAP1>は<TYPED>
で、<NAME>はソートされた<EMPTY>に追加されます>
| <左部品リスト< TYPEMAP2 > >
<左側に< TYPED > < NAME >と入力>
<ここで、< TYPEMAP1 > は< TYPED > であり、 < NAME >はソートされた< TYPEMAP2 >に追加されます>
<代入文<代入先> <使用先> >
::= < 左部分リスト<代入先> > < 算術式<使用先> >
| <左部品リスト<割り当て先> > <ブール式<使用先> >
<where < TYPED > < NAME > is < TYPED > < NAME >がソートされた< EMPTY > >
に追加されます::=
<ここで、< TYPEMAP1 >は< TYPED1 > であり、 < NAME1 >はソートされた< TYPEMAP2 >に
追加されます::= <ここで、< TYPEMAP2 >は< TYPED2 > であり、< NAME2 >はソートされた< TYPEMAP3 >に追加されます<NAME1>
は辞書順で<NAME2>より前です>
<ここで、< TYPEMAP1 >は< TYPED1 > であり、 < NAME1 >はソートされた< TYPEMAP2 >に
追加されます::= <ここで、< TYPEMAP2 >は< TYPED2 > であり、< NAME2 >はソートされた< TYPEMAP3 >に追加されます
<ここで、<NAME2>は辞書順で<NAME1>より前です>
<ここで、< TYPEMAP3 > は< TYPED1 > であり、 < NAME1 >はソートされた< TYPEMAP4 >に追加されます>
<ここで、< EMPTY >は辞書順で< NAME1 >の前になります>
::= <ここで、< NAME1 >は< LETTER OR DIGIT >で、その後に< NAME2 >が続きます>
<ここで、< NAME1 >は辞書順で< NAME2 >より前です>
::= <ここで、< NAME1 >は<文字または数字>で、その後に< NAME3 >が続きます><NAME2>は<文字または数字>で
、その後に<NAME4>が続きます><NAME3>
は辞書順で<NAME4>より前です>
<ここで、< NAME1 >は辞書順で< NAME2 >より前です>
::= <ここで、< NAME1 >は<文字または数字 1 >で、その後に< NAME3 >が続きます>
<ここで、< NAME2 >は<文字または数字 2 >で、その後に< NAME4 >が続きます>
<ここで、<文字または数字 1 >が先行し、+ <文字または数字 2 >
<ここで、<文字または数字 1 >が先行します+ <文字または数字 2 >
::= <ここで、<文字または数字 1 >が先行します<文字または数字 2 >
<ここで、<文字または数字 1 >は+ <文字または数字 2 >の前にあります
::= <ここで、<文字または数字 1 >は+ <文字または数字 3 >の前にあります
<ここで、<文字または数字 3 >は+ <文字または数字 2 >の前にあります
< a が b に先行する場合> :==
< b が c に先行する場合> :==
[...]
<型> ::= = 実数 | 整数 | ブール値
<名前> ::= = <文字> | <名前> <文字> | <名前> <数字>
<文字または数字> ::= = <文字> | <数字>
<文字または数字 1 > ::= <文字または数字>
<文字または数字 2 > ::= <文字または数字>
<文字または数字 3 > ::= <文字または数字>
<文字> ::= = a | b | c | [...]
<数字> ::= = 0 | 1 | 2 | [...]
<名前1 > ::= = <名前>
<名前2 > ::= = <名前>
<割り当て先> ::= = <名前>
<使用> ::= = <名前>
<名前> ::= = <名前> | <名前> <名前>
<空> ::= =
<タイプマップ> ::= = ( <型指定> <名前> ) <タイプマップ>
<タイプマップ1 > ::= = <タイプマップ>
<タイプマップ2 > ::= = <タイプマップ>
<タイプマップ3 > ::= = <タイプマップ>
元の文法と比較すると、3 つの新しい要素が追加されました。
- 現在のハイパールール内の非終端記号に属性を追加します。
- 属性に許容される値を指定するメタルール。
- 属性値に対する操作を指定するための新しいハイパールール。
新しいハイパールールはεルールです。つまり、空の文字列のみを生成します。
ALGOL 68 の例
ALGOL 68 レポートでは、<山括弧> のない若干異なる表記法が使用されます。
1968年の最終報告書§2.1にあるALGOL 68
a) プログラム: オープンシンボル、標準プレリュード、
ライブラリプレリュードオプション、特定のプログラム、終了、
ライブラリ後奏オプション、標準後奏、終了記号。
b) 標準プレリュード: 宣言プレリュードシーケンス。
c) ライブラリ プレリュード: 宣言プレリュード シーケンス。
d) 特定のプログラム:
ラベルシーケンスオプション、強力な CLOSED void 句。
e) 終了: シンボル、文字 e、文字 x、文字 i、文字 t、ラベル シンボルに進みます。
f) ライブラリ後奏: ステートメント間奏。
g) 標準的な後奏:強い空節列
ALGOL 68 1973年改訂報告書§2.2.1、§10.1.1
プログラム: 強いvoid新しい閉じた節
A) 外部:: 標準; ライブラリ; システム; 特定。
B) STOP :: 文字 s 、文字 t 、文字 o 、文字 p にラベルを付けます。
a) プログラムテキスト: STYLE開始トークン、新しいLAYER1プレリュード、
並列トークン、新しいLAYER1タスクPACK、
STYLE 終了トークン。
b) NEST1プレリュード: DECS1を使用したNEST1標準プレリュード、
NEST1ライブラリプレリュードとDECSETY2、
NEST1システムプレリュードとDECSETY3、ここで(NEST1)は
(新しい EMPTY、新しい DECS1、DECSETY2、DECSETY3)。
c) DECSETY1 を使用した NEST1 EXTERNAL プレリュード:
DECSETY1 による強力な void NEST1 シリーズ、トークンに進みます。
ここで、(DECSETY1) は (EMPTY)、EMPTY です。
d) NEST1タスク: NEST1システムタスクリスト、およびトークン、
NEST1 ユーザータスク PACK リスト。
e) NEST1 システムタスク: 強力な無効 NEST1 ユニット。
f) NEST1ユーザータスク: NEST2 DECSによる特別な前置き、
NEST2 特定のプログラム PACK、トークンに進む、
NEST2 特別後奏曲、
ここで、(NEST2) は (NEST1 新しい DECS STOP) です。
g) NEST2 特定プログラム:
NEST2 新規 LABSETY3 結合ラベル定義
LABSETY3の、強いボイドNEST2新しいLABSETY3
ENCLOSED 句。
h) LABSETYのNEST結合ラベル定義:
ここで、(LABSETY) は (EMPTY)、EMPTY です。
ここで、(LABSETY)は(LAB1 LABSETY1)であり、
LAB1のNESTラベル定義、
$ LABSETY1 の NEST 結合ラベル定義。
i) NEST2 の特別な後奏:
STOP 付きの強力なボイド NEST2 シリーズ。
W文法の威力を示す簡単な例は、節
a) プログラムテキスト: STYLE開始トークン、新しいLAYER1プレリュード、
並列トークン、新しいLAYER1タスクPACK、
STYLE 終了トークン。
これにより、BEGIN ... END および { } がブロック区切り文字として許可されますが、BEGIN ... } および { ... END は除外されます。
このレポートの文法を、Marc van LeeuwenによるALGOL 68のサブセットのYaccパーサーと比較するとよいだろう。 [11]
実装
アンソニー・フィッシャーは 、W文法の大規模なクラス用のパーサーであるyo-yo [ 12]を書きました。これには、 expressions、eva、sal、Pascal(Pascalの実際のISO 7185標準では拡張バッカス・ナウア形式が使用されています)の文法例が含まれています。
ディック・グルーネはW文法のあらゆる可能な生成規則を生成するCプログラムを作成した。 [13]
ALGOL 68以外のアプリケーション
上で述べた拡張接辞文法(EAG)の応用は、EAGがW文法に非常に近いため、事実上W文法の応用とみなすことができます。[14]
W文法は、人間工学における複雑な人間の行動の記述にも提案されている。[要出典]
AdaにはW文法記述も提供されている。[15]
参照
参考文献
- ^ Cleaveland, J. Craig; Uzgalis, Robert C. (1977).プログラミング言語の文法. Elsevier. ISBN 978-0-444-00199-3。
- ^ ab van Wijngaarden, Adriaan (1972-04-04) [Premature and provisional edition 1965-10-22]. MR 76: Orthogonal design and description of a formal language (PDF) (Technical report). Amsterdam: CWI . 2017-10-02 のオリジナル(PDF)からアーカイブ。
- ^ van Wijngaarden, A.; et al. (eds.). 「アルゴリズム言語 ALGOL 68 の改訂レポート」。2002 年 1 月 24 日時点のオリジナルよりアーカイブ。
- ^ Koster, CHA (1996)。「Algol 68 の作成」。Bjørner, D、Broy, M.、Pottosin, IV (編)。システム情報学の展望。コンピュータサイエンスの講義ノート。第 1181 巻。ベルリン: Springer。pp. 55–67。doi : 10.1007 /3-540-62064-8_6。ISBN 978-3-540-62064-8。
- ^ シンツォフ、M. (1967)。 「再帰的に列挙可能なすべてのセットに対する van Wijngaarden 構文の存在」。ブリュッセル科学学会誌。2:115-118。
- ^ デランサート、ピエール、マルシンスキー、ヤン (1993)、「論理プログラムの文法拡張」、論理プログラミングの文法的な見方、MIT プレス、pp. 109–140、doi :10.7551/mitpress/3345.003.0008、ISBN 9780262290845、 2023-06-14取得
- ^ Knuth, Donald E (1990)、「属性文法の起源」( Plain TeX、gZiped )、国際属性文法とその応用会議の議事録、Springer Verlag : 1–12。
- ^ シンツォフ、M. (1967)。 「再帰的に列挙可能なすべてのセットに対する van Wijngaarden 構文の存在」。ブリュッセル科学年報。81:115-118。
- ^ Augusto, LM (2023) .「2レベル文法:van Wijngaarden文法のいくつかの興味深い特性」(PDF)。Omega - Journal of Formal Languages。1:3–34。
- ^ Backus, JW; et al. (1963). 「アルゴリズム言語ALGOL 60の改訂レポート」. The Computer Journal . 5 (4): 349–367. doi : 10.1093/comjnl/5.4.349 .
- ^ 「構文」、アルゴル 68、フランス:ポワティエ大学
- ^ フィッシャー、アンソニー(2024年7月30日)、「yo-yo」、ソフトウェア、英国:ヨーク。
- ^ グルーネ、ディック、2 レベル文生成器、NL : VU。
- ^ アルブラス、ヘンク;メリチャール、ボリヴォイ (1991)。属性の文法、アプリケーション、およびシステム。コンピューターサイエンスの講義ノート。 Vol. 545.スプリンガー。 p. 371.ISBN 978-3540545729。
- ^ Flowers, Roy、「Ada の W 文法記述(PDF) (修士論文)」、空軍工科大学、空軍大学
さらに読む
- Augusto, LM (2023). 「van Wijngaarden文法:決定可能な制約のある構文入門」(PDF) . Journal of Knowledge Structures and Systems . 4:1–39。
- スティーブン・ペンバートン(2016) [1982]。 「2 レベル文法を使用したプログラミング言語の実行可能な意味定義 (Van Wijngaarden 文法)」。アムステルダム: Centrum Wiskunde & Informatica。。
- Petersson, Kent (1990)。「プログラミング言語の構文と意味論」(PDF)。講義ノート草稿。2001 年 6 月 5 日のオリジナル(PDF)からアーカイブ。
