0. はじめに
Delphi で本記事のコードを試すにはコンソールアプリケーションを作成します。
[ファイル | 新規作成 | その他...]
から
コンソールアプリケーション
を選択します。
新規作成時のソースコードは以下の通りですが、
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〕キーを押すと、
program Hello(Output);
begin
Writeln('Hello, world.');
end.
コンソールが開いて Hello, world.
が表示されます。
コンソールがすぐに閉じて実行結果が見えない場合には、
program Hello(Output);
begin
Writeln('Hello, world.');
Readln; // <-- 追加
end.
最後に Readln;
の行を追加しましょう。
章や節が ( ) で囲まれているものは、オリジナルの J&W には存在しない章や節ですので、読み飛ばしても問題はありません。後で読み返すと Delphi に対する理解が深まると思います。
記事中には Delphi では検証できない 標準 Pascal 用に書かれたコード もあるのですが、そのようなコードは PASCAL-P5 を使って検証する事が可能です。
See also:
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 つの節で構成されていて、実行部以外の節は省略可能なため、最少のソースコードは以下のようになります。
program test;
begin
end.
標準 Pascal では節の順番が決められており、
program test2;
const
A = 1;
var
B: Integer;
begin
end.
const (定数定義部) と var (変数宣言部) を入れ替えるとコンパイルが通らなくなります。
Delphi では実行部以外なら節を入れ替えても大丈夫ですし、
var
A: Integer;
var
B: Integer;
begin
end.
同じ節を何度入れても大丈夫です。
See also:
(0.1.1.) unit と uses
次の例ではユニット Sub で定義された関数 Foo()
を Main プログラムから呼び出しています。
program Main;
uses
Sub;
var
v: Integer;
begin
v := Foo(5);
Writeln(v);
end.
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 文リスト].
unit ユニット識別子;
// 宣言部
interface
{ 宣言部のコード }
// 実現部
implementation
{ 実現部のコード }
// 初期化部 (オプション)
initialization
{ 初期化部のコード }
// 終了処理部 (オプション)
finalization
{ 終了処理のコード }
end.
- ユニットの宣言部 (interface セクション) は予約語 interface で始まり、実現部 (implementation セクション) の直前で終わります。宣言部は、クライアント (他のユニットやプログラム) が使用できる定数、型、変数、手続き、および関数を宣言します。このセクションには uses 句が記述できます。
- ユニットの実現部 (implementation セクション) は予約語 implementation で始まり、初期化部 (initialization セクション) の直前で終わるか、初期化部がない場合はユニットの末尾で終わります。implementation 部は、実現部で宣言された手続きと関数を定義します。このセクションには uses 句が記述できます。
- 初期化部 (initialization セクション) はオプションです。初期化部は予約語 initialization で始まり、終了処理部 (finalization セクション) の直前で終わるか、終了処理部がない場合はユニットの末尾で終わります。初期化部には、プログラムの起動時に実行される文が含まれます。
- 終了処理部 (finalization セクション) はオプションであり、初期化部を持つユニットにのみ存在することができます。終了処理部は予約語 finalization で始まり、ユニットの末尾で終わります。プログラム終了に Halt() を使用しない限り、終了処理部の文はメインプログラムが終了したときに実行されます。
終了処理部が必要なければ、次のように初期化部を begin で書くことができます。これは古い Turbo Pascal の構文です。
unit ユニット識別子;
// 宣言部
interface
{ 宣言部のコード }
// 実現部
implementation
{ 実現部のコード }
// 初期化部 (オプション)
begin
{ 初期化部のコード }
end.
See also:
(0.1.2.) インクルード ファイル
Delphi ではインクルードファイルを使うこともできます。{$I ファイル名}
で指定された位置に指定されたファイル (インクルードファイル) の内容を展開するコンパイラ指令です。
次の例では contents.inc
に関数 Foo()
を記述してメインプログラムに埋め込んでいます。
program Main;
var
v: Integer;
{$I 'Contents.inc'}
begin
v := Foo(5);
Writeln(v);
end.
function Foo(n: Integer): Integer;
begin
result := n * 10;
end;
Delphi ではインクルードファイルの拡張子は *.inc
となります。
See also:
(0.1.3.) パッケージとライブラリ
パッケージとライブラリは Delphi で静的または動的にロード可能なライブラリで、構造としては特殊なプログラムとなります。
(0.1.3.1.) パッケージ
パッケージは、アプリケーション、IDE、あるいはその両方で使用される特別にコンパイルされたライブラリです。
パッケ-ジ =
package 識別子 ";"
[requires 節]
[contains 節]
end ".".
requires 節 =
requires 識別子リスト... ";".
contains 節 =
contains 識別子リスト... ";".
package packageName;
requies
...;
contains
...;
end.
VCL や FMX のコンポーネントや IDE 拡張機能もパッケージです。これらはビルドしてインストールする事ができます。
See also:
(0.1.3.2.) ライブラリ
他のプログラム (や言語) との相互運用性が必要な場合には ライブラリを作ります。
ライブラリは、パッケージと比較すると、エクスポートできるものに関してより大きな制限があります。 ライブラリは定数、型、および通常の変数をエクスポートできません。 つまり、ライブラリで定義されたクラス型は、そのライブラリを使用するプログラムでは見えません。
ライブラリ =
libraty 識別子 ";"
プログラムブロック ".".
ライブラリのブロックの中は一度だけ実行されるため、ここに初期化コードを記述することができます。
library TEST;
begin
{ 一度だけ実行される }
end.
unit における初期化部の古い書き方と同じです。
See also:
0.2. 構文図
構文図があれば視覚的にも見やすいのでしょうけれど、手間がかかるので省略します。すべての章を書き終えたら考えることにします。
See also:
0.3. 拡張バッカス・ナウア記法 (EBNF)
EBNF は 0.1. に出てきたアレです。例えば プログラムヘッダ
を EBNF で定義すると、以下のようになります。
プログラムヘッダ =
PROGRAM 識別子 ["(" 識別子リスト ")"] ";".
本記事では度々 EBNF が出てきますが、”なんちゃって EBNF” だと思いますので、フィーリングで読んでいただけると幸いです。
See also:
0.4. 有効範囲 (スコープ)
Pascal では手続きや関数を入れ子 (ネスト) にできるので、以下のようなコードが書けます。
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 }
フラクタルみたいですね。この時のネストレベルはこうなっています。
この時の各ブロックからアクセス可能なオブジェクトは以下の通りです。
ブロック | アクセス可能なオブジェクト |
---|---|
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:
0.5. その他
標準 Pascal の特徴を列挙してしまうと Delphi 等のモダンな Pascal への誤解を生みかねないので、”Pascal にはこのような特徴がある!" というような主語の大きい話はできるだけしないようにして話を進めたいと思います。
索引
[ ↑ 目次へ ] [ → 1. 記法: トークンと区切り文字 ]