申し分なく、私はプログラミングの初心者であり、これはかなり抽象的な質問であることを認めます。
私たちが毎日話す自然言語は、人々がお互いを理解できるために存在します。特定の言語で書かれたコードをコンピューターがどのように理解できますか?
A氏が新しい言語を作成するとします。機械はそれをどのように受け入れますか?作成者は、新しい言語を作成するために機械語を使用して機械と通信する必要がありますか?機械が正しく理解している間に言語で書けることを保証するものは何ですか?
申し分なく、私はプログラミングの初心者であり、これはかなり抽象的な質問であることを認めます。
私たちが毎日話す自然言語は、人々がお互いを理解できるために存在します。特定の言語で書かれたコードをコンピューターがどのように理解できますか?
A氏が新しい言語を作成するとします。機械はそれをどのように受け入れますか?作成者は、新しい言語を作成するために機械語を使用して機械と通信する必要がありますか?機械が正しく理解している間に言語で書けることを保証するものは何ですか?
回答:
「コンパイラ」という単語を使用して、一連の質問に対する回答全体をほぼまとめることができます。コンパイラは、ソースコードを入力として受け取り、言語設計者が決定した言語規則を適用してコードの意味を理解し、別の言語で同じ意味を持つコードを出力として生成する機能を持つ特別なプログラムです。これは通常、コードを他の高水準言語に変換する専用のコンパイラーが存在しますが、マシンコードまたは何らかの形式のバイトコード(仮想マシンの「マシンコード」)です。ただし、これらはこの質問の範囲を超えています。
すべての言語にコンパイラーがあるわけではありません。代わりにインタープリターを使用するものもあります。これは、プログラムの意味を判断した後にマシンコードを生成する代わりに、ただちにプログラムを実行することを除いて、コンパイラと同じことをすべて行います。ただし、コードの解析(読み取り)とコードの意味の決定の基本原則は同じです。
これよりも詳細に答えると、コンパイラ理論になります。これは非常に幅広いテーマです。トピックに興味がある場合は、「コンパイラ」に関するウィキペディアの記事を読んでリンクを確認することから始めてください。特定の質問がある場合は、ここで気軽に質問してください。
あなたが指摘したように、人間は英語、フランス語、ドイツ語などの「自然な」言語を介して相互に通信します。自然と呼ばれるのは、意図的に発明するのではなく自然に取得するためです(エスペラントは例外です)。
正式な言語とは、何らかの目的で発明された言語です。たとえば、Cなどのプログラミング言語は、コンピューターのプログラミングを目的として考案された正式な言語です。
すべての言語は、文法を使用して説明できます。文法の階層は、1956年にNoam Chomskyによって記述されました。次のレベルで構成されています。
タイプ0の文法(制限のない文法)。それらは最も一般的で、チューリングマシンと同等です。そのため、特定の文字列が無制限の文法の一部であるかどうかを決定する問題は決定不能です。
タイプ1の文法(文脈依存文法)。英語などのほとんどすべての自然言語は文脈依存です。英語の状況依存性の例は、「時間は矢のように飛びます」という2つのフレーズです。「フルーツはバナナのように飛ぶ」一般に、コンピューターが状況依存言語を理解することは困難です。
タイプ2文法(コンテキストなし)。コンテキストフリー言語は、ほとんどのプログラミング言語の構文の理論的基礎です。
タイプ3文法(通常の文法)。正規言語のファミリーは、正規表現によって取得できます。通常、通常の言語は、検索パターンとプログラミング言語の字句構造を定義するために使用されます。
タイプ2(コンテキストなし)およびタイプ3(通常)の文法は、それらのパーサーを効率的に実装できるため、ほとんどの場合コンピューターで使用されます。
BNF(Backus Normal FormまたはBackus–Naur Form)は、文脈自由文法の表記法であり、コンピューティングで使用される言語の構文を記述するためによく使用されます。
たとえば、識別子は次のように記述できます。
<identifier> ::= <letter> { <letter> | <digit> }
つまり、文字で始まる必要があり、追加の文字または数字を含めることができます。
以前、文字は「a」と定義されています| 'b' | 「c」など。数字は、同じタイプの表記法を使用して「0」から「9」として定義されます。
AC「for」ステートメントは次のように定義できます。
<for_statement> ::=
'for' '(' <expression> ';' <expression> ';' <expression> ')' <statement>
次に、特定の言語のBNFによって記述された特定の文法を受け入れるために、字句解析器およびパーサー(コンパイラーまたはインタープリターの最初の段階)が構築されます。通常、字句アナライザーは、言語のさまざまなトークン(キーワード、識別子、数字など)を分離するために使用され、パーサーは、「for」ステートメントの構築方法など、トークンがどのように連携するかを把握するために使用されます。
まず、それが何であるかという観点から「言語」を定義しましょう。言語には、最初に語彙(コミュニケーションの対象となる概念を定義する単語のリスト)、次に構文(コミュニケーションの構造を定義する「プライマー」または一連の規則)が必要です。
この最も基本的なレベルでは、C#は英語とそれほど違いはありません。C#を「プログラミング言語」にするのはその意図であり、したがってその設計です。個々の低レベルコマンドに要約されるように設計されています。そのため、事前定義された語彙は制限され、構文は非常に厳密に実施され、言語全体は「オーディエンス」(コンピューター、より正確にはダイジェストするコンパイラー)ソースコードを単純なコマンドの「中間言語」に変換し、「ランタイム」でさらにマシンコードに変換できます)。C#で散文や詩を書くことはありません。可能な限り最も明確な方法でジョブを実行するようにコンピューターに指示します。
コンピューターの場合、はい、通常コンパイラーと呼ばれるツールは、コードで記述したものを取得し、コンピューターが使用できる命令に変換するために必要です。コンピューターサイエンスは、ほとんどのテクノロジーと同様に、本質的に反復的な「レイヤード」プロセスです。コンピュータが最初に発明されたとき、それらはバイナリ命令を手動で入力することによってプログラムされました。これらの命令は、プロセッサごとに16進数の「マシンコード」に標準化されました。違いは、人間に表示するために2進数がどのようにグループ化されるかだけです。次に、アセンブラコードでは、プログラムの作成時にコマンドのリストとレジスタ名などの基本的な識別子が16進コードに置き換えられました。ASMは、ネイティブマシンコードに1:1で変換できます。飛躍的な進歩は、第3世代の「命令型」プログラミング、基本的には、変数やロジックループなど、人間が理解できる抽象的な概念を取り入れ、それらをキーワードと構文に基づくパターンを使用してネイティブ命令にダイジェストします。COBOL、FORTRAN、Pascal、Cなどの初期の言語は、人間が特定の機械語(通常は8086 ASM)に「翻訳」することができます。その後、オブジェクト指向プログラミングの革命が起こりました。これは基本的に、状態とロジックの何らかの組み合わせを持つ「オブジェクト」に概念的にカプセル化されるコードを定義する追加の構文規則です。特定の機械語(通常は8086 ASM)への人間による。その後、オブジェクト指向プログラミングの革命が起こりました。これは基本的に、状態とロジックの何らかの組み合わせを持つ「オブジェクト」に概念的にカプセル化されるコードを定義する追加の構文規則です。特定の機械語(通常は8086 ASM)への人間による。その後、オブジェクト指向プログラミングの革命が起こりました。これは基本的に、状態とロジックの何らかの組み合わせを持つ「オブジェクト」に概念的にカプセル化されるコードを定義する追加の構文規則です。
今日、私たちは「第4世代」の言語に精通しています。これは、マシンに直接ではなく、他のプログラムとの通信を定義するために書かれた言語です。広く定義されているものには、XML / HTMLのような「マークアップ」言語、JavaScriptやSQLのような「スクリプト」言語、およびJavaや.NET Frameworkなどの「サンドボックス」言語の大部分が含まれます。マシンおよびプラットフォーム固有の詳細を抽象化するランタイム)。また、それは関数型プログラミング言語の領域を包含すると言うこともできます。関数型プログラミング言語は、ランタイムに大きく依存しており、マシン固有の詳細だけでなく、操作固有の詳細も抽象化します。これらの第4世代言語は、多かれ少なかれ、人間がネイティブの機械語命令に翻訳することは不可能です。そしてポイントは、それは価値のある努力ではないということです。これらの言語の強みは、それらが最終的にコンピューターに低レベルで何をすべきかを伝えるために使用される階層化プロセスです。
いい質問ですね。適切な答えは、「コンピューターサイエンス」と呼ばれるもののかなりの半分を形成します。
手始めに、私は表象的および操作的なセマンティクスをざっと読んでからこの本を読むことをお勧めします。プログラミング言語とは何か、それを正式に定義する方法について、多かれ少なかれしっかりと理解できるでしょう。
上記が少しアカデミックすぎる場合は、Petzold「Code」から始めて、セマンティクスに戻ることができます。
プログラミング言語でプログラムを作成する場合、別のプログラムがプログラム内のシンボルをコンピューターが理解できるシンボルに変換します。これにはいくつかの手順が必要になる場合があります。Cの例:
ユーザーはプログラムを高水準言語(C)で記述します。これはCPUには理解されませんが、プログラマーには直接理解されます(願っています!)。
コンパイラはCをAssmebly言語に変換します。この言語はCPUに直接理解されませんが、他の言語に簡単に変換できます。
アセンブラーは、アセンブリをCPUによって直接理解されるバイナリコードのシーケンスに変換します。一部のコンパイラは、上記の手順(手順2)をスキップして、ソースコードからコンパイル済みバイナリを直接生成します。
コンピューターがプログラムを理解することを保証するために、コンパイラーまたはインタープリターはエラーを出し、通常、構文エラーなどのコンパイルできないものに遭遇すると停止します。プログラムをコンパイルできない場合、プログラムが「理解」しなかったため、プログラムが実行を試みて失敗する段階に達することはありません。
新しい言語を作成するには、まず高レベル言語を設計し、次に新しい言語のシンボルをCPUが理解するアセンブリ言語コマンドにマップする方法を見つける必要があります。