KLの文法¶
KLが開発された当初、可能な限り JavaScriptのシンタックスを模倣するよう設計しました。JavaScript自体は C-like language をシンタックスはともかく参照しています。この節ではKLの文法を詳細に掘り下げます。C言語に親しんでいない場合、レファレンスとなることでしょう。一方、もし既に JavaScript and/or C言語 に詳しいのであれば、この節はスキップし、ガイドの続きへ進むことをお薦めします。
Cライクな言語の特徴:
- プログラムは人間可読なプレーンテキストです。
- プログラムは一連の tokens から成ります。トークンには4つの構成要素があります。 キーワード(keywords) 、識別子(identifiers), シンボル(symbols)、定数(constants)
- トークンは任意の個数のホワイトスペースで区切ります。2つの隣接するトークン同士は、それぞれ個別に見えるようにスペースで分割しなければなりません。「ホワイトスペースによる」とは スペース(ASCII 32)、改行 n(ASCII 10)、タブ(ASCII 9)、キャリッジ・リターン r(ASCII 13)、ヴァーティカルタブ(ASCII 11)を意味します。
- プログラムにはどこにでもコメントを付することができます。コメントはコンピュータでの処理の際、ホワイトスペースと同じように扱われます。2つのコメント方法があります。 ブロックコメント、
/*
で始まり次ので終わり*/
。そして行コメント//
で始まり次の改行コード(n ASCII 10)まで続きます。 - ブロックは
{
と}
により分割されます。 - 文(statement)は
;
で終端です。
次にKLシンタックスの詳細を掘り下げます。
エンコーディング¶
KLプログラムは人間可読なプレインテキストですが、KLではテキストファイルのエンコーディングを UTF-8 に限ります。KLコンパイラは全てのソースコードを エンコーディングマーク無しの UTF-8とみなします。KLプログラムではコードに不正なUTF-8シーケンスが含まれていると、コンパイルできずシンタックスエラーが返ります。
これの意味するところがわからないのであっても、C言語でのソースコード(あるいはJavaScript)がそうであるようにプレイン7ビットASCIIテキストであれば、UTF-8ディフォルトエンコードです。1つ注意すべき点があり、Windowsで “Unicode format” として保存 (実際には UCS-2 としてエンコードされる) されたテキストファイルは、KLコンパイラでは読み込めません。アルファベット以外の外国語をKLソースコードに混入させるときには、エディタの設定で UTF-8 を必ず使いましょう。
エンコードを特定することの利点は、外国語で使用される高ビットの文字を、KLソースファイル中に文字列定数として直接挿入できることです。
行の連続性¶
C言語同様、KLプログラム中のバックスラッシュ文字 \
で終わる行は、その次の行と連結されます。単独トークンを分割するときなど、長くなってしまう行を複数の行に分割でき便利です。たとえば長い文字列などのトークンです。
このサンプルではKLソース・ファイル中での文字列連結使用例です。
/*
** Example: Line Continuations
*/
operator entry() {
report("\
This is a really, really long string \
that spans multiple lines.\n\
Note that \
<-- the SPACES at the beginning \
of the next line are preserved!");
}
/*
** Output:
This is a really, really long string that spans multiple lines.
Note that <-- the SPACES at the beginning of the next line are preserved!
*/
コメント¶
KLはC言語やJavaScriptと同じ2つのコメント法をサポートします。ブロックコメントと行コメントです。
ブロックコメント¶
ブロックコメントは、任意の、 /*
ではじまる次ので終わる */
連続した文字の連なりにより構成されます。C言語同様、KLのブロックコメントは */
がきたら即コメント終端とみなします。また同様にネストしたブロックコメントを認識しません。
KLで受け付ける例:
/* A simple, one-line block comment */
/* This is
a multi-line
block comment
*/
/*
** And so is this
*/
operator entry() {
/* comments can appear in source code */
report("Hello!"); /* pretty much anywhere */
foo( 32 /*, 53*/ ); /* block comments are a simple way to temporarily remove code */
}
KLでは無効な例:
/* KL ends the comment
* as soon as the first */
* is seen, so this is
* a bad block comment that
* results in a syntax error
*/
/* Like C, block comments
* cannot nest in KL,
/* so this is also
* a bad comment that
* will result in a
* syntax error
*/
*/
ブロックコメントを使用する際の注意点:プログラム中、以上のエラーが発生すると問題の原因解明が非常に困難になります。このため行コメントの使用をお薦めします。
行コメント¶
行コメントは、 //
で始まり行の終端、つまり改行コード(ASCII character 10)まで続く文字の連なりです。ブロックコメントと違い、行コメントでは「落とし穴」はありません。期待通りに動作することでしょう。ただ行の途中で、コードのセクションをコメントアウトすることはできません
KLでの行コメントの例:
// A simple, one-line line comment
// This is
// a multi-line
// line comment
operator entry() {
// comment can appear in source code
report("Hello!"); // pretty much anywhere
foo( 32 //, 53 ); // can't comment out code in the middle of the line
); // but you can continue it on the next line.
}
トークン¶
KLプログラムはトークンの連なりとして パース されます。トークンとは、コメントや、ホワイトスペースではない何らかの文字の連なりです。トークンには以下の4つのカテゴリがあります。キーワード(keywords), 識別子(identifiers), シンボル(symbols)定数(constants)
キーワード¶
KLでの全キーワードのリスト:
|
|
|
キーワードは識別子として使用することはできません。すなわち、以下の名前に使用することはできません。変数、パラメータ、関数、定数、型の名前です。
識別子¶
Identifiers とは、文字1つかそれ以上の連なりから成ります:
a...z
,A...Z
,_
などの文字から始まり、- 次の文字0個以上つづきます。
a...z
,A...Z
,0...9
or_
識別子は、KLでの変数の名前、パラメータの名前、関数の名前、定数の名前、メソッドの名前、型の名前に使用します。
注釈
KLでの組み込み型(例:Boolean
, String
, Float32
)はキーワードではなく、識別子です。このことは言語設計の技術的詳細として重要ではありますが、実際にはあまり違いはありません。違いといえばシンタックスエラーのかわりにセマンティクスエラーがでる程度です。正常な識別子の例:
foo
someVariable
MyType
MyTypeVersion2
variable_with_underscores
piBy2
_
だめな識別子の例:
2by4
my%Share
シンボル¶
KLにおける symbols とは、英数字以外の、アンダースコアを含まない文字(もしくはそれらの短いセット)です。具体的には:
|
|
|
|
|
|
KLコンパイラは、シンボル走査に “貪欲” です。文字の最長シーケンスを有効なシンボルとして解釈します。 ==(
が ==
と (
の2つのシンボルとして扱われる理由です。==(
ではじまるシンボルは存在せず、 ==
ではじまるシンボルは存在します。
定数¶
定数とは、特定の型の固定された値として解釈されるトークンです。KLでは5つの型の定数をサポートします:真偽値(boolean), 整数(integer), 浮動小数点数(floating-point), 文字列(string) です。それぞれいかに説明します。
真偽値定数¶
true
と false
の2つのキーワードが2つの boolean constants です。どちらも Boolean
型の値です。
/*
** Example: Boolean Constants
*/
operator entry() {
Float32 value = 1.1;
Index steps = 0;
Boolean done = false;
while (!done) {
value *= value;
if (value > 2)
done = true;
++steps;
}
report("took " + steps + " steps");
}
/*
** Output:
took 3 steps
*/
整数定数¶
integer constant の3つの形態:
- 一桁の
0
1...9
の一桁から始まり、ゼロ桁以上の0...9
が続く10進定数0x
もしくは0X
とそれに1つ以上の0...9
,a...f
andA...F
の文字が続く16進定数
どの形態であれ、整数定数では必要に応じ整数型の型の指定を行えます。整数型の指定では、符号(signededness)の可否、ビット長の指定、どの形態かについて指定します。
s
(signed) もしくはu
(unsigned)に続けて、- (任意)
8
,16
,32
or64
(ビット幅)
ビット幅を指定しない場合、整数のビット幅は 32-bit です。なので、 145u
は unsigned 32-bit 整数定数で 78s
は signed 32-bit 整数定数を意味します。
型の指定がない場合、整数は signed 32-bitになります。なので 5421
は signed 32-bit 整数定数です。
/*
** Example: Integer Constants
*/
operator entry() {
report(0); // SInt32
report(1); // SInt32
report(123456789u); // UInt64
report(0xA9); // SInt32
report(0xdeadBEEFu); // UInt32
report(123456789012345678u64); // UInt64
}
/*
** Output:
0
1
123456789
169
3735928559
123456789012345678
*/
浮動小数点数定数¶
KLの floating-point constant は Float32
と Float64
の2つの型があります。シンタックスは C/C++ に非常に近く Float32
は C での float
を意味し Float64
は C での double
型:
1.2
はFloat64
型1.2f
はFloat32
型.7
はFloat64
型3.4e7
や3.4e+7
はFloat64
型3.4e7f
や3.4e+7f
はFloat32
型.5e-4f
はFloat32
型
KLは C/C++ のシンタックスをさらに拡張し、f32
and f64
を接尾語として使うことでより明示的な型の指定を可能にします。例:
4.5e-6f32
は4.5e-6f
と同じ2.874f64
は2.873
同じ
f
, f32
も f64
も接尾語に使われていない場合、浮動小数点数定数は untyped floating-point constant になります。untyped floating-point 定数は自動的にその周囲の式の型を継承します。 例えば, 浮動小数点数定数 .5
が Float32
型の変数に加算されるとその定数は Float32
であるとして扱われます。
/*
** Example: Floating-Point Constants
*/
operator entry() {
// Float32
report(0.f);
report(0.0f);
report(.0f);
report(0.5f);
report(.5f);
report(-5.6e7f);
report(.75e-10f);
report(3.4e14f32);
report(7.89f32);
report(.67f32);
report(.12e20f32);
// Float64
report(0.);
report(0.0);
report(.0);
report(0.5);
report(.5);
report(-5.6e7);
report(.75e-45);
report(5.4f64);
report(.78f64);
report(7.532453e-120f64);
report(.754e45f64);
}
/*
** Output:
+0.0
+0.0
+0.0
+0.5
+0.5
-5.6e7
+0.75e-10
+3.4e14
+7.89
+0.67
+1.199999e19
+0.0
+0.0
+0.0
+0.5
+0.5
-56000000.0
+0.75e-45
+5.4
+0.78
+0.7532453e-119
+0.754e45
*/
注釈
IEEE浮動小数点形式では、ほとんどの少数や分数の式を表現することはできません。ですのでそのような式で出力された値が、多少ずれているように見えたとしても驚いてはいけません。上記の例では定数.12e20f32
など。文字列定数¶
string constant とは String
型の定数値です。とりうる2つの形態:
- 文字の連なり。 2つの
"
(ダブルクォート)文字で囲われた、文字列定数のエスケープシーケンス(後述)を含む - 文字の連なり。2つの
'
(シングルクォート)文字で囲われた、文字列定数のエスケープシーケンス(後述)を含む
string constant escape sequence とは以下の、文字列に置き換えられる文字の連なりです。
\n
- 単一の改行文字(ASCII 10)
\f
- 単一フォームフィード(ASCII12)文字
\r
- 単一のキャリッジリターン(ASCII 13)文字
\t
- 単一のキャリッジタブ(ASCII9)文字
\v
- 単一の垂直タブ(ASCII11)文字
\a
- 単一のベル(ASCII7)文字
\b
- 単一のバックスペース(ASCII8)文字
\0
- 単一のヌル(ASCII0)文字
\"
- 単一の二重引用符(ASCII34)文字
\'
- 単一のシングルクォート(ASCII39)文字
\\
- 単一のバックスラッシュ(ASCII92)文字
\xHH
- 単一の文字、ASCIIコード16進数で指定。2つの文字
HH
はともに16進文字です。(すなわち0...9
,a...f
,A...F
)。例:0x0A
(十進数の10) はエスケープシーケンスの\n
(ASCII 10) に等しくなります。
/*
** Example: String Constants
*/
operator entry() {
report("double-quoted!");
report('single-quoted\nwith a newline');
report("double-quoted containing \"double quotes\"");
}
/*
** Output:
double-quoted!
single-quoted
with a newline
double-quoted containing "double quotes"
*/
FILE
、 LINE
定数¶
この2つのキーワード FILE
と LINE
はKLプログラム中、特別な定数です。 FILE
はコンパイルされている現在のファイルのファイル名と同一な文字列定数に置換されます。 FILE
は同様に、現在のファイル中での行番号と同一な整数定数日感されます。例えば、以下のKLソースコードが標準入力から渡されると:
/*
** Example: FILE and LINE
*/
operator entry() {
report(FILE + ":" + LINE);
}
/*
** Output:
(stdin):7
*/
プログラム構造¶
KLプログラムはそのシーケンス中にゼロ個以上の global declarations から成ります。グローバル宣言は次のいずれかです:
- 関数 関数の宣言、関数プロトタイプの宣言、オペレータの宣言、コンストラクタの宣言、デストラクタの宣言、メソッドの宣言、演算子オーバーロードの宣言
- 構造体(Structures), オブジェクト(Objects) : 構造体の宣言、オブジェクトの宣言
- 名前付き定数 :グローバル定数の宣言
- require による機能のインポート :
require
文
関数、オペレータ、他同様は、ゼロ以上の statements を構成します。どの文も ;
(セミコロン)で終わります。KLで利用可能な文に関する詳しい情報は 文(Statements) を参照してください。
中括弧({
と }
)で囲まれた複数の文の連なりは、単文の場をとることができます。これによりネストされたスコープを導入できます。より詳しい情報は Compound Statement Scope を参照してください。