一般的事項

PASCAL のプログラムでは、行の切れ目や空白には(名前の切れ目としての他 は)意味はない。つまり、
program sample(input, output); begin writeln('Hi'); end.

program sample(input, output); 
    begin
        writeln('Hi');
    end.
も全く同じ意味である。しかし、
pro gram sample(input, output); begin write ln('Hi'); end.
は文法エラーになる。 (pro と gram の間、 write と ln の間にスペースが 入っているため)。

プログラムの構造

PASCAL のプログラムは、すべて、以下のような構造を持つ。

program プログラム名(ファイル名, ... ,ファイル名);
    宣言部
    実行文部.

プログラム名

プログラム名は、最初はアルファベット、後はアルファベット、数字、または アンダースコア(_)をつかう。(変数名とかも同じ)長さは(一応)無制限で ある。例えば sample や sample_1 は正しいプログラム名だが、 1sample は 正しいプログラム名ではない。

その後の () とその中のファイル名何とかは、 ここのシステムのPascalの場合は指定し なくてもいい。慣習により、 (input,output) と書いておくのが普通である。 つまり、
program sample;
と書いても、
program sample(input,output);
と書いても、プログラムの動きにかわりはない。

宣言部

宣言部は、以下の各宣言部を並べたものである。(必要ないものはなくていい)
    定数宣言部
    型宣言部
    変数宣言部
    手続き・関数宣言部

定数宣言部

定数宣言部は、
const 定数名 = 値; 定数名 = 値; .... 定数名 = 値;

という形をしている。定数名は、プログラム名と同じような、英字から始まる 文字列である。値は、整数、実数、あるいは文字列定数である。この宣言があ ると、「値」が必要なところで、「定数名」を書いて済ませることができる。 例えば、
const pi =3.1415926535;
と書いてあれば、以下のプログラムでいちいち 3.1415926535 と書かなくても pi と書けば済む。

型宣言部

型宣言部は、
type 型名 = 型表記;型名 = 型表記; .... 型名 = 型表記; という形をしている。型名は、プログラム名と同じような、英字から始まる 文字列である。これは、レコード型や配列に名前をつけて使いたい時に使う。 配列なら
type vector = array[1..3] of real;
と宣言しておくと、
var r1, r2 : array[1..3] of real;
のかわりに
var r1, r2 : vector;
と宣言できる。

レコード型を使う場合、型宣言部は必須である。というのは、レコード型は、 もともとあるものではなくてこちらで作るものだからである。レコード型の宣 言は以下のような形をしている。
type 型名 = record
フィールド名 : 型;
......
フィールド名 : 型
end;

変数宣言部

変数宣言部は、
var 変数名[,変数名]:型表記;変数名:型表記 ; .... 変数名:型表記;
という形をしている。変数名は、プログラム名と同じような、英字から始まる 文字列である。なお、 [,変数名]としているのは、あってもなくてもいいとい う意味である。

型表記は、 integer, real, longint のような単純型、 「 array [start..end] of 型表記」という形の配列、レコード型 の型名などが使える。

プログラム先頭で宣言してある変数は、メインプログラムと手続き、関数のど ちらでも使える(同じものである)。

var i : integer; とすれば、 i は整数型の変数で、 -32768 から 32767 までの数を扱える。

var x : real; とすれば、 x は実数型である。

var data : array [1..100] of real; とすれば、 data は実数変数 100 個からなる配列である。

var mat : array [1..100,1..100] of real; とすれば、 data は実数変数 10000 個からなる2次元配列である。 (mat[1,1] から mat[100,100]まで)

手続き・関数宣言部

手続き・関数宣言部は、
手続き・関数頭部; 宣言部; 実行部;
の形をしている。

手続き頭部は
procedure 手続き名(仮引数; .... ; 仮引数);
関数頭部は
function 手続き名(仮引数; .... ; 仮引数) : 型表記;
の形をしている。

仮引数は 引数名 : 型表記 または var 引数名 : 型表記 の形をして いる。

例えば procedure print(n:integer); は、print という手続きが n という整 数型の引数 1 つをとるという宣言になる。実行部でこの手続きを呼び出すに は、例えば print(5) とかすればいい。なお、実行部で呼び出す時には、 5 のかわりに整数型の変数とか値が整数である式も書ける。例えば i,j が整数型 変数なら、 print(i)とかprint(i+j) とかできる。

function cube(x:real):real; とかすると、これは、 cube が実数の引数 1 つをとって実数を帰す関数であると宣言したことになる。実行部では、例えば y := cube(x); と単純に代入する、あるいは y := cube(x)*z; とかいったよ うに、式の中で使うことができる。

さて、宣言部であるが、宣言部の説明は 上の宣言部のところそのものである。 つまり、ここにも、また定数宣言部、型宣言部、変数宣言部、手続き・関数宣 言部といったものを書くことができる。ここで宣言したものは、プログラム先 頭で宣言したものと違い、この手続き(または関数)の中でしか使えない。こ の辺の事情は教科書 を参照のこと。

実行文部も、形式はプログラム本体の実行文部と全く同じである。

実行文部

実行文部は、以下の形をしている
begin 文; 文; ... ;文 end この形のことを、複文ともいう。つまり、実行文部は複文1つからなる。

文は、単純文または構造化文である

単純文

単純文は、代入文または手続き文である。

代入文は 変数 := 式 または 関数名 := 式
関数名 := 式 の形は、関数宣言部のなかの実行文部でだけ出てくる。

変数は、変数名または添字つき変数(配列要素)またはフィールド指定子であ る。

変数名は、変数宣言部で宣言した名前である。

添字つき変数は 配列変数[式, ... ] の形をしたもので、配列変数は array of 何とかと宣言した変数名である。[]の中の式は整数式である。 式の数は、宣言した数とあっている必要がある。

フィールド指定子は、レコード変数.フィールド名 という形のものである。

式はめんどくさいので後で述べる。

手続き文は 手続き名; または 手続き名(実引数, ... , 実引数); という形を している。仮引数がない手続きでは前者の形、あれば後者の形をとる。実引数 の型は、対応する位置にある仮引数の型と同じでないといけない。

構造化文

構造化文は、複文、条件文、繰り返し文のいずれかである。

複文は以下の形をしている。 begin 文; 文; ... ;文 end

条件文は以下の形をしている if 論理式 then 文 または if 論理式 then else

ちょっと注意して欲しいのは、ここで「文」は構造化文でもいいということで ある。つまり、 then else のあとに来る文は複文、条件文、 あるいは繰り返し文でも構わない。論理式の値が真なら then の次の 文が実行され、偽なら、 else があればその後の文が実行される。なけ れば何も起きない。

繰り返し文は for 文、 while 文、 repeat 文のいずれか である

for文は以下の形をしている。 for 制御変数 := 最初の値 to 最後の値 do 文;

制御変数は整数型の変数でないといけない。まず制御変数に最初の値を代入し、 文を実行する。次に制御変数に1を加え、また文を実行する。制御変数が最後 の値になったら、また文を実行する。これで終りである。もし最初の値が最後 の値よりも大きいと、文は一度も実行されない。また、文が実行されたかどう かに無関係に、 for 文の実行が終ったあとの制御変数の値はどうなって いるかわからない。

while 文は以下の形をしている。

while 論理式 do 文;

まず論理式の値を計算し、真であったら文を実行する。実行が終ったらまた論 理式の値を計算し、真であったら文をもう一度実行する。論理式が真でなくな るまでこれを繰り返す。

repeat 文は以下の形をしている。

repeat 文; .... ;文 until 論理式 ;

まず repeat untilの間の文; .... ;文を実行する。実行が終ったら論 理式の値を計算し、偽であったら文; .... ;文をもう一度実行する。論理式が 真にな るまでこれを繰り返す。 while文との違いは、必ず1度は実行されるとい うことである。

式は、単純式であるかないかのいずれかである。

単純式でない式は以下の形をしている

単純式  関係演算子  単純式
関係演算子には以下のものがある

演算子  意味 
=       等しい
<>      等しくない
<       より小さい
<=      より小さいか等しい
>       より大きい
>=      より大きいか等しい
単純式は以下の形をしている

[+/-] 項 または [+/-] 項 加算演算子 項
加算演算子には以下のものがある

演算子  意味
+       加算
-       減算 
or      論理和
項は以下の形をしている

項 または 因子 乗算演算子 因子

乗算演算子には以下のものがある

演算子  意味
  *     乗算
  /     実数除算
 div    整数除算
 mod    剰余
 and    論理積
因子は以下の形をしている

符号なし定数 または 変数 または 関数名 または 関数名(引数、、、) 
または (式) または not 因子
注:ここで、 (式)というのは「括弧のなかに式がある」ものである。

...... というのが、PASCAL の文法定義にそった式の構文規則なのだが、これ では全くなんだかわからないに違いないので、ちょっと補足。

上で、「因子」とか「項」とか「単純式」とかいったなんだかわからないもの が定義されているのは、演算子の優先順位を決めるためである。つまり、たと えば 1 + 2 * 3 > y + g(x)/f(x) と書いた時に、これは (1 + (2 * 3)) > (y + (g(x)/f(x))) と解釈されることになる。これ は、式が上のように定義されているからである。

もう少し普通にいうと、演算子の優先順位は 関係演算子、加算演算子、乗算演算子、 not の順で高くなるというこ とである。

意味論的規則

以上で、PASCAL 言語の文法については一応定義されていることになる。しか し、上の規則にしたがっていて、なおかつ文法的に間違った PASCAL のプログ ラムがある。これは、意味的に間違っているものである。意味的な規則はいろ いろあるが、以下に重要なものをまとめる。

標準手続き

標準手続きには以下のものがある