プログラミング言語は、人間がコンピュータに命令を指示するために作られており、コンピュータが曖昧さなく解析できるように設計されている。多くの場合構文上の間違いは許されず、人間はプログラミング言語の文法に厳密にしたがった文を入力しなければならない。
これに対して、一般に自然言語の文法規則はプログラミング言語にくらべてはるかに複雑であり、例外も多い。ただしこれは規則が一般にいいかげんであったり、曖昧であるということではない。一般に自然言語の規則は奥が深く、驚くほどの合理性に裏打ちされていることがある。
また、自然言語の意味は、その文脈(コンテキスト)によって定まる部分も多い。これに対して、プログラミング言語は、コンピュータによって扱いやすいように、文脈によって意味が変わることができるだけないように設計されている。
自然言語は、誤用や流行などにより長い時間をかけ、たくさんの人間の利用により、意図せざる形で変化していく。しかし、プログラミング言語の規則は、言語設計者の意図と作業によってのみ、変更される。
人間がふだん使っている日本語などの自然言語を使ってコンピュータに指示することができるのが理想ではある。しかし、自然言語はあまりにも複雑で曖昧で変則的なので、それを機械語に翻訳できるようなプログラムを作成することはとても難しい。そのような研究も進められているが、未だに汎用で実用になるプログラムは作成されたことがない。
そこで、自然言語よりも制限が強く、単純で厳密で規則的な人工言語を作って代用する。これがプログラミング言語である。プログラミング言語は自然言語よりもいくらか人間には扱いづらいが、機械語よりは遥かに親しみやすく、人間の指示の手間を軽減している。ちなみにコンピュータ向けの形式性と人間向けの柔軟性を兼ね備えるロジバンなど、本来の開発目的が違えど潜在的に一つのプログラミング言語として機能しうるものもある。
自然言語と異なりほとんどのプログラミング言語は厳密に定義されており、規則に従わないプログラムは実行されない。大部分のプログラミング言語の文法は文脈自由文法によって定義されている。
文法シンタックスハイライトはソースコードを認識しやすくする。ここでの言語はPython。
プログラミング言語の見た目は、その構文(統語論)で決定される。多くのプログラミング言語は文字だけで構成され、単語や数や区切り記号の並びであり、自然言語に似ている。一方で、グラフィカルなプログラミング言語もあり、プログラムをグラフィカルなシンボル間の関係で表す。
言語の構文は、構文的に正しいプログラムを形成するシンボルの組合せを規定するものである。シンボルの組合せの意味は意味論で与えられる。多くの言語は文字で構成されるため、以下ではそれについて論じる。
プログラミング言語の構文は一般に、字句解析用の正規表現と構文解析用のバッカス・ナウア記法(文脈自由文法)で定義される。下記はLISPに関する単純な構文である。
expression ::= atom | list
atom ::= number | symbol
number ::= [+-]?['0'-'9']+
symbol ::= ['A'-'Z''a'-'z'].*
list ::= '(' expression* ')'
この構文は次のような意味である。
expression は atom または list である。
atom は number または symbol である。
number は1文字以上の数字列であり、オプションとして符号が前置される(空白は含まない)。
symbol はアルファベットで始まる任意の文字列である(空白は含まない)。
list は括弧記号の対であり、その間に0個以上の expression がある。
これに従うトークン列の例として、'12345'、'()'、'(a b c232 (1))' などがある。
構文上正しいプログラムが全て意味論的にも正しいとは限らない。つまり、プログラミング言語の文法は、構文と意味論の両方がそろって成立する。また、構文的にも意味論的にも正しいプログラムだとしても、それを書いた人の意図を正しく反映していない場合もある。
自然言語を例にすると、文法的に正しい文に「偽」となるような意味を与えることもできる。
"Colorless green ideas sleep furiously."(直訳すると「無色の緑色のアイデアは猛烈に眠る」)は文法的には正しいが意味のない文である。
"John is a married bachelor."(ジョンは既婚の独身男である)は文法的には正しいが、決して真とは言えない文である。
以下のC言語のコード断片は構文上は正しいが、意味論的には正しくない(p はヌルポインタなので、p->real と p->im には意味がない)。complex *p = NULL;complex abs_p = sqrt (p->real * p->real + p->im * p->im);
プログラミング言語の文法はチョムスキー階層内で分類可能である。多くの言語の構文は文脈自由文法を使って記述される[11]。
詳細は型システムを参照
型システムは、プログラミング言語において値や式を「型」に分類し、その型をどう扱うかを定義するものである。これには一般に、その言語で構成可能なデータ構造の定義が含まれる。数理論理学を使った型システムの設計および研究を型理論という。
内部的には、デジタルコンピュータでは全てのデータが0と1(二進法)で格納されている。
型のある言語とは、あるデータ型について定義されている操作を他のデータ型の値に対して実行できないものを指す[12]。例えば、"this text between the quotes" は文字列型の値である。多くの言語では、数を文字列で割る操作には意味がない。そのため、そのような操作をしようとしているプログラムは拒絶される。言語によっては、そのような意味のない操作をコンパイル時に検出し(静的型検査)、コンパイラが拒絶する。また、言語によっては実行時に検出し(動的型検査)、例外処理が呼び出されることになる。
型のある言語の特殊例として、単一型言語がある。REXXやSGMLといったスクリプト言語やマークアップ言語は、単一のデータ型しか扱わない(多くの場合、そのときのデータ型は文字列型である)。
対照的にアセンブリ言語などの型のない言語は、任意のデータに任意の操作を実行可能であり、データは単にある長さのビット列として扱われる[12]。高級言語で型を持たない言語としては、BCPLやForth系言語の一部などがある。
型理論的に厳密な型適用をしている言語は少なく、多くの言語はそれなりの型システムを採用している[12]。