<1> 記法: トークンと区切り文字 (標準 Pascal 範囲内での Delphi 入門)

# 1. 記法: トークンと区切り文字
Pascal は **トークン (記号)** と **区切り文字 (分離子)** で構成されます。トークン (Token) とは、プログラム内で意味を持つテキストの最小単位です。トークンには次のようなものがあります。

 - 特殊シンボル (特殊記号) 
 - 予約語 (綴り記号)
 - 識別子 (名前)
 - 数値 (数)
 - ラベル
 - 指令 (指図)

区切り文字 (Separators) は空白かコメント (注釈) です。

**See also:**

 - [トークン (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E6%A7%8B%E6%96%87%E8%A6%81%E7%B4%A0%EF%BC%88Delphi%EF%BC%89#.E3.83.88.E3.83.BC.E3.82.AF.E3.83.B3)

## 1.1. 区切り文字 (Token Separators)
空白、改行 (行分離子/行末) 及びコメント (注釈) は **区切り文字 (分離子/字句分離符)** です。Pascal のトークンの途中に区切り文字が存在するのはトークンが文字列である場合のみです。

### コメント (Comment)
標準 Pascal の **コメント (注釈)** は `{` で始まり `}` で終わる**ブロックコメント**だけですが、Delphi では `//` から始まる**行コメント**も使えます [^1]。

```pascal
{ これはコメントです }
// これはコメントです (Delphi)
```

Pascal の文法を理解してくると、**行コメントは Pascal という言語には異質な存在**と思えるようになってきます (多分)。

**See also:**

 - [コメントおよびコンパイラ指令 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E6%A7%8B%E6%96%87%E8%A6%81%E7%B4%A0%EF%BC%88Delphi%EF%BC%89#.E3.82.B3.E3.83.A1.E3.83.B3.E3.83.88.E3.81.8A.E3.82.88.E3.81.B3.E3.82.B3.E3.83.B3.E3.83.91.E3.82.A4.E3.83.A9.E6.8C.87.E4.BB.A4)

## 1.2. 特殊シンボルと予約語

#### 特殊シンボル (Special-symbols)
標準 Pascal の**特殊シンボル (特殊記号)** は次の通りです。

`# ' ( ) * + , - . / : ; < = > [ ] ↑ { }`

Delphi の特殊シンボルは次の通りです。

`# $ & ' ( ) * + , - . / : ; < = > @ [ ] ^ { }`

オリジナルの Pascal が動作したコンピュータ ([CDC 6000](https://en.wikipedia.org/wiki/CDC_6000_series)) には `↑` という文字がありました。他の処理系では `@` または `^` で置き換えることが可能でした。以下の表は CDC の科学用 64 文字集合です。

|   |0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|  **0** | : | A | B | C | D | E | F | G | H | I |
| **10** | J | K | L | M | N | O | P | Q | R | S |
| **20** | T | U | V | W | X | Y | Z | 0 | 1 | 2 |
| **30** | 3 | 4 | 5 | 6 | 7 | 8 | 9 | + | - | * |
| **40** | / | ( | ) | $ | = |   | , | . | &#x2261; | [ |
| **50** | ] | % | ≠ | &#x21B1; [^2] | ∨ | ∧ | ↑ | ↓  [^3] | < | > |
| **60** | &#x2264; | &#x2265;  | ￢  | ; |   |   |   |   |   |   |

標準 Pascal では `「↑ と ^ は同じ文字を表しているけど、視認性が高いので (文章中では) ↑ を使うね」` という事になっています。また、Delphi では `@` は演算子なので `^` の代わりに `@` を使う事はできません。

特殊シンボルの一部は **ダイグラフ（2 文字表記）** で表す事ができます。

| 文字<br>(基準表現) | ダイグラフ<br>(代替表現) |
|:---:|:---:|
|{|(*|
|}|*)|
|[|(.|
|]|.)|

つまり、ブロックコメント `{` `}` は `(*` `*)` として書くこともできます。 `{` `}` や  `[` `]` キー (または文字) のないコンピュータでもダイグラフを使って文字を表現する事が可能になります。

文字代替における基準となる文字を **基準表現 (Reference Token)**、それを代替する文字を **代替表現 (Alternative Token)** と言います。

標準 Pascal ではダイグラフが機能するため、ブロックコメントを次のように書く事ができます。左ブラケットと右ブラケットが異なりますが、これで対になっています。

```pascal
  { Comment *)
```

Delphi のブロックコメントでは異なる種類のブラケットを混在させる事はできません。しかし、別種類のブロックコメントを組み合わせる事により、ブロックコメントのネストを行う事ができます。

```pascal
{
  (* TEST *)
  A := 1;
}
```

上記コードは標準 Pascal だと次のように解釈されてエラーになります。

```pascal
  A := 1;
}
```

#### 予約語 (Word-symbol / Reserved-word)

標準 Pascal の **予約語 (綴り記号)** は次の通りです。

```
and       end       nil       set    
array     file      not       then
begin     for       of        to
case      function  or        type
const     goto      packed    until
div       if        procedure var
do        in        program   while  
downto    label     record    with      
else      mod       repeat    
```

Delphi (12.0 Athens 時点) の予約語は次の通りです。

```
and                 except              label               set    
array               exports             library             shl
as                  file                mod                 shr
asm                 finalization        nil                 string
begin               finally             not                 then
case                for                 object              threadvar
class               function            of                  to
const               goto                or                  try
constructor         if                  packed              type
destructor          implementation      procedure           unit
dispinterface       in                  program             until
div                 inherited           property            uses
do                  initialization      raise               var
downto              inline              record              while  
else                interface           repeat              with        
end                 is                  resourcestring      xor
```

※ **at** および **on** という単語も予約語として扱う必要があります。

**See also:**

 - [特殊シンボル (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E6%A7%8B%E6%96%87%E8%A6%81%E7%B4%A0%EF%BC%88Delphi%EF%BC%89#.E7.89.B9.E6.AE.8A.E3.82.B7.E3.83.B3.E3.83.9C.E3.83.AB)
 - [ダイグラフ (Wikipedia)](https://ja.wikipedia.org/wiki/%E3%83%80%E3%82%A4%E3%82%B0%E3%83%A9%E3%83%95)
 - [C++Builder とトライグラフ (Qiita)](https://qiita.com/ht_deko/items/36115af8a57636257445)
 - [予約語 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E6%A7%8B%E6%96%87%E8%A6%81%E7%B4%A0%EF%BC%88Delphi%EF%BC%89#.E4.BA.88.E7.B4.84.E8.AA.9E)
 - [CDC display code (Wikipedia: en)](https://en.wikipedia.org/wiki/CDC_display_code)

## 1.3. 識別子 (Identifiers)
**識別子 (名前)** は、定数、変数、フィールド、型、プロパティ、手続き、関数、プログラム、ユニット、ライブラリ、およびパッケージを表します。

標準 Pascal では識別子は英字で始まる英数字の組み合わせです。Delphi の場合、識別子にアンダーバー(_) が使え、**Unicode 版 Delphi** (Delphi 2009 以降) であればUnicode 文字も使えます。

Delphi の場合、識別子の長さに制限はありませんが、有効なのは最初の 255 文字だけです。標準 Pascal は実装依存ですが、最初の 8 文字しか有効でないものもあるようです。

**Pascal は識別子の大文字と小文字を区別しない**ため `HOGE` と `hoge` と `Hoge` は同じものとして扱われます。

予約語と同じ識別子を使う事はできませんが、Delphi では `&` 記号を使う事によって、そのキーワードを予約語として解釈しないようにする事ができます [^4]。例えば `&and` とすると予約語として解釈しないため、変数名として使えるようになります。

**See also:**

 - [識別子 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E6%A7%8B%E6%96%87%E8%A6%81%E7%B4%A0%EF%BC%88Delphi%EF%BC%89#.E8.AD.98.E5.88.A5.E5.AD.90)

## 1.4. 数値 (Numbers)
整数および実数を表す **数値 (数)** は 10 進表示を用います。数値の先頭には符号 (`+` または `-`) を付ける事ができます。

```
123    -100    +0001
```

実数は小数点や指数、あるいはその両方を使って記述します。次の記述はいずれも実数です。

```
-0.1    5e-3    87.35E+8
```

Delphi の場合、先頭に `$` の付いたものは 16 進値です。例えば `$0A` は 10 進値で `10` となります。

```
$0A    $007F    $DEADBEEF    
```

先頭に `%` の付いたものは 2 進値です [^5]。例えば `%100` は 10 進値で `4` となります。

```
%100    %1001001    %1000_1100_1001_0011    
```
 
2 / 10 / 16 進数いずれの数値表現においても任意の位置で桁区切り文字 `_` を挿入する事が可能となっています [^5]。

## 1.5. 文字列 (Character-strings)
**文字列** は **文字列リテラル** や **文字列定数** とも呼ばれるもので、引用符付き文字列として表現されます。引用符付き文字列は文字列をアポストロフィ (or シングルクォーテーション or 単一引用符) で囲み、単一行に記述します。引用符付き文字列内でアポストロフィを表したい場合にはアポストロフィを二つ並べます。

```pascal
  'a'    ';'    '3'    'begin'    'don''t'
```

文字列リテラルの要素数には制限があります。要素数の制限を超える文字列リテラルは `+` 演算子で連結して表現する必要があります。

```pascal
  'Hello,' + 'world.'
```

| バージョン | 要素数 |
|:---|:---|
| Delphi 11 以前 | 255 文字 |
| Delphi 12 以降  | 一行あたり 4K 文字<br>(エディタの制限) |

また、三重引用符を用いた複数行文字列も利用可能です [^6]。

```pascal
const
  MULTILINE_STR = '''
  AAA
  BBB
  CCC
  ''';
```

```
AAA
BBB
CCC
```

文字列のインデント位置は終了 (閉じる) 三重引用符の位置です。次の例では各行の先頭にスペースが 2 つ入ります。

```pascal
const
  MULTILINE_STR = '''
    AAA
    BBB
    CCC
  ''';
```

```
  AAA
  BBB
  CCC
```

次のようなインデント位置はエラーとなります。

```pascal
const
    MULTILINE_STR = '''
  AAA
  BBB
  CCC
    ''';
```

三重引用符以上の**奇数引用符も三重引用符と同じように動作します**。例えば五重引用符を使うと、文字列中で三重引用符を扱う事ができます。

```pascal
const
  MULTILINE_STR = '''''
    AAA
    '''BBB'''
    CCC
    ''''';
```

:::note
複数行文字列の改行をどう処理するかは `{$TEXTBLOCK}` 指令で指定できます。
:::


### (1.5.1.) 制御文字列
Delphi の場合 `#数値` として、文字として表現できない文字を **制御文字** で記述する事ができます。例えば 

```pascal
#13#10
``` 

は [CR][LF] の改行コードとなります。制御文字は 16 進表記も可能で、

```pascal
#$0D#$0A
```

と記述する事もできます。

### (1.5.2.) キャレット記法 (Caret notation)
Delphi の場合、**キャレット記法**を使い、ASCII コードの制御文字を表す事ができます。キャレット記法とは `^(キャレット)` と英数記号の組み合わせによる記法です。

次の改行コード (制御文字) を含む文字列は

```pascal
'Hello'#$0D#$0A'world'
```

次のように書き換える事ができます。

```pascal
'Hello'^M^J'world'
```

**See also:**

 - [ASCII - 制御文字 (Wikipedia)](https://ja.wikipedia.org/wiki/%E5%88%B6%E5%BE%A1%E6%96%87%E5%AD%97#ASCII)
 - [キャレット記法 (Wikipedia)](https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%A3%E3%83%AC%E3%83%83%E3%83%88%E8%A8%98%E6%B3%95)

## 1.6. ラベル (Labels)
標準 Pascal における**ラベル**は、文に印を付けるための符号なし整数です。0～9999 の値が使えます。

Delphi における**ラベル**は[識別子](#13-%E8%AD%98%E5%88%A5%E5%AD%90-%E5%90%8D%E5%89%8D)または符号なし整数です。符号なし整数として 0～4294967295 の値が使えます。

ラベルは [goto 文](https://qiita.com/ht_deko/items/05af01a81f7c3bb5eeb4#47-goto-%E6%96%87) で使用します。

## 1.7. 指令 (Directives)

**指令 (指図)** はソースコード内の特定の位置で区別される単語です。特定の位置でのみ予約語のように振る舞います。予約語ではないため、同じ名前の識別子を作る事も可能です (もちろん非推奨)。

標準 Pascal の指令は **forward** だけです ([11.3 節](https://qiita.com/ht_deko/items/b93ac03bfee002f17137#113-%E5%89%8D%E6%96%B9%E5%AE%A3%E8%A8%80-forward-declaration))。

```pascal
forward
```

先述の通り、指令と同じ名前の識別子を作る事が可能です。

```pascal
program FWTEST(Output);

  procedure Forward(v: Integer); forward;

  procedure Test(v: Integer);
  begin
    Forward(v + 1);
  end; { Test }

  procedure Forward;
  begin
    Writeln(v);
  end; { Forward }

begin
  Test(1);
end.
```

Delphi (12.0 Athens 時点) の指令は次の通りです。

```
absolute            final               override            safecal
abstract            forward             package             sealed
assembler           helper              pascal              static
automated           implements          platform            stdcall
cdecl               index               private             stored
contains            inline              protected           strict
default             library             public              unsafe
delayed             local               published           varargs
deprecated          message             read                virtual
dispid              name                readonly            winapi
dynamic             near                reference           write
experimental        nodefault           register            writeonly
export              operator            reintroduce         
external            out                 requires
far                 overload            resident
```

**See also:**

 - [指令 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E6%A7%8B%E6%96%87%E8%A6%81%E7%B4%A0%EF%BC%88Delphi%EF%BC%89#.E6.8C.87.E4.BB.A4)

### (1.7.1.) ヒント指令 (Hint directives)

Delphi には以下の**ヒント指令**があり、型宣言、変数宣言、クラス、インターフェイス、構造体の宣言、クラスまたはレコード内のフィールド宣言、手続き、関数、メソッドの宣言、およびユニット宣言に適用できます。

```
platform           deprecated           library
```

| ヒント指令 &nbsp; &nbsp; &nbsp; | 説明 |
|:---:|:---|
| **platform** | シンボルまたはユニットに対する platform ヒント<br>指令は、そのシンボルまたはユニットが存在<br>しない可能性があること、<br>またはプラットフォームによって実装方法が<br>かなり異なる可能性があることを示します。|
| **deprecated**  | deprecated 指令は、使われなくなった項目、<br>つまり下位互換性のためにのみサポートされて<br>いる項目を示します。 |
| **library**   |  シンボルまたはユニットに対する library ヒント<br>指令は、コードが存在しない可能性があること、<br>またはライブラリのアーキテクチャによって<br>実装方法がかなり異なる可能性があることを<br>示します。  |

**See also:**

 - [ヒント指令 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%AE%A3%E8%A8%80%E3%81%A8%E6%96%87%EF%BC%88Delphi%EF%BC%89#.E3.83.92.E3.83.B3.E3.83.88.E6.8C.87.E4.BB.A4)

### (1.7.2.) コンパイラ指令 (Compiler directives)
コンパイルオプションです。

**クラシック Pascal** である **Pascal 6000** にも**コンパイラ指令**はありましたが、標準 Pascal では定義されていません。コンパイラ指令はブロックコメントとして書き、コメントブロックの先頭に $ を付けて記述します。

```pascal
{$T+, P+}
```

:::note
Delphi でもコンパイラ指令をカンマで区切って複数並べる事が可能ですが、短い名前のコンパイラ指令に限られ、コンパイラ指令間にスペースを入れる事はできません。
:::

**See also:**

 - [コンパイラ指令 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/Delphi_%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E6%8C%87%E4%BB%A4)


### (1.7.3.) 呼び出し規約に関連する指令

呼び出し規約に関わる指令は次の通りです。

```
cdecl pascal register safecall stdcall winapi
```

呼び出し規約については別記事にまとめています。

 - [Delphi と Windows の呼び出し規約 (Qiita)](https://qiita.com/ht_deko/items/840c96166b8f175826ef)

## (1.8.) 属性 (Attributes)

属性は、追加情報を備えた特殊なオブジェクトによる型および型メンバの注釈付けを可能にする Delphi の言語機能です。

 - [属性と RTTI (DocWiki)](https://docwiki.embarcadero.com/RADStudio/ja/%E5%B1%9E%E6%80%A7%E3%81%AE%E6%A6%82%E8%A6%81)
 - [カスタム属性の宣言 (DocWiki)](https://docwiki.embarcadero.com/RADStudio/ja/%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E5%B1%9E%E6%80%A7%E3%81%AE%E5%AE%A3%E8%A8%80)
 - [型および型メンバの注釈付け (DocWiki)](https://docwiki.embarcadero.com/RADStudio/ja/%E5%9E%8B%E3%81%8A%E3%82%88%E3%81%B3%E5%9E%8B%E3%83%A1%E3%83%B3%E3%83%90%E3%81%AE%E6%B3%A8%E9%87%88%E4%BB%98%E3%81%91)
 - [属性の実行時抽出 (DocWiki)](https://docwiki.embarcadero.com/RADStudio/ja/%E5%B1%9E%E6%80%A7%E3%81%AE%E5%AE%9F%E8%A1%8C%E6%99%82%E6%8A%BD%E5%87%BA)

### (1.8.1.) コンパイラ属性 (Compiler Attributes)

対象を限定したコンパイラ指令のようなものです [^7]。

 - [コンパイラ属性 (DocWiki)](https://docwiki.embarcadero.com/RADStudio/ja/%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E5%B1%9E%E6%80%A7)
 - [Delphi モバイル コンパイラでの自動参照カウント (DocWiki: 10.3 Rio)](https://docwiki.embarcadero.com/RADStudio/Rio/ja/Delphi_%E3%83%A2%E3%83%90%E3%82%A4%E3%83%AB_%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E3%81%A7%E3%81%AE%E8%87%AA%E5%8B%95%E5%8F%82%E7%85%A7%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88)

#### (1.8.1.1.) [Ref] コンパイラ属性

定数パラメータ (**const**) を強制的に参照渡しさせます。

 - [Ref 属性 - 定数パラメ－タ (DocWiki)](https://docwiki.embarcadero.com/RADStudio/ja/%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%EF%BC%88Delphi%EF%BC%89#.E5.AE.9A.E6.95.B0.E3.83.91.E3.83.A9.E3.83.A1.E3.83.BC.E3.82.BF)
 - [11.1.1. パラメータリスト (パラメータ並び / Parameter list)](https://qiita.com/ht_deko/items/b93ac03bfee002f17137#1111-%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%83%AA%E3%82%B9%E3%83%88-%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E4%B8%A6%E3%81%B3--parameter-list)

#### (1.8.1.2.) [Unsafe] コンパイラ属性

参照カウントに関連するコードを生成しないようにします。変数（メンバ）、関数の結果、関数や手続きのパラメータに指定できます。

 - [Unsafe 属性 (DocWiki)](https://docwiki.embarcadero.com/RADStudio/ja/%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E5%B1%9E%E6%80%A7#Unsafe)

関数の結果に \[Unsafe\] 属性を付けるには次のようにします。

```pascal
[Result: Unsafe] function ReturnUnsafe: TObject;
```

:::note
Delphi 10.1 Berlin 以降で、すべてのプラットフォームで利用可能になりましたが、10.4 Sydney で ARC が廃止されたため、現在ではインターフェイス参照のためだけに利用されます。
:::
 
#### (1.8.1.3.) [Volatile] コンパイラ属性

最適化による変数の破棄を防ぎます。C++ の volatile と同等です。変数、関数や手続きのパラメータ、レコード、クラスに対して指定できます。

 - [Volatile 属性 (DocWiki)](https://docwiki.embarcadero.com/RADStudio/ja/%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E5%B1%9E%E6%80%A7#volatile)
 - [Volatile (C++) (DocWiki)](https://docwiki.embarcadero.com/RADStudio/ja/Volatile)

簡単な例を挙げてみます。次のコードをコンパイルすると変数 i は使われていないためヒント (H2164) が出ます。

```pascal
procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  
end;
```

\[Volatile\] 属性を付けるとヒントが出なくなります。

```pascal
procedure TForm1.Button1Click(Sender: TObject);
var
  [Volatile] i: Integer;
begin
  
end;
```





#### (1.8.1.4.) [Weak] コンパイラ属性

 - [Weak 属性 (DocWiki)](https://docwiki.embarcadero.com/RADStudio/ja/%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E5%B1%9E%E6%80%A7#Weak)
 - [弱い参照 (DocWiki: 10.3 Rio)](https://docwiki.embarcadero.com/RADStudio/Rio/ja/Delphi_%E3%83%A2%E3%83%90%E3%82%A4%E3%83%AB_%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E3%81%A7%E3%81%AE%E8%87%AA%E5%8B%95%E5%8F%82%E7%85%A7%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88#.E5.BC.B1.E3.81.84.E5.8F.82.E7.85.A7)

:::note
Delphi 10.1 Berlin 以降で、すべてのプラットフォームで利用可能になりましたが、10.4 Sydney で ARC が廃止されたため、現在ではインターフェイス参照のためだけに利用されます。
:::

# 索引
[ [← 0. はじめに](https://qiita.com/ht_deko/items/afb3c008a83a20792169) ] [ [↑ 目次へ](https://qiita.com/ht_deko/items/e2796788c65c2cda1de5) ] [ [→ 2. データの概念: 単純データ型](https://qiita.com/ht_deko/items/5c04bb2b42947e29d94b) ] [:sushi:](https://qiita.com/ht_deko/items/bb5d4eaf532e8c217cdb)

[^1]: Delphi 2 以降で行コメントが使えます。
[^2]: ETH では `{` が使われていました。
[^3]: ETH では `}` が使われていました。
[^4]: Delphi 2005 以降で使えます。
[^5]: 11.0 Alexandria 以降で使えます。
[^6]: 12.0 Athens 以降で使えます。
[^7]: 10.1 Berlin から、すべてのプラットフォームで使えるようになりました。