Forthの柔軟性が文法を不適切にするのはなぜですか?


10

私は最近、スタックベースのプログラミング言語を書く仕事を引き受けました。しかし、自分の言語の設計を始める前に、既存のスタックベースの言語を読んで実験するのは良い考えだと思いました。

これにより、この投稿のトピックに移動します。私は、Postfixスタイルの式を使用するスタックベースの言語であるForthに関するWikipediaの記事を読んでいました。記事では、私は次の声明を見ました:

Forthの柔軟性により、静的なBNF文法が不適切になり、モノリシックコンパイラーがありません。コンパイラを拡張するには、文法を変更して基礎となる実装を変更するのではなく、新しい単語を書くだけで済みます。

私の理解では、フォースの専門用語では、「単語」という用語は基本的に「サブルーチン」と同義のようです。これを考えると、上記のステートメントは奇妙に思えます。Forthで新しい関数を作成する機能がForthの正式な文法を不適切にするのはなぜですか?定義する新しいサブルーチンごとに文法を書き直す必要があるのはなぜですか?環境で新しい単語を書くことは、コンパイラの拡張をどのように構成しますか?上記のステートメントは、新しい関数を定義できるため、正式な文法はPythonには不適切であると言っているように見えます。

実際、私は以下のForthの単純なサブセットに対してBNFスタイルの文法を書くことを試みることにしました。

program        ::= stmt+
stmt           ::= func | expr
func           ::= ':' expr+ ';'
expr           ::= INTEGER | word
word           ::= ('+' | '-' | '*' | '/' )

上記の文法は、Forthステートメントの有効なサブセットをカバーしているように思われ、Forth言語のすべての有効なステートメントをカバーするように拡張することはそれほど難しくないと思われます。さらに、コンパイラーのパーサーが上記の文法を実装している場合、コンパイラーがどのように拡張されるかはわかりません。コンパイラは、環境に新しい単語を追加するだけです。環境のみが変更されます。まるで、上記のWikipediaからの抜粋は、コンパイラー(変更されない)構成する下線コードとコンパイラーの環境(変更される)融合しているようです。

要約すると、なぜ新しい単語(サブルーチン)を定義するForthの能力が、書かれた文法には不適切なのでしょうか。


1
「不適切」は、この文脈での強い言葉です。より良い言葉はおそらく「不必要」でしょう。
ロバートハーベイ、

1
ああ、大丈夫@RobertHarvery。しかし、それが事実である場合、私が引用した抜粋はほとんどの言語に当てはまるようです。厳密には文法は必要ありません、特にパーサーを手書きする場合には文法は必要です。
クリスチャンディーン

しかし、ほとんどの言語では、パーサーはユーザーコードによって変更できる単純なランタイムライブラリではないため、次の行の解析方法に影響を与えます。
イェルクWミッターク

回答:


10

「通常の」単語は、ほとんど単なるサブルーチンです。

...ただし、コンパイラの動作を変更するユーザー定義の定義語を記述できます。たとえば、定義は通常、コロン( ":")で始まり、セミコロン( ";")で終わります。ただし、必要に応じて、(たとえば)コロンの動作を変更したり、その過程で単語定義を「コンパイル」する方法を変更したり、コンパイラの動作を変更したり、認識される言語の文法を変更したりできます。

これが文法が不適切であると言っている理由です-文法はプログラムのある部分から別の部分に文字通りかなり変わる可能性があります。辞書をロードすると、名前が現在認識されているサブルーチンだけでなく、新しい単語を定義するときに解析される文法も変更される可能性があります。


2
Forthのこのプロパティは、セマンティクスだけでなく、文法を本当に変更しますか?
Doc Brown

@DocBrown:Forthを使用するほとんどの人はかなり気に入っているので、通常、手元のタスクに必要な最小限の変更のみを行います。野心的でクレイジーな人なら、必要に応じて構文を完全に変更することができます。
Jerry Coffin

@DocBrown ForthでCインタープリターを記述して、プログラムの途中で突然Cに切り替えることができるような文法はどのようなものに書けますか?
user253751 2018年

@immibis:ええ、私の質問です-Forthは本当にこのようなものを許可しますか?そのリンクされた記事から、これは本質的に私には明確ではありません。
Doc Brown

@DocBrownはい、あります。コンパイル時にコードを実行できます。つまり、必要に応じて、コンパイラを完全に引き継ぐことができます。基本的に、Forthコンパイラー/インタープリターの途中でCコンパイラー/インタープリターを実行できます。(最終的にForthに戻るかどうかはあなた
次第

3

Forthでは、コンパイル時にコードを実行できます。

特に、入力からの単語を消費するコードを実行できます。たとえば、ForthでCコンパイラを記述し、それをコンパイル時に呼び出してから、残りのプログラムをCで記述できます。

より一般的には、ソースコードから引数を読み取る単語を定義できます。従来は、コンパイラと同じ方法で単語を読みますが、必須ではありません。

たとえば、."単語(文字列を出力する)は、次のスペースまで読み取られません"。次のスペースまで読み取られます。の: PRINTHELLO ." Hello ; : func2 world!" ;特別なケースなしでコードを解析しようとすると、."正しく解析されないことがわかります。

あなたは確かにするために、特別なケースを追加することができ."、あなたの文法に、しかし、のようなプログラマは、自分の言葉を定義する場合、文法はまだ不正確になります."-例えば、ここで一つです:: MY_PRINT POSTPONE ." ; IMMEDIATE。この単語はと同等."です。私が書くことができMY_PRINT Hello ; world! "、あなたの文法はそれを解析できる必要があります。頑張ってください。

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