予約語(よやくご、(英: reserved word)とは、プログラミング言語などの人工言語の仕様に定められているもので、ユーザープログラムの開発者が自分で付ける識別名としては利用できない特定の文字列のこと。たとえば変数名や関数名などに使用することができない、とあらかじめ定められた文字列(単語、字句など)のこと。あるいは、プログラミング言語などにおいて、固定された意味を持っており、その結果、プログラマーの側ではその意味を再定義できない語。

## 概要

予約語と似た言葉に「キーワード」(keyword) があるが、プログラミング言語の種類、また文脈によってreserved wordとkeywordは全く違う意味を持ちうるので、両者は異なる用語・概念と扱われている場合が多い。

キーワードであっても予約語でないこともあるし、その逆もある。たとえばECMAScript (ECMA-262) 5th Edition (ES5) では、`class`や`extends`は予約語だが言語で使われておらずキーワードではない。しかしECMA-262 6th Edition (ES6) では新たにサポートしたクラス構文のために使われるキーワードとなった。ECMA-262 では、キーワードは予約語の部分集合で、言語で制御構造などの意味を持つ予約語がキーワードである。Javaでは言語で使われていない`goto`や`const`もキーワードである。SQLには予約されたキーワードと予約されていないキーワードがある。例にも出てきたように、個々の規格によっても両者それぞれ微妙に意味が違うこともある。

なお、FORTRANやPL/Iのように予約語を持たないプログラミング言語もある。

「予約されたキーワード」(reserved keywords) や「予約されていないキーワード」(unreserved keywords) という用語が使用されている場合もある。

共通言語基盤 (CLI) 向けの共通言語仕様 (CLS) にしたがって実装されたC#やVB.NETでは、キーワードを識別子として利用する構文が用意されている。

- C#では`@class`などのように先頭に`@`をつけることで識別子として利用することができる。
- VB.NETでは`[Class]`などのように`[...]`で囲むことで識別子として利用することができる。
- F#では``` ``class`` ```などのように``` ``...`` ```で囲むことで識別子として利用することができる。

上記の機能は、CLSを満たす他の.NET言語で記述されてアセンブリに公開されたシンボルの名前を使う場合などでも有用である。例えばC#では`Dim`はキーワードではないため、プロパティなどの名前として使用できるが、VB.NETではキーワードであるためそのままでは使えず、相互運用に支障が出る。そこで、シンボル名を使用する際に`[Dim]`と記述することでVB.NETでも識別子として使えるようになる。

## 主な言語の予約語やキーワード

### C言語

C言語はキーワード (keywords) の他、予約済みの識別子 (reserved identifiers) を持つ。正確な詳細は ISO/IEC 9899 規格を参照のこと。

なお、IBMのz/OSのドキュメントでは「reserved keywords」と呼んでいるが、この用語はCの標準規格に準じたものではない。

### C++

C++には、C言語由来のキーワードと、C++で新たに追加されたキーワードがある。また、予約済みの識別子のルールもCと似ているが、若干異なる部分がある。

### C#

C#の構文はC/C++やJavaによく似ており、キーワードも類似している。

### COBOL

COBOLは、500ほどの予約語がある。

### FORTRAN

FORTRANにはキーワードがあるが、予約語を持たない。そのため、ユーザー定義の名前(識別子)に`if`や`goto`のようなキーワードと同じ綴りを使うこともできるが、プログラムの可読性やメンテナンス性を著しく下げるため使うべきではない。

隣接するキーワードは、その間に1つ以上の空白文字を入れる必要があるものもあれば、必要がないものもある。例えば`GO TO`を`GOTO`と書くことはできるが、`DO WHILE`を`DOWHILE`と書くことはできない。

### Java

Javaの構文はC/C++によく似ており、キーワードも類似している。

### Pascal

Pascalでは特殊記号 (special-symbol) の中に含まれる部分集合として、綴り記号 (word-symbol) という用語が使われる。『PASCAL 原書第4版』(培風館、1981)では word symbol の訳として「綴り記号」という用語を使っている。また、同書には「綴り記号(すなわち予約語)」という記述がある(p.12)。

ISO/IEC 7185:1990 の翻訳である JIS X 3008:1994「プログラム言語Pascal」では、「word-symbol」に対して「予約語」という翻訳を割り当てている。

特殊記号は、`+`, `-`などの演算子に使われる記号に加えて、`begin`, `end`などの綴り記号を含む。

## 典型的な予約語・キーワード

- フロー制御を表す単語(`if`、`while` など)
- プログラムの構成要素を表す単語(`function`、`class` など)
- プログラムの構成要素を修飾する単語(`static`、`const` など)
- 組み込み関数(`open`、`read`など)
- 組み込みの型(`int`、`string`など)
- 他の言語などと混同して、誤用される可能性のある語(Javaの`goto`、`const`など)
- 将来キーワードとして利用するかも知れない語(JavaScriptの`let`、`super`)
- 過去にキーワードだったため意味が無くなった後も(将来的な再利用のために)残してあるもの(C++11の`export`、C++17の`register`)

なお、C系の言語では、BASIC系の言語における`ELSEIF`に直接相当するキーワードおよび構文は存在しない。C系言語の`else if`は複合キーワードや専用構文などではなく、`else`節に続く別のネストされた`if`文とみなされる。処理系によっては、あらかじめ定められたネスト数の上限に達するとコンパイルエラーとなる。

## キーワード指向の言語と記号指向の言語

抽象構文的には全く違いは無いにもかかわらず、具象構文・字句構文(lexical syntax)的な違いは見た目の違いとしてわかりやすいこともあり、しばしばプログラマの好みの問題になりやすい。代表的にはブロックが `{ ... }` か `begin ... end` か、などといった点であるが、そういった要素に記号を多用しがちな言語と、キーワードを多用しがちな言語がある。記号を使うのは簡潔だが、やりすぎると一見では暗号のようになりかねない(PerlやAPLなど)。キーワードを使う言語は冗長だが明示的という点は利点だが、識別子に使える名前が制限され、フォントを変えるなどシンタックスハイライトの支援がないと見た目にも区別しづらい。キーワードは全て大文字とし、識別子には必ず大文字アルファベット以外の文字が含まれるようにする、といった解決法もある。近年はISO 646の国際版に、世界的に7ビットの文字コードは定着したが、以前は、あるいは今もEBCDICは絶滅していないので記号は自由に使えない場合もあった。

## コンテキストキーワード

コンテキストキーワード (contextual keywords) はC#やC++などの言語で採用されている特殊なキーワードで、文脈キーワード、文脈依存キーワード (context-sensitive keywords) とも言われる。

言語を後から拡張する場合、新しい構文やキーワードあるいは予約語を追加すると既存のコードとの互換性が壊れてしまう場合がある。例えば、既存の変数やメソッドの名前が新しいキーワードあるいは予約語と同じだった場合、新しい言語仕様では構文エラーとなる。しかし、完全に将来の拡張を予期してあらゆるキーワードを予約しておくことは困難であり、予約語が拡張の障害になりうる。

そこで、新しく拡張された構文の中でのみキーワードとして動作するのがコンテキストキーワードである。コンテキストキーワードは特定の構文以外では変数などの名前として使用できるため、既存のコードを破壊することがない。

例えば、C#のプロパティ構文では、C# 1.0の登場当初から`get`、`set`、`value`という多くの名前に使われているであろう語をコンテキストキーワードとして定義している。これは例えばC/C++やJavaのコードをC#に移植する際に、名前の衝突を避けるのに役立つ。C# 5.0で追加されたasync/await構文でも、コンテキストキーワードを利用して言語仕様が拡張されている。

Cでは、例えば`include`や`elif`などはプリプロセッサディレクティブの文脈では命令のひとつとして認識されるが、それ以外では通常のユーザー定義識別子として使用することもできる。

C++では、例えばC++11で追加された`override`や`final`は単独ではキーワードではなく、通常は変数名や関数名などの識別子として使用することもできるが、文脈によっては特殊な意味を持つようになる。

マイクロソフトによる独自の言語拡張であるC++/CLIおよびC++/CXでは、プロパティやデリゲートなど、標準C++からの拡張機能に関連するキーワードはすべてコンテキストキーワードとして規定されている。

### コンテキストキーワードの問題点

- 文脈によってキーワードか否かが決まるので正規表現などでは判断しがたいこともあり、テキストエディタのシンタックスハイライトを正確に行うのが困難なこともある。
- パーサ(構文規則)が複雑になる場合もある。
- 他のスコープの変数やクラスメンバなどを使用する際に、新しい構文の中でも識別子として利用しないといけない場合があり、コンテキストキーワードだけでは回避できない(以下のC#によるコード例を参照)