最近の更新 (Recent Changes)

2014-01-01
2013-01-04
2012-12-22
2012-12-15
2012-12-09

Wikiガイド(Guide)

サイドバー (Side Bar)


← 前のページに戻る

1. プログラミング言語PL/0

1.1 プログラミング言語PL/0の文法

PL/0プログラミング言語の文法を簡単に説明しましょう。

簡単に示すと以下のような構成になっています。


const 定数名 = 整数値, 〜 ;
var   変数名, 〜 ;
procedure 手続き名 ;
begin
        プログラム
end;

begin
        メインプログラム
end.


プログラムはconst部、var部、複数の手続き定義、メインプログラム部で構成されます。 構成部分は次のように並べられます。


const部
var部
手続き定義
   ...
手続き定義
メインプログラム部

const部は、省略可能あるいは1つだけ設定でき、プログラムで使う定数を設定します。

var部も、省略可能あるいは1つだけ設定でき、プログラムで使う変数を設定します。

手続き定義は、サブルーチン・プログラムを定義する部分で複数設定できます。省略することも可能です。

メインプログラム部は、メインプログラムを定義する部分で1つだけ定義できます。省略はできません。

const部

const部には、定数を' = 'で整数値で設定した定義を' , 'で並べます。最後には' ; 'を置きます。


const c = 1, teisu = 10, LEN = 256;

定数は、符号付整数です。

var部

var部には、プログラムで使用する変数を定義し、' , 'で並べて置きます。最後には' ; 'を置きます。


var vvg, abc, varx;

変数の型は、符号付整数のみです。

手続き定義

手続き定義には、サブルーチンのプログラムを書きます。

PL/0では手続き呼び出しには、引数を指定できません。 また、返り値もありません。 手続き名を定義してから、サブルーチンのプログラムを書きます。 const部やvar部で定義した定数や変数がサブルーチンの中で使えます。


procedure test;
begin
        a := 1;
        a := a + x
end;

手続き定義はいくつでも定義できます。また、まったく定義しなくてもかまいません。

メインプログラム部

最初によびだされるプログラムを定義します。

これは手続き定義とは異なり、一つのみ定義できます。


begin
        call test
end.


最後は' . 'で終るのに注意してください。

1.2 PL/0の構文

ブロック

ブロックは複数のプログラム行をまとめます。

if文やwhile文の実行されるプログラムのブロックを囲むことに使われます。

C言語で言えば、" { " と " } "に囲むことと同様です。


 
        begin
                プログラム行;
                プログラム行;
                プログラム行
        end

囲まれたプログラム行は、" ; "で区切られます。 C言語とは違い、プログラム行の間を区切るのに" ; "を使うため、最後のプログラム行の最後には" ; "が付いていないことに注意してください。 これは、Pascal系の言語の特徴です。

またブロック"begin"から"end"に囲まれた領域もプログラム行と解釈されます。 そのため、ブロック内でブロックを使う場合には"end"の最後にも" ; "を付けたり付けなかったりします。


 
    begin
        begin
                        プログラム行;
                        プログラム行;
                        プログラム行
        end;
        プログラム行;
        プログラム行;
        begin
                        プログラム行;
                        プログラム行;
                        プログラム行
        end
    end

代入文

代入文は、変数に数式で計算した値を代入します。

変数と数式は、" := "で結ばれているのに注意してください。" = "ではありません。


        変数名 := 数式

変数は、var部で定義された変数を使います。

数式では、次の算術演算子が使えます。


算術演算子 + - * /

演算子の優先度は、* と / が高く、+ と - が低い

数式は、符号付整数の計算式です。


        plvar := 283*a + b

call文

call文は、手続き部で定義されたサブルーチンを呼び出すのに使います。

定義されたサブルーチンは、引数も返り値もないので単独で呼び出すだけの機能です。 呼び出された手続きのサブルーチンが実行され、終了後にこの呼び出しの次に処理が返ってきます。

さすがにモダンなプログラミング言語でこれでは機能不足なため、後の章で説明する拡張版では、引数や返り値やクロージャの拡張を行う予定です。

        call 手続き名

if文

if文は、条件判定を行うプログラム文です。

条件式にある条件を満たせば、then の次の文が実行されます。 普通は、then の下にはブロックを使って複数のプラグラム文が実行されます。

PL/0は簡易な構文なので、普通のプログラミング言語にはあるelse 文が使えないことに注意してください。

    if 条件式 then
    begin
         プログラム行;
         プログラム行;
         プログラム行
    end

条件式では、次の比較演算子が使えます。


比較演算子 = # < <= > >=

# は、左右の値が一致しないことを表す。

また、PL/0には唯一の組み込み関数odd があり、条件式の中で使えます。


組み込み関数 odd 数式

odd 関数は、引数の結果が奇数であるとTRUEとなり、偶数であるとFALSEとなります。


    if odd 2*x then
    begin
        y := 2*x-1
        print y
    end

while文

while 文は、条件式が満たされている間にdo の次からの文を実行し続けます。 普通は、do の下にはブロックを使って複数のプログラム文が実行されます。

条件式は、if 文の説明で示したものと同じものが使えます。


    while 条件式 do
    begin
                プログラム行;
                プログラム行;
                プログラム行
    end

print文

print 文は、プログラムの結果出力を表示するのに使います。


       print 項目, 項目, ... , 項目


項目は、変数名、定数名、整数値、文字列のいずれかです。

print 文では、引数に数式を指定できないことに注意してください。

PL/0 は、整数しか型がないのですが、print 文の中では文字列を指定して表示することができます。

print文は、引数の項目をすべて表示した後に改行を出力します。

1.3 拡張バッカス・ナウア記法(EBNF: Extended Backus–Naur Form)

PL/0の構文を厳密に拡張バッカス・ナウア記法(EBNF)で定義したものを次に示しましょう。

PL/0の構文は、非常に簡潔に定義できます。


program = block "." .
block = [ "const" ident "=" number {"," ident "=" number} ";"]
        [ "var" ident {"," ident} ";"]
        { "procedure" ident ";" block ";" } statement .
statement = [ ident ":=" expression | "call" ident |
            "begin" statement {";" statement } "end" |
            "if" condition "then" statement |
            "while" condition "do" statement|
            "print" [(ident | number | strings)
                   { ","  (ident | number | strings)}]].
condition = "odd" expression |
            expression ("="|"#"|"<"|"<="|">"|">=") expression .
expression = [ "+"|"-"] term { ("+"|"-") term}.
term = factor {("*"|"/") factor}.
factor = ident | number | "(" expression ")".

省略可能な部分は、' [ ' ~ ' ] ' で表されます。

省略可能かつ繰り返し可能な部分は、' { ' ~ ' } ' で表されます。

終端記号は、" で括られます。終端記号は、実際の文字や数字や記号で構成されます。

非終端記号は、' = ' の右辺でどのように構成されているのか定義されます。最後にはピリオドが置かれます。

" | "は、区切られたいずれかの要素を選択するのに使います。

programは、blockと"."で構成され、blockは、省略可能な"const" ~ , "var" ~ と複数の"procedure"手続きと、一つのstatementで構成されます。このように次々の非終端記号の定義を行っています。最終的に定義されていない非終端記号がなくなるようにすべて定義します。

ただし、ident, number, stringsは非終端記号ですが、識別名(変数や定数名), 数値, 文字列であることを示し、ここでは定義していません。 これらは、組み込み関数のようなもので、デフォルトで組み込まれているようなものと考えてください。

1.4 デカルト言語での構文の記述

EBNFのPL/0の定義をデカルト言語で再定義してみましょう。


// BNF of PL/0 by Descartes language

<program>       <block> "." ;
<block>         [ "const" <ident> "=" <number> {"," <ident> "=" <number>} ";"]
                [ "var" <ident> {"," <ident>} ";"]
                { "procedure" <ident> ";" <block> ";" }
                <statement> ;
<statement>     [ <ident> ":=" <expression> | "call" <ident> |
                 "begin" <statement> {";" <statement> } "end" |
                 "if" <condition> "then" <statement> |
                 "while" <condition> "do" <statement> |
                 "print" [(<ident> | <number> | <strings>)
                    { ","  (<ident> | <number>| <strings>)}]];
<condition>     "odd" <expression> |
                <expression> ("="|"#"|"<"|"<="|">"|">=") <expression> ;
<expression>    [ "+"|"-"] <term> { ("+"|"-") <term>};
<term>          <factor> {("*"|"/") <factor>};
<factor>        <ident> | <number> | "(" <expression> ")";

<ident>         <ID>;
<number>        <NUM>;
<strings>       <STRINGS>;

EBNFとの違いは、次に示すような点です。

- 終端記号は、" "で括られます。

- 非終端記号は、< >で括られます。

- 定義の最後は、" ; "です。

- 非終端記号の定義に = 記号は使いません。

デカルト言語ではEBNFで定義した構文は、ここで示したようにほとんど同じで若干表現を変えただけでそのまま使えます。

ここでの定義だけで構文の解析ができます。次の章からは、この構文解析プログラムを利用して実際の実行コードの出力まで説明をします。