<0> はじめに (標準 Pascal 範囲内での Delphi 入門)

# 0. はじめに

Delphi で本記事のコードを試すにはコンソールアプリケーションを作成します。

`[ファイル | 新規作成 | その他...]` から

![image.png](https://qiita-image-store.s3.amazonaws.com/0/21785/1a7a0686-03bc-6270-e6a7-946956bf49c1.png)

`コンソールアプリケーション` を選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/21785/4e221e49-8817-ee0a-682f-96bc6964c43c.png)

新規作成時のソースコードは以下の通りですが、

```pascal
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

begin
  try
    { TODO -oUser -cConsole メイン : ここにコードを記述してください }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
```

すべてを消してプログラムを試す事ができます。以下のコードに書き換えて `[実行 | 実行]` を選ぶか〔F9〕キーを押すと、

```pascal
program Hello(Output);
begin
  Writeln('Hello, world.');
end.
```
コンソールが開いて `Hello, world.` が表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/21785/3729c80d-dcb9-206a-cb00-451f61491ae9.png)

コンソールがすぐに閉じて実行結果が見えない場合には、

```pascal
program Hello(Output);
begin
  Writeln('Hello, world.');
  Readln; // <-- 追加
end.
```

最後に `Readln;` の行を追加しましょう。

章や節が ( ) で囲まれているものは、**オリジナルの J&W には存在しない章や節**ですので、読み飛ばしても問題はありません。後で読み返すと Delphi に対する理解が深まると思います。

記事中には Delphi では検証できない **標準 Pascal 用に書かれたコード** もあるのですが、そのようなコードは **PASCAL-P5** を使って検証する事が可能です。

**See also:**

 - [割と簡単に ’標準 Pascal' を試してみたい (Qiita)](https://qiita.com/ht_deko/items/41e95154e8da2f901698)


## 0.1. Pascal プログラムの概要

Pascal のプログラムはプログラムヘッダとブロックによって構成されています。

```
プログラム = 
  プログラムヘッダ (program)
  ブロック.

ブロック = 
  [ラベル宣言部 (label)]
  [定数定義部 (const)]
  [型定義部 (type)]
  [変数宣言部 (var)]
  [手続き・関数宣言部 (procedure / function)]
  実行部 (begin～end).
```

Delphi にはソース分割のための **uses** 句があるため、

```
プログラム = 
  [プログラムヘッダ (program)]
  プログラムブロック.

プログラムブロック =
  [uses 句]
  ブロック.

ブロック = 
  [ラベル宣言部 (label)]
  [定数定義部 (const)]
  [型定義部 (type)]
  [変数宣言部 (var)]
  [手続き・関数宣言部 (procedure / function)]
  実行部 (begin～end).
```

となります。**uses** 句は省略可能です。

ブロックは 6 つの**節**で構成されていて、実行部以外の節は省略可能なため、最少のソースコードは以下のようになります。

```pascal:test.pas
program test;
begin
end.
```
標準 Pascal では節の順番が決められており、

```pascal:test2.pas
program test2;
const
  A = 1;
var
  B: Integer;
begin
end.
```
**const** (定数定義部) と **var** (変数宣言部) を入れ替えるとコンパイルが通らなくなります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/21785/fd754f63-16b1-4b79-04ff-bdc3c06ad03d.png)

Delphi では実行部以外なら節を入れ替えても大丈夫ですし、

```pascal:test3.pas
var
  A: Integer;
var
  B: Integer;
begin
end.
```

同じ節を何度入れても大丈夫です。

**See also:**

 - [プログラムとユニット（Delphi）(DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%A8%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%EF%BC%88Delphi%EF%BC%89)
 - [program ヘッダー (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%A8%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%EF%BC%88Delphi%EF%BC%89#program_.E3.83.98.E3.83.83.E3.83.80.E3.83.BC)
 - [ブロック (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%A8%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%EF%BC%88Delphi%EF%BC%89#.E3.83.96.E3.83.AD.E3.83.83.E3.82.AF)


### (0.1.1.) unit と uses
次の例ではユニット Sub で定義された関数 `Foo()` を Main プログラムから呼び出しています。

```pascal:Main.dpr
program Main; 
              
uses          
  Sub;        
              
var           
  v: Integer; 
begin         
  v := Foo(5);
  Writeln(v); 
end.                        
```

```pascal:Sub.pas
unit Sub;

interface

function Foo(n: Integer): Integer;

implementation

function Foo(n: Integer): Integer;
begin
  result := n * 10;
end;
end.                     
```

Delphi では **program** のある主ファイル (Delphi Project File) の拡張子は `*.dpr`、**unit** のある副ファイル (Unit File) の拡張子は `*.pas` となります。

ユニットのおおまかな構造は次のようになっています。

```
ユニット =
  unit 識別子 [ヒント指令] ";"
  宣言部
  実現部
  [初期化部]
  end ".".
宣言部 =
  interface
    [uses 節]
    [インターフェース宣言].
実現部 =
  implementation
  [uses 節]
  [宣言部]
  [Exports 文].
初期化部 =
  [initialization 文リスト [finalization 文リスト] | begin 文リスト].
```

```pascal
unit ユニット識別子;

// 宣言部
interface

  { 宣言部のコード }

// 実現部
implementation

  { 実現部のコード }

// 初期化部 (オプション)
initialization

  { 初期化部のコード }

// 終了処理部 (オプション)
finalization

  { 終了処理のコード }

end.             
```
 - ユニットの**宣言部** (interface セクション) は予約語 **interface** で始まり、実現部 (implementation セクション) の直前で終わります。宣言部は、クライアント (他のユニットやプログラム) が使用できる定数、型、変数、手続き、および関数を宣言します。このセクションには **uses** 句が記述できます。
 - ユニットの**実現部** (implementation セクション) は予約語 **implementation** で始まり、初期化部 (initialization セクション) の直前で終わるか、初期化部がない場合はユニットの末尾で終わります。**implementation 部**は、実現部で宣言された手続きと関数を定義します。このセクションには **uses** 句が記述できます。
 - **初期化部** (initialization セクション) はオプションです。初期化部は予約語 **initialization** で始まり、終了処理部 (finalization セクション) の直前で終わるか、終了処理部がない場合はユニットの末尾で終わります。初期化部には、プログラムの起動時に実行される文が含まれます。
 - **終了処理部** (finalization セクション) はオプションであり、初期化部を持つユニットにのみ存在することができます。終了処理部は予約語 **finalization** で始まり、ユニットの末尾で終わります。プログラム終了に **Halt()** を使用しない限り、終了処理部の文はメインプログラムが終了したときに実行されます。

終了処理部が必要なければ、次のように初期化部を **begin** で書くことができます。これは古い **Turbo Pascal** の構文です。

```pascal
unit ユニット識別子;

// 宣言部
interface

  { 宣言部のコード }

// 実現部
implementation

  { 実現部のコード }

// 初期化部 (オプション)
begin

  { 初期化部のコード }

end.             
```


**See also:**

 - [プログラムの uses 句 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%A8%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%EF%BC%88Delphi%EF%BC%89#.E3.83.97.E3.83.AD.E3.82.B0.E3.83.A9.E3.83.A0.E3.81.AE_uses_.E5.8F.A5)
 - [Halt() (DocWiki)](http://docwiki.embarcadero.com/Libraries/ja/System.Halt)

### (0.1.2.) インクルード ファイル
Delphi では**インクルードファイル**を使うこともできます。`{$I ファイル名}` で指定された位置に指定されたファイル (インクルードファイル) の内容を展開するコンパイラ指令です。

次の例では `contents.inc` に関数 `Foo()` を記述してメインプログラムに埋め込んでいます。

```pascal:Main.pas
program Main; 
var           
  v: Integer; 
{$I 'Contents.inc'}
begin         
  v := Foo(5);
  Writeln(v); 
end.                        
```

```pascal:Contents.inc
  function Foo(n: Integer): Integer;
  begin
    result := n * 10;
  end;
```

Delphi ではインクルードファイルの拡張子は `*.inc` となります。

**See also:**

 - [インクルードファイル（Delphi） (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E3%82%A4%E3%83%B3%E3%82%AF%E3%83%AB%E3%83%BC%E3%83%89_%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%EF%BC%88Delphi%EF%BC%89)


### (0.1.3.) パッケージとライブラリ

パッケージとライブラリは Delphi で静的または動的にロード可能なライブラリで、構造としては特殊なプログラムとなります。

#### (0.1.3.1.) パッケージ

パッケージは、アプリケーション、IDE、あるいはその両方で使用される特別にコンパイルされたライブラリです。 

```
パッケ－ジ =
  package 識別子 ";"
  [requires 節]
  [contains 節]
  end ".".
requires 節 =
  requires 識別子リスト... ";".
contains 節 = 
  contains 識別子リスト... ";".
```

```pascal
package packageName;

requies
  ...;

contains
  ...;

end.
```

VCL や FMX のコンポーネントや IDE 拡張機能もパッケージです。これらはビルドしてインストールする事ができます。

**See also:**

 - [パッケージ (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8)
 - [パッケージとコンポーネントの操作 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%A8%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%AE%E6%93%8D%E4%BD%9C%EF%BC%9A%E3%82%A4%E3%83%B3%E3%83%87%E3%83%83%E3%82%AF%E3%82%B9)

#### (0.1.3.2.) ライブラリ

他のプログラム (や言語) との相互運用性が必要な場合には **ライブラリ**を作ります。

ライブラリは、パッケージと比較すると、エクスポートできるものに関してより大きな制限があります。 ライブラリは定数、型、および通常の変数をエクスポートできません。 つまり、ライブラリで定義されたクラス型は、そのライブラリを使用するプログラムでは見えません。

```
ライブラリ =
  libraty 識別子 ";"
  プログラムブロック ".".
```

ライブラリのブロックの中は一度だけ実行されるため、ここに初期化コードを記述することができます。

```pascal
library TEST;

begin
  { 一度だけ実行される }
end.
```

**unit** における初期化部の古い書き方と同じです。

**See also:**

 - [動的にロードされるライブラリの作成 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%8B%95%E7%9A%84%E3%81%AB%E3%83%AD%E3%83%BC%E3%83%89%E3%81%95%E3%82%8C%E3%82%8B%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E4%BD%9C%E6%88%90)



## 0.2. 構文図
構文図があれば視覚的にも見やすいのでしょうけれど、手間がかかるので省略します。すべての章を書き終えたら考えることにします。

**See also:**

 - [Syntax Diagram (Wikipedia: en)](https://en.wikipedia.org/wiki/Syntax_diagram)

## 0.3. 拡張バッカス・ナウア記法 (EBNF)
EBNF は [0.1.](#01-pascal-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E6%A6%82%E8%A6%81) に出てきたアレです。例えば `プログラムヘッダ` を EBNF で定義すると、以下のようになります。

```
プログラムヘッダ = 
  PROGRAM 識別子 ["(" 識別子リスト ")"] ";".
```

本記事では度々 EBNF が出てきますが、**”なんちゃって EBNF”** だと思いますので、フィーリングで読んでいただけると幸いです。

**See also:**

 - [EBNF (Wikipedia)](https://ja.wikipedia.org/wiki/EBNF)

## 0.4. 有効範囲 (スコープ)
Pascal では手続きや関数を入れ子 (ネスト) にできるので、以下のようなコードが書けます。

```M.pas
program M;
  procedure P;
    procedure A;
      procedure B;
      begin
      end; { B }
    begin
    end; { A }
  begin
  end; { P }
  procedure Q;
    procedure R;
    begin
    end; { R }
    procedure S;
    begin
    end; { S }
  begin
  end; { Q }
begin
end. { M }
```
[フラクタル](https://ja.wikipedia.org/wiki/%E3%83%95%E3%83%A9%E3%82%AF%E3%82%BF%E3%83%AB)みたいですね。この時のネストレベルはこうなっています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/21785/8fe956da-7570-b5ab-58b3-467710c6a49c.png)

この時の各ブロックからアクセス可能なオブジェクトは以下の通りです。

| ブロック | アクセス可能なオブジェクト |
|:----------------:|:------------------|
| M | M |
| P | P, M |
| A | A, P, M|
| B | B, A, P, M|
| Q | Q, M|
| R | R, Q, M|
| S | S, Q, M|

入れ子になった手続きや関数は **関数内関数** とか **ネストされたルーチン (Nested Routines)** と呼ばれます。

**See also:**

 - [スコープ (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97)
 - [ネストルーチン (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E6%89%8B%E7%B6%9A%E3%81%8D%E3%81%A8%E9%96%A2%E6%95%B0%EF%BC%88Delphi%EF%BC%89#.E3.83.8D.E3.82.B9.E3.83.88_.E3.83.AB.E3.83.BC.E3.83.81.E3.83.B3)
 - [Nested function (Wikipedia: en)](https://en.wikipedia.org/wiki/Nested_function)


## 0.5. その他
標準 Pascal の特徴を列挙してしまうと Delphi 等のモダンな Pascal への誤解を生みかねないので、**”Pascal にはこのような特徴がある！"** というような主語の大きい話はできるだけしないようにして話を進めたいと思います。


# 索引
[ [↑ 目次へ](https://qiita.com/ht_deko/items/e2796788c65c2cda1de5) ] [ [→ 1. 記法: トークンと区切り文字](https://qiita.com/ht_deko/items/ce1f56017fb4fcf0302a) ] [:sushi:](https://qiita.com/ht_deko/items/017489388d859692ddbb)