予約語
概要編集
予約語と似ていてしばしば混同されてしまう言葉に「キーワード」(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) という用語が使用されている場合もある[4][5]。
共通言語基盤 (CLI) 向けの共通言語仕様 (CLS) にしたがって実装されたC#やVB.NETでは、キーワードを識別子として利用する構文が用意されている。
- C#では
@class
などのように先頭に@
をつけることで識別子として利用することができる[6]。 - VB.NETでは
[Class]
などのように[...]
で囲むことで識別子として利用することができる[7]。 - F#では
``class``
などのように``...``
で囲むことで識別子として利用することができる[8]。
上記の機能は、CLSを満たす他の.NET言語で記述されてアセンブリに公開されたシンボルの名前を使う場合などでも有用である。例えばC#ではDim
はキーワードではないため、プロパティなどの名前として使用できるが、VB.NETではキーワードであるためそのままでは使えず、相互運用に支障が出る。そこで、シンボル名を使用する際に[Dim]
と記述することでVB.NETでも識別子として使えるようになる。
主な言語の予約語やキーワード編集
Ada編集
C言語編集
C言語はキーワード (keywords) の他、予約済みの識別子 (reserved identifiers) を持つ[9][10]。正確な詳細は ISO/IEC 9899 規格を参照のこと。
なお、IBMのz/OSのドキュメントでは「reserved keywords」と呼んでいる[11]が、この用語はCの標準規格に準じたものではなく、厳密には誤りである。
C++編集
C++には、C言語由来のキーワードと、C++で新たに追加されたキーワードがある[12]。また、予約済みの識別子のルールもCと似ているが、若干異なる部分がある[13]。正確な詳細は ISO/IEC 14882 規格を参照のこと。
C#編集
C#の構文はC/C++やJavaによく似ており、キーワードも類似している。
COBOL編集
FORTRAN編集
FORTRANにはキーワードがあるが、予約語を持たない。
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
[15]) - 過去にキーワードだったため意味が無くなった後も(将来的な再利用のために)残してあるもの(C++11の
export
[16]、C++17のregister
[17])
キーワード指向の言語と記号指向の言語編集
抽象構文的には全く違いは無いにもかかわらず、具象構文・字句構文(lexical syntax)的な違いは見た目の違いとしてわかりやすいこともあり、しばしばプログラマの好みの問題になりやすい。代表的にはブロックが { ... }
か begin ... end
か、などといった点であるが、そういった要素に記号を多用しがちな言語と、キーワードを多用しがちな言語がある。記号を使うのは簡潔だが、やりすぎると一見では暗号のようになりかねない(PerlやAPLなど)。キーワードを使う言語は冗長だが明示的という点は利点だが、識別子に使える名前が制限され、フォントを変えるなどシンタックスハイライトの支援がないと見た目にも区別しづらい。キーワードは全て大文字とし、識別子には必ず大文字アルファベット以外の文字が含まれるようにする、といった解決法もある。近年[いつ?]はISO 646の国際版に、世界的に7ビットの文字コードは定着したが、以前は、あるいは今もEBCDICは絶滅していないので記号は自由に使えない場合もあった。
コンテキストキーワード編集
コンテキストキーワード (contextual keywords) はC#やC++などの言語で採用されている特殊なキーワードで、文脈キーワード、文脈依存キーワードとも言われる。実際のところ、goto
を go to
とも書けたり、elseif
相当を else if
という2語で1語扱いであったりと、文脈依存文法的なキーワードはさほど特殊でもなく、珍しいものでもない。
言語を後から拡張する場合、新しい構文やキーワードあるいは予約語を追加すると既存のコードとの互換性が壊れてしまう場合がある。例えば、既存の変数やメソッドの名前が新しいキーワードあるいは予約語と同じだった場合、新しい言語仕様では構文エラーとなる。しかし、完全に将来の拡張を予期してあらゆるキーワードを予約しておくことは困難であり、予約語が拡張の障害になりうる。
そこで、新しく拡張された構文の中でのみキーワードとして動作するのがコンテキストキーワードである。コンテキストキーワードは特定の構文以外では変数などの名前として使用できるため、既存のコードを破壊することがない。
例えば、C#のプロパティ構文では、C# 1.0の登場当初からget
、set
、value
という多くの名前に使われているであろう語をコンテキストキーワードとして定義している[18]。これは例えばC/C++やJavaのコードをC#に移植する際に、名前の衝突を避けるのに役立つ。C# 5.0で追加されたasync/await構文でも、コンテキストキーワードを利用して言語仕様が拡張されている。
コンテキストキーワードの問題点編集
- 文脈によってキーワードか否かが決まるので正規表現などでは判断しがたいこともあり、テキストエディタのシンタックスハイライトを正確に行うのが困難なこともある。しかし、パーサの設計次第ではあるが統合開発環境などでは言語処理系自体のパーサを利用するなどして構文解析を行って実現する、という手もある。
- パーサ(構文規則)が複雑になる場合もある。
- 他のスコープの変数やクラスメンバなどを使用する際に、新しい構文の中でも識別子として利用しないといけない場合があり、コンテキストキーワードだけでは回避できない(以下のC#によるコード例を参照)。
public class MyClass {
private string value; // value は setter でのみ使われるコンテキストキーワードなので、ここでは衝突しない。
public string Value {
get { return value; } // value は setter でのみ使われるコンテキストキーワードなので、ここでは衝突しない。
set { value = value; } // フィールド MyClass.value への代入ではなく、パラメータ value への自己代入となる。
//set { this.value = value; } // フィールドへの代入とするには、this による修飾が必要。
}
}
var obj = new MyClass();
obj.Value = "hoge";
System.Console.WriteLine("Value = \"{0}\"", obj.Value);
コンテキストキーワードの利点編集
- 前述の「問題点」は全て、レキシカルアナライザは厳密な正規表現(正規言語に限られた範囲の表現)によって先頭のトークンを切り出すことしかできず、パーサは厳密にLL(1)かLALR(1)の構文規則のみに従ってパースすることしかできない、という、聊か非現実的な前提の下では正しい。しかし実際の言語の処理系の実装では、レキシカルアナライザもパーザもアドホックに拡張されているのが普通である。コンテキストキーワードのようなものは一般に、何らかの指定されたキーワードの直後であるとか、記号の特殊な組み合わせといったような、アドホックな拡張によって容易に扱えるように設計されるのが通例であり、以上の問題点による実際の問題は小さい。
- 共通言語基盤 (CLI) のように、他の言語と共通のバックエンドやライブラリを使うためには、予約されている綴りを識別子として使うためのエスケープとともに、重要で必須な対応とも言える。
脚注編集
- ^ a b 予約語(reserved word)とは - IT用語辞典 e-Words
- ^ Collins, reserved words
- ^ Reserved word Definition & Meaning | Dictionary.com Dictionary.com, “a word in a programming language or computer system that has a fixed meaning and therefore cannot be redefined by a programmer”
- ^ Keywords - Visual Basic | Microsoft Docs
- ^ キーワード - Visual Basic | Microsoft Docs
- ^ @ - C# リファレンス | Microsoft Docs
- ^ 宣言された要素の名前 - Visual Basic | Microsoft Docs
- ^ シンボルと演算子のリファレンス - F# | Microsoft Docs
- ^ C のキーワード - cppreference.com
- ^ 識別子 - cppreference.com (C)
- ^ C reserved keywords - IBM Documentation
- ^ C++ のキーワード - cppreference.com
- ^ 識別子 - cppreference.com (C++)
- ^ [1]
- ^ これらはES5時点では予約語だったが、ES6で追加された新機能に使われることになり、キーワードに昇格した。
- ^ C++03ではテンプレートのエクスポート機能のために使われていたが、C++11ではその機能が廃止された。のちにC++20ではモジュール機能のために再利用されることになった。
- ^ 非推奨だったregisterキーワードを削除 - cpprefjp C++日本語リファレンス
- ^ C# Keywords | Microsoft Docs