一言で言えば
プログラミング言語は、プログラムを文字列として表す構文と、プログラムの意図する意味であるセマンティクスで構成されます。
形式言語は意味のない構文です。通常、これらの文字列に意味を付けることなく、形式的に定義された文字列のセットの構造を調べることを目的としています。
正規表現およびその他の形式(コンテキストフリー文法など)は、プログラミングおよび自然言語の構文コンポーネントとして使用される形式言語を定義するために使用されます。つまり、構造化された方法で文を表します。他のメカニズムを使用して、その構造をプログラミング言語のセマンティクスと関連付けます。
ここでは、特に自然言語に関して、かなり簡略化されています。
もっと詳細に
あなたの質問に答えるには、最初から始めなければなりません。通常の意味での言語は、非公式には、情報やアイデアを伝える手段です。言語では、通常、構文とセマンティクスを区別します。セマンティクスは、あなたが話したい/書きたいものです。伝えたい情報。構文は、それを伝えるために使用する手段です。つまり、人々間で交換できる従来の表現であり、現在は人々とデバイス間、またはデバイス(コンピューター)間でも交換できます。
通常、dog
犬のアイデアを伝えるためにこの言葉を使用します。単語dog
は3文字または同等の音で構成されており、ある種の動物を表すことを目的としています。重要な考え方は、コミュニケーションは、伝えられるものの表現を通じて行われるということです。通常、表現構造は構文と呼ばれ、表現されるものはセマンティクスと呼ばれます。これは、プログラミング言語だけでなく、自然言語にもほぼ当てはまります。
単語は、多かれ少なかれ基本的なセマンティック概念を表すための構文エンティティです。しかし、これらの基本的な概念は、より複雑な意味を与えるためにさまざまな方法でまとめる必要があります。私たちthe dog
は特定の犬を意味することをthe dog bites the cat
伝え、より複雑なアイデアを伝えるために書き
ます。しかし、犬と猫のどちらが実際にもう一方を噛んでいるかを知ることができるように、言葉の構成方法はルールによって修正する必要があります。
そのsentence -> subject verb complement
ため、文に一致し、各部分に関連付けられたアイデアがどのように明確化されるかを示すルールがあります。これらの規則は、メッセージの表現がどのように編成されるかを教えてくれるため、構文規則です。subject
自体はルールによって定義することができますsubject -> article noun
ように、と。
2 x + 1 = 23バツ123
equation -> expression "=" expression
expression -> expression "+" expression
expression -> number
プログラミング言語の構造は同じです。プログラミング言語は、解決すべき問題、定理の証明、または動物間の友好関係を表すのではなく、実行する計算を表すことに意味的に特化しています。しかし、それが主な違いです。
構文で使用される表現は、通常、文字列、または話し言葉の音の文字列です。セマンティクスは通常、抽象的な領域に属しているか、現実に属している可能性がありますが、それでも思考プロセスやデバイスの動作領域に抽象化されています。通信では、情報/アイデアを構文にエンコードし、受信者が送信およびデコードします。その結果は、受信者によって何らかの方法で解釈されます。
したがって、この言語で見られるのは、ほとんど構文とその構造です。上記の例は、構文文字列とその構造編成を定義する最も一般的な方法の1つにすぎません。他にもあります。特定の言語では、一部の文字列に構造を割り当てることができ、その言語に属すると言われますが、そうでない文字列もあります。
言葉についても同じことが言えます。いくつかの文字(または音)のシーケンスは正当な単語ですが、他のシーケンスはそうではありません。
形式言語は意味論のない単なる構文です。アルファベットの基本要素を使用して、構築可能なシーケンスを一連のルールで定義します。ルールは非常に多様で、時には複雑になる場合があります。しかし、正式な言語は、自然言語であれプログラミング言語であれ、言語コミュニケーションを超えた多くの数学的な目的に使用されます。言語の文字列を定義する一連の規則は、文法と呼ばれます。しかし、言語を定義する方法は他にもたくさんあります。
実際には、言語は2つのレベルで構成されています。字句レベルは、文字のアルファベットから構成される単語を定義します。構文レベルは、文、または単語のアルファベット(より正確には単語ファミリのアルファベットで構成されているため、有限のアルファベットのままである)から構成されるプログラムを定義します。これは必然的にいくらか単純化されます。
単語の構造はほとんどの言語(プログラミングまたは自然)でかなり単純であるため、通常、最も単純な形式言語と見なされるものである通常言語で定義されます。これらは正規表現(regexp)で定義でき、有限状態オートマトンと呼ばれるプログラムされたデバイスでかなり簡単に識別できます。プログラミング言語の場合、単語の例は、識別子、整数、文字列、実数、if
またはなどの予約語repeat
、句読点記号、または開き括弧です。単語ファミリの例は、識別子、文字列、整数です。
構文レベルは通常、少し複雑な形式の言語、つまり単語をアルファベットとして使用するコンテキストフリー言語によって定義されます。上で見た規則は、自然言語の文脈自由な規則です。プログラミング言語の場合、ルールは次のとおりです。
statement -> assignment
statement -> loop
loop -> "while" expression "do" statement
assignment -> "identifier" "=" expression
expression -> "identifier"
expression -> "integer"
expression -> expression "operator" expression
このようなルールを使用すると、次のように記述できます。
while aaa /= bbb do aaa = aaa + bbb / 6
これは声明です。
そして、その生成方法は、解析ツリーまたは構文ツリーと呼ばれるツリー構造で表すことができます(ここでは完全ではありません)。
statement
|
_______________ loop _______________
/ / \ \
"while" expression "do" statement
__________|_________ |
/ | \ assignment
expression "operator" expression _______|_______
| | | / | \
"identifier" "/=" "identifier" "identifier" "=" expression
| | | |
aaa bbb aaa ... ...
規則の左側に表示される名前は非終端記号と呼ばれますが、単語は言語のアルファベット順(字句レベルより上)であるため、終端記号とも呼ばれます。非終端記号は、プログラムを構成するために使用できるさまざまな構文構造を表します。
このようなルールはコンテキストフリーと呼ばれます。非終端記号は、出現するコンテキストに関係なく、対応するルールを使用して任意に置き換えることができるためです。言語を定義する一連のルールは、コンテキストフリー文法と呼ばれます。
実際には、識別子を最初に宣言する必要がある場合、または式が型の制限を満たす必要がある場合、それに制限があります。しかし、そのような制限は、構文的なものではなく、意味的なものと見なされる場合があります。実際、一部の専門家は静的セマンティクスと呼ばれるものにそれらを配置します
。
任意の文、任意のプログラムが与えられると、その文の意味は、この文の解析ツリーによって与えられた構造を分析することによって抽出されます。そのため、プログラムが与えられたときに、プログラムに対応するツリー構造を回復できるパーサーと呼ばれるアルゴリズムを開発することが非常に重要です。
パーサーの前には、単語を認識し、それらが属するファミリーを判別する字句アナライザーがあります。次に、基礎となるツリー構造を取得するパーサーに一連の単語または語彙要素が与えられます。この構造から、コンパイラーはコードを生成する方法を決定できます。これは、コンパイラー側のプログラム処理のセマンティック部分です。
コンパイラのパーサーは、実際には解析ツリーに対応するデータ構造を構築し、それをコンパイルプロセスの後の段階に渡すことができますが、そうする必要はありません。解析アルゴリズムの実行は、プログラムテキストに暗黙的な構文ツリーを探索するための計算戦略の開発に相当します。この構文/解析ツリーは、コンパイル戦略(ステージ数)に応じて、プロセスで明示的にされる場合とされない場合があります。ただし、必要なのは、計算構造で明示的に指定されているか、暗黙的に残されているかにかかわらず、最終的に解析ツリーのボトムアップ探索が少なくとも1回行われることです。
その理由は、直感的には、構文木構造に関連付けられたセマンティクスを定義する標準の正式な方法は、準同型と呼ばれるものを使用するためです。大きな言葉を恐れないでください。アイデアは、単に全体の意味がパーツの意味から構築され、それらを接続する演算子に基づいて考慮することです
たとえば、文the dog bites the cat
はルールを使用して分析できますsentence -> subject verb complement
。3つのサブツリーの意味を知ることsubject
、verb
およびcomplement
、それらを構成するルールは、対象者がアクションをやって、そして猫がかまされたものであるとされていることを教えてくれる。
これは直感的な説明にすぎませんが、形式化できます。セマンティクスは、構成要素から上向きに構築されます。しかし、これは多くの複雑さを隠しています。
コンパイラの内部動作は、いくつかの段階に分解できます。実際のコンパイラは、中間表現を使用して段階的に動作する場合があります。また、いくつかの段階をマージする場合があります。これは、使用する技術と、手元の言語のコンパイルの複雑さに依存します。