ソフトウエア実践講座 コンパイラ入門

 本資料は、下記の資料と共に使用されることを想定してます。本資料だけを
お持ちの方は、下記資料を整えた上で読み進めて下さい。
 テキストについては市販されています。教員用CDについては無料で提供し
てますので、詳しくは『コンパイラ入門』の付録M 参考情報をご覧下さい。
 ソフトウエア実践講座 コンパイラ入門
ソフトバンク クリエイティブ株式会社
ISBN4-7973-3169-0
 ソフトウエア実践講座 コンパイラ入門 教員用CD
 教員用資料
 講義用スライド(本資料)
 サンプルソースプログラム
 初期テンプレート ([email protected])
 スキャナ構築後 ([email protected])
 パーサ構築後 ([email protected])
 シンボルテーブル構築後 ([email protected])
 コード生成後 ([email protected])
1
ソフトウエア実践講座
コンパイラ入門
~ 究極のソフトウエア開発 ~
2
目次



準備作業
 コードジェネレータの構築
 1章
はじめに
 13章 コードジェネレータ
 2章
コンパイラ
 14章 コードジェネレータ(変数と関数)
 3章
問題の把握
 15章 コードジェネレータ(式と代入文)
 4章
開発環境の設定
 16章 コードジェネレータ(選択文)
スキャナの構築
 17章 コードジェネレータ(繰り返し文)
 5章
語彙定義
 6章
スキャナの構築
 参考資料
パーサの構築
 パーサの構築
 7章
文法定義
 テストプログラム
 8章
パーサの構築
 言語仕様
 9章
パーサの構築(変数と関数)  付録CD-ROM
 10章 パーサの構築(式と代入文)
 11章 パーサの構築(選択文と繰り返し文)
 12章 シンボルテーブル
3
1章 はじめに


シラバス
自作コンパイラのイメージ
4
1章 はじめに
シラバス案(1/6)

コース名









~大学 ~学部 ~学科
~
~
~
~
~
~
~
担当教員







対象者:
開講時期:
コース番号:
授業科目:
単位数:
開講日:
開講時間:
開講場所:
氏名:
研究室:
電話番号:
FAX番号:
メールアドレス:
オフィスアワー:
~
~研究室
~
~
~
~
担当助手/ティーチング・アシスタント


氏名:
オフィスアワー:
~研究室
~
5
1章 はじめに
シラバス案(2/6)

目的


ゴール



自作コンパイラの完成
必要な理論・知識を身につける
前提条件


コンパイラに必要な理論と実践を習得
最低1つのプログラム言語でプログラムを作成できること
課題・レポート・プロジェクト

自作コンパイラを作成するプロジェクトを完成する




1回目:スキャナー構築後のソース、入力プログラム、出力結果
2回目:パーサ構築後のソース、入力プログラム、出力結果
3回目:コードジェネレータ構築後のソース、入力プログラム、出力結果
期末考査
6
1章 はじめに
シラバス案(3/6)

評価



60%
40%
成績






自作コンパイラ作成プロジェクト
期末考査
優
90%以上
良
75%以上、90%未満
可
60%以上、75%以下
不可
60%未満
合計が60%に満たない場合、上限を60%として再試験を評価
上手な履修方法のアドバイス



スケジュールされた章を予め読んでおく事
毎週スケジュールに沿ってプロジェクトを推進・検証する事
プロジェクト推進に必要な内容を整理しておく事
7
1章 はじめに
シラバス案(4/6)

授業スケジュール

1週目
~月~日(~)
2週目
~月~日(~)

3週目
4週目
5週目
6週目
7週目
8週目
9週目
10週目
11週目
12週目
13週目
14週目
~月~日(~)
~月~日(~)
~月~日(~)
~月~日(~)
~月~日(~)
~月~日(~)
~月~日(~)
~月~日(~)
~月~日(~)
~月~日(~)
~月~日(~)
~月~日(~)

15週目
16週目
~月~日(~)
~月~日(~)












1章:はじめに
2章:コンパイラ
3章:問題の把握
4章:開発環境の設定
5章:語彙定義
6章:スキャナーの構築
7章:文法定義
8章:パーサの構築
9章:パーサの構築(変数と関数)
10章:パーサの構築(式と代入文)
11章:パーサの構築(選択文と繰り返し文)
12章:シンボルテーブル
13章:コードジェネレータ
14章:コードジェネレータ(変数と関数)
15章:コードジェネレータ(式と代入文)
16章:コードジェネレータ(選択文)
17章:コードジェネレータ(繰り返し文)
18章:ポストモーテム(事後検証)
期末考査
8
1章 はじめに
シラバス案(5/6)

教科書/テキスト



ソフトウエア実践講座 ~コンパイラ入門~
ソフトバンク クリエイティブ株式会社
ISBN4-7973-3169-0
添付CD内容






統合開発環境プロジェクト一式

Visual Studio .NET 2003

Visual Studio 2005

Visual C#/C++ 2005 Express Edition
Express Edition用擬似アセンブラ
入出力ライブラリ

iolib.lib / iolib.dll / iolib.inc
コンパイラ開発用テンプレート

C#テンプレートソース(Primitive.cs)

入力ファイル(in.txt)

出力ファイル(out.asm)
テストプログラム

検証用テストプログラムサンプル一式

HelloWorld.txt

Change.txt

Fibonacci.txt

Prime.txt
統合化環境用サンプルプログラム

PrimitiveIDE
本スライドにはテキストの一部を抜粋して使用しています
9
1章 はじめに
シラバス案(6/6)~テキスト目次

準備作業











5章
6章
語彙定義
スキャナの構築
7章 文法定義
8章 パーサの構築
9章 パーサの構築(変数と関数)
10章 パーサの構築(式と代入文)
11章 パーサの構築(選択文と繰り返し文)
12章 シンボルテーブル













A
B
C
D
E
F
G
H
I
J
K
L
M
言語仕様
トークンと言語仕様
トークン一覧表
スキャナ後の言語仕様
文法変換規則
文法変換後の言語仕様
文法とパーサの変換対応表
テンプレート
アセンブラ関連
素数プログラム、アセンブラ、実行結果
フィボナッチプログラム、アセンブラ、実行結果
添付CD-ROMについて
参考情報
コードジェネレータの構築






はじめに
コンパイラ
問題の把握
開発環境の設定
パーサの構築


付録
スキャナの構築


1章
2章
3章
4章

13章
14章
15章
16章
17章
コードジェネレータ
コードジェネレータ(変数と関数)
コードジェネレータ(式と代入文)
コードジェネレータ(選択文)
コードジェネレータ(繰り返し文)
ポストモーテム(事後検証)

18章 ポストモーテム(事後検証)
10
1章 はじめに
1.3 本書で構築するコンパイラについて
MODULE Prime;
VAR
i,j,n,q,r,flg : INTEGER;
BEGIN
WriteStr("N>");
ReadInt(n);
i:=2;
WHILE i<=n
DO
flg:=0;
j:=2;
WHILE j<i
DO
q:=i/j;
r:=i-j*q;
IF r=0 THEN flg:=1 END;
j:=j+1
END
IF flg=0
THEN
WriteInt(i);
WriteStr(",");
END;
i:=i+1
END;
END Prime.
Input N>1000 (入力)
2:→剰余が無いので素数
3:→2で割り切れないので素数
4:→2で割り切れる
5:→2→3→4で割り切れないので素数
6:→2で割り切れる
7:→2→3→4→5→6で割り切れないので素数
8:→2で割り切れる
9:→2→3で割り切れる
10:→2で割り切れる
・・・
入力された数値までこれを繰り返す
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,
61,67,71,73,79,83,89,97,101,103,107,109,・・・
11
2章 コンパイラ



コンパイラについて
コンパイラを構成する要素
これから学ぶべき内容
12
2章 コンパイラ
2.1 コンパイラの概要

コンパイラ



特定のプログラム言語をアセンブラに変換するプログラム
一般的には、ある規則を別の規則に変換するプログラム
規則=特定の規則に沿った記述やフォーマット
コンパイラとインタープリタ


コンパイラは変換と実行が別のタイミングで行われる
例:C言語のコンパイル、アプリケーションの実行
インタープリタは変換と実行が同じタイミングで行われる
例:BASICインタープリタ
13
2章 コンパイラ
2.1 コンパイラの概要
プログラム言語
main()
{
puts(Hello, World!);
}

入力
コンパイラ
出力
アセンブラ言語
.data
Letter dd 0
.code
mov Letter, ‘H’
....
コンパイラは変換プログラム


入力プログラム(通常~言語と名前がある)
出力プログラム(通常、アセンブラ言語)
14
2章 コンパイラ
2.1 コンパイラの概要

手続き型言語


オブジェクト指向型言語


C#、C++、Smalltalkなど
関数型言語


C, Pascal, COBOL, FORTRANなど
Lisp, Scheme, MLなど
論理型言語

Prologなど
15
2章 コンパイラ
2.2 コンパイラの全体構成
プログラム言語
main()
{
puts(“Hello!);
}
コンパイラ
スキャナー
パーサ
コード
ジェネレータ
入力:プログラム
出力:トークン
機能:トークンに分解
入力:トークン
出力:構文解析木
機能:構成を分析
「トークン」とはプログラ
ムの最小構成要素
構成=「文法」~あるべ
きトークンがあるべき場
所に収まっているか
アセンブラ言語
.data
Letter dd 0
.code
mov Letter, ‘H’
....
入力:構文解析
出力:アセンブラ
機能:意味(コードを生成)
「意味」とは解析結果
16
2章 コンパイラ
2.2 コンパイラの全体構成
プログラム
MODULE HelloWorld;
BEGIN
WriteStr(“Hello World!“)
END HelloWorld .
トークン
MODULE
HelloWorld
;
BEGIN
WriteStr
(
"Hello World!“
)
END
HelloWorld
.
17
2章 コンパイラ
2.2 コンパイラの全体構成
トークン
MODULE HelloWorld;
BEGIN
WriteStr
(
"Hello World!“
)
END HelloWorld .
構文解析木(該当する部分のみ抽出)
<program>=
<program1>=
|
<statlist>=
<statlist1> =
|
<statement>=
<statement1>=
<literal>=
|
|
MODULE IDENT ;
<program1>
BEGIN
<statlist>
END IDENT .
ε
<decllist>
<statement>
<statlist1>
ε
; <statement> <statlist1>
IDENT→WriteStr
<statement1>
(
<literal>
)
STR→“Hello World!”
NUMBER
IDENT
18
2章 コンパイラ
2.2 コンパイラの全体構成
構文解析木(該当する部分のみ抽出)
<program>=
<program1>=
|
<statlist>=
<statlist1> =
|
<statement>=
<statement1>=
<literal>=
|
|
MODULE IDENT ;
<program1>
BEGIN
<statlist>
END IDENT .
ε
<decllist>
<statement>
<statlist1>
ε
; <statement> <statlist1>
IDENT→WriteStr
<statement1>
(
<literal>
)
STR→”HelloWorld!”
NUMBER
IDENT
アセンブラ
.586
.model flat,stdcall
INCLUDE iolib.inc
.data
Letter dd 0
.code
_start:
mov Letter, 'H'
invoke OutputLetter, Letter
・・・
invoke ExitProcess,0
end _start
END
19
2章 コンパイラ
2.2 コンパイラの全体構成

準備作業


フェーズ1


7~12章:パーサの構築
フェーズ3


5~6章:スキャナの構築
フェーズ2


1~4章:基礎知識と開発環境
13~17章:コードジェネレータの構築
ポストモーテム

18章:まとめと更に深い学習のために
20
3章 問題の把握
ステップ1




BNFと文法
BNFとEBNF
言語仕様
プログラムと言語仕様との関係
21
3章 問題の把握
3.2 BNF(Backus Naur Form)

BNF



英文法



「文法」を記述する表記法
コンピュータ言語を表す為に使われることが多い
単語と単語の構成・関係を表す
5文型は単語の品詞から英文の型を表現している
プログラム言語の文法



プログラムの最小構成要素の構成・関係を表す
変数、キーワード、オペレータなどの関係
代入文の①abc=123、②123=abc、どちらが正しい?
22
3章 問題の把握
3.2 BNFの定義

BNF




ターミナル(終端記号)
ノンターミナル(非終端記号)で< >と表記する
左辺と右辺はターミナルとノンターミナルの集合体
左辺 ::= 右辺


例題





本書では左辺はノンターミナルだけに制限する
<文>
<主語>
<動詞>
<目的語>
::=
::=
::=
::=
<主語> <動詞> <目的語>
I
Love
You
「::=」は置き換えるという意味、以後「→」を使用
23
3章 問題の把握
3.2 BNFの定義


BNFが出来ること

文字列が文法に合致しているかどうかを「識別」できる

置き換えのステップを「導出」と呼ぶ
例題

ステップ1~先頭から開始される~
<文>





ステップ2~<文>は<主語><動詞><目的語>によって置き換えられる~
<主語><動詞><目的語>
ステップ3~<主語>は I によって置き換えられる~
I <動詞><目的語>
ステップ4~<動詞>は Love によって置き換えられる~
I Love <目的語>
ステップ5~<目的語>は You によって置き換えられる~
I Love You
ステップ6~<文>は I Love You に変換換された~
24
3章 問題の把握
3.2 BNFの定義
下記の様
に表す
縦書きでも
同義
<文>
↓
<主語t> <動詞> YOU
↓
↓
I
LOVE
25
3章 問題の把握
3.2 BNF例~数値の識別

数値


BNF





→ <digit> <number1>
→ε
| <digit> <number1>
<digit>
→ 0|1|2|3|4|5|6|7|8|9
注:|(OR)は選択を示す(次スライド参照)
<number>
<number1>
識別できる数値の例


1文字以上の数字
1、1、2、3、5、8、13、21・・・
識別できない数値の例

-123(マイナスは定義されていない)、abc(数字ではない)
26
3章 問題の把握
3.2 BNF例~数値の識別

BNF




<number>
→ <digit> <number1>
<number1> → ε| <digit> <number1>
<digit>
→ 0|1|2|3|4|5|6|7|8|9
BNF(上記の記述と同義)

<number>

<digit>
<digit>
<digit>
<digit>
<digit>
<digit>
<digit>
<digit>
<digit>
<digit>
<number1>
<number1>











→ <digit>
<number1>
→ 0
→ 1
→ 2
→ 3
→ 4
→ 5
→ 6
→ 7
→ 8
→ 9
→ε
→ <digit>
<number1>
27
3章 問題の把握
3.2 BNF例~数値の識別

構文解析木



1を識別した場合の構文解析木


<number> → <digit>
→1
<number1> → ε
13の識別した場合の構文解析木


識別に到るBNF(右辺と左辺)を表したもの
前ページの例題でアニメーションが付いた部分を並べたもの
<number> → <digit>
→ 1
<number1> → <digit> → 3
<number1> → ε
ε(エプシロン)の意味


該当するBNFやシンボルが「選択・識別」されなかった意味
選択・識別する物が無いと明確に示す
28
3章 問題の把握
3.2 BNF例~数値の識別

構文解析木の表記について



横書きの場合(13を識別した場合)


トポロジーが一致していればどんな形式でもかまわない
下記の解析木は同じ意味
<number> → <digit>
→ 1
<number1> → <digit> → 3
<number1> → ε
縦書きの場合(13を識別した場合)
<number>
↓
<digit> <number1>
↓
↓
1
<digit> <number1>
↓
↓
3
ε
29
3章 問題の把握
3.2 BNF例~文字列の識別

文字列


BNF

<ident>
<ident1>

<letter>





→ <letter> <ident1>
→ε
| <letter> <ident1>
→ a|b|c|d|e|f|g|h|i|j|k|l|m|
n|o|p|q|r|s|t|u|v|w|x|y|z|
A|B|C|D|E|F|G |H|I|J|K|L|M|
N|O|P|Q|R|S|T|U|V|W|X|Y|Z
識別できる数値の例


1文字以上の文字でプログラムでは識別子と呼ばれる
a、ab, abc, xyz, Hello ・・
識別できない数値の例

123、abc123(数字は定義されていない)
30
3章 問題の把握
3.2 BNF例~文字列の識別

Abを識別した場合の構文解析木

ステップ1: <ident>





ステップ2: <ident>→<letter>
<ident1>
ステップ3: <ident>→<letter>→A
<ident1>
ステップ4: <ident>→<letter>→A
<ident1>→<letter>
<ident1>
ステップ5: <ident>→<letter>→A
<ident1>→<letter>→b
<ident1>
ステップ6: <ident>→<letter>→A
<ident1>→<letter>→b
<ident1>→ε
31
3章 問題の把握
3.3 BNFとEBNF

EBNF



( )によるグルーピング


再帰呼び出しを省略できる
+による1回以上の繰り返し


まとめて処理できる
*による0回以上の繰り返し


Extended BNF(拡張されたBNF)
BNFよりコンパクトに記述できる
再帰呼び出しを省略できる
[ ]により二者択一の選択

εを使わずに処理できる
32
3章 問題の把握
3.3 EBNF~( )と*

BNF(識別子)





同等のEBNF


<ident>
→ <letter> ( <letter> | <digit> )*
( )の効果


<ident> → <letter> <ident1>
<ident1> → ε
→ <lettter> <ident1>
→ <digit> <ident1>
<letter> → 前例と同じ(英小文字、英大文字)
<digit> → 前例と同じ(0~字、数値)
( <letter> | <digit> )によって2つのノンターミナルがまとめて処理
*の効果

( <letter> | <digit> )*により<ident1>の再帰呼び出しが不要
33
3章 問題の把握
3.3 EBNF~[ ]




BNF

<program> → MODULE <ident> ; <additional> BEGIN ・・・END <ident> .

<additional>→ ε
→ <decllist> (変数定義が行われるノンターミナル)
同等のEBNF

<program> --> MODULE <ident> ; [ <decllist> ] BEGIN ・・・END <ident> .
例題1~変数が無い場合は[ ]内が選択されなかった

MODULE PROGRAM;

~ここに変数定義が無い~

BEGIN
・・・
例題2~変数がある場合は[ ]内が選択された

MODULE PROGRAM;
VAR I, J, K : INTEGER;

BEGIN
・・・
34
3章 問題の把握
3.3 EBNF~+




BNF

<decllist> → VAR <decilist1>

<decllist1> → <identlist> : <type> ; <decllist2>

<decllist2> → ε
→ <decilist1>
同等のEBNF

<decllist> -->VAR ( <identlist> : <type> ; )+
例題1~<decllist>が+により1回選択された場合(前ページの例題2).
例題2~変数定義のラインは1回以上何回定義されてもよい(この例では3回)

MODULE PROGRAM;
VAR I, J, K : INTEGER;
VAR a, b : INTEGER;
VAR z, z, x, y, z : INTEGER;
・・・

BEGIN
・・・
35
3章 問題の把握
3.4 言語仕様=プログラムの設計図
→ MODULE <ident> ; [ <decllist> ] BEGIN <statlist> END <ident> .
→ <letter> ( <letter> | <digit> )*
→ VAR ( <identlist> : <type> ; )+
→ <statement> ( ; <statement> )*
→ <ident> ( , <ident> )*
→ INTEGER | STRING
→ <ident> := <expression>
| IF <relation> THEN <statlist> [ ELSE <statlist> ] END
| WHILE <relation> DO <statlist> END
| <ident> "(" <literal> ")“
<relation>
→ <expression> <rel op> <expression>
<expression>→ <unary op> ] <term> ( <add op> [ <unary op> ] <term> )*
<term>
→ <factor> ( <mul op> <factor> )*
<factor>
→ <literal> | "(" <expression> ")“
<literal>
→ <ident> | <integer> | <string>
<integer>
→ <digit>+
<rel op>
→ = | < | <= | <> | > | >=
<unary op> → + | <add op>
→ +|<mul op>
→ *|/
<digit>
→ 0|1|2|3|4|5|6|7|8|9
<string>
→ " <any character except EOF, EOL and "> “
<letter>
→ a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|
A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
<program>
<ident>
<decllist>
<statlist>
<identlist>
<type>
<statement>
36
3章 問題の把握
3.4 言語仕様の説明

<program>は変数定義と文から構成される






<program> → MODULE <ident> ;
[ <decllist> ]
BEGIN
<statlist>
END <ident> .
<decllist> → VAR ( <identlist> : <type> ; )+
<identlist>
<type>
変数定義
例 VAR I,J,K: INTEGER;
文
例 WriteStr(“HelloWorld!”)
→ <ident> ( , <ident> )*
→ INTEGER | STRING
<statlist> → <statement> ( ; <statement> )*
<statement>→ <ident> := <expression>
| IF <relation> THEN <statlist> [ ELSE <statlist> ] END
| WHILE <relation> DO <statlist> END
| <ident> "(" <literal> ")“
37
3章 問題の把握
3.4 言語仕様の説明

<ident>による識別子~先頭が英字で2文字目以降は英数字




→ <letter> ( <letter> | <digit> )*
→0|1|2|3|4|5|6|7|8|9
→a|b|c|d|e|f|g|h|i|j|k|l|m|n
o|p|q|r|s|t|u|v|w|x|y|z|
A|B|C|D|E|F|G |H|I|J|K|L|M|
N|O|P|Q|R|S|T|U|V|W|X|Y|Z
<string>は” と“で囲まれた文字、但し、EOF, EOL, ”は除く





<ident>
<digit>
<letter>
<string>
→ " <any character except EOF, EOL and "> “
EOL(End Of Line)~2行にまたがれない
EOF(End Of File)~ファイルの終わりまで継続できない
例:”Hello World!”, ”Input N>”, etc
<integer>による数値~1桁以上の数値


<integer>
<digit>
→ <digit>+
→ 0|1|2|3|4|5|6|7|8|9
38
3章 問題の把握
3.4 言語仕様の説明(2/3)

<unary op>は符号


<add op>は加減演算


<add op> → + | -
<mul op>は乗除演算


<unary op>→ + | -
<mul op> → * | /
比較演算子

<rel op>
→
→
→
→
→
→
=
<
<=
<>
>
>=
(EQ)
(LT)
(LE)
(NE)
(GT)
(GE)
39
3章 問題の把握
3.4 言語仕様の説明(3/3)

<literal>は<ident>か<integer>か<string>


→ <ident> | <integer> | <string>
<expression>は符号と加減乗除付の<literal>の式(再帰的に定義)








<literal>
例1:1+2*3
例2:-1+-2*-3
例3:(1+2)*3
例4:(((1)))
(加算、乗算)
(符号付)
(括弧付の式~加算優先)
<expression>→ [ <unary op> ] <term> ( <add op> [ <unary op> ] <term> )*
<term>
→ <factor> ( <mul op> <factor> )*
<factor>
→ <literal> | "(" <expression> ")“
<relation>は比較式~式と式を比較演算子で結合


例:123<234
<relation> → <expression> <rel op> <expression>
40
3章 問題の把握
3.5 言語仕様とプログラム
プログラム
MODULE HelloWorld;
BEGIN
WriteStr ( "Hello World!“ )
END HelloWorld .
プログラムと言語仕様の対応
MODULE <ident> ;
BEGIN
<statlist>→<statement>→<ident> ( <literal> )
END <ident> .
相当する言語仕様 (該当する部分のみ)
<program> → MODULE <ident> ; [ <decllist> ] BEGIN <statlist> END <ident> .
<statlist>
→ <statement> ( ; <statement> )*
<statement> → <ident> "(" <literal> ")“
41
4章 開発環境の設定
ステップ2

環境設定と動作検証


プロジェクト環境のセットアップ
C#/アセンブラの開発/実行環境検証
42
4章 開発環境の設定
4.1 事前準備(開発環境)




開発環境

自作コンパイラを作るために必要な開発/実行環境

コンパイラ、マクロアセンブラ、リンカが必要
コンパイラ

① Visual Studio 2005

② Visual Studio .NET 2003

③ Visual C# 2005 Express Edition (無料ダウンロードはテキスト参照)
アセンブラ

マクロアセンブラ(ml) ~ ①、②の場合

擬似アセンブラ(mlx) ~ ③の場合 (添付CDに格納)
リンカ

リンカ(link) ~ ①、②の場合

Visual C++ 2005 Express Edition ~ ③の場合
(無料ダウンロードについての詳細はテキスト参照)
43
4章 開発環境の設定
4.1 事前準備(開発方法)

統合開発環境による開発




プログラム開発作業の効率化
プロジェクト(CDで提供)を利用可能
新しい言語と環境に慣れる為に、こちらがお勧め
コマンドラインによる開発



エディタによるプログラム入力
コンパイル、アセンブル、リンク、実行はコマンド入力
前提知識や間接作業が多いので、熟練者向き
44
4章 開発環境の設定
4.1 事前準備(開発方法)
統合開発環境
豊富な機能とメニューを選択
コマンドライン
全てコマンドを入力
45
4章 開発環境の設定
4.1 事前準備

① 開発環境がインストールされている事を確認




② 開発環境を持っていない場合


Visual Studio 2005
Visual Studio .NET 2003
Visual C#/C++ 2005 Express Edition (2つ必要)
Visual C#/C++ 2005 Express Editionをダウンロード
③ テキスト4.1 事前準備を熟読

「陥りやすいトラブル」は必ず目を通すこと!
46
4章 開発環境の設定
4.1 事前準備

Visual Studio 2005の統合開発環境を使う場合


Visual Studio .NET 2003の統合開発環境を使う場合


テキスト4.3を参照しながら各自で実行
Visual C#/C++ 2005 Express Editionの統合開発環境
を使う場合


テキスト4.2を参照しながら各自で実行
テキスト4.4を参照しながら各自で実行
上記の開発環境でコマンドラインを用いて開発する場合

テキスト4.5を参照しながら各自で実行
47
4章 開発環境の設定
参考 セットアップ
Visual Studio 2005 (統合開発環境版)をダブルクリック
Setup.exeをダブルクリックし、インストーラを起動
48
4章 開発環境の設定
参考 セットアップ
49
4章 開発環境の設定
参考 C#の開発/実行環境検証
入力
検証用プログラム
In.txt
入力
開発
環境・方法
C#

出力
出力
実行結果
out.asm
動作検証


入力ファイルをコンパイル・実行、出力結果を確認
開発環境、方法を自ら検証し、動作確認できる
50
4章 開発環境の設定
参考 アセンブラの開発/実行環境検証
入力
検証用プログラム
out.asm

入力
開発
環境・方法
アセンブラ
リンカ
出力
出力
実行結果
out.exe
動作検証


入力ファイルをアセンブル・リンク・実行、出力結果を確認
開発環境、方法を自ら検証し、動作確認できる
51
4章 開発環境の設定
参考 C#、アセンブラ、リンカ

コンパイラ(自作コンパイラを開発する言語)


マクロアセンブラ



C#
ML(MASMの後継)
コンパイラが生成したアセンブラをオブジェクトに変換
リンカ


LINK
アセンブラが生成したオブジェクトを実行形式に変換
52
4章 開発環境の設定
参考 C#、アセンブラ、リンカ

コマンドを入力することで検証可能
53
4章 開発環境の設定
参考 コマンドプロンプト


開発製品のコマンドプロンプトを使うこと
アクセサリから起動したコマンドプロンプトは使わないこと
54
5章 語彙(ごい)定義
ステップ3

入力


言語仕様
出力

トークン定義(一覧、チャート)
55
5章 語彙定義
5.1 トークン
プログラム
MODULE HelloWorld;
BEGIN
WriteStr(“Hello World!“)
END HelloWorld .
トークンとはプログラムの最小構成要素
文章だと、「単語」に相当
プログラムだと、「トークン」と言われる
トークン
MODULE
HelloWorld
;
BEGIN
WriteStr
(
"Hello World!“
)
END
HelloWorld
.
56
5章 語彙定義
5.1 トークン

トークンは言語仕様の中で定義されている




① <規則>で定義されているもの~識別子、数値、文字列
② 予約語~MODULE、INTEGERなど
③ 埋め込まれている記号~2文字(<>、:=)、1文字(; .)など
BNFで使われているシンボルとの違いに注意
例1 <ident>は規則で定義(先頭が英字で、2文字目以降は英数字)
例2 MODULE, BEGIN, END等、プログラムの予約語
例3 「;」や「.」など埋め込まれている文字
<program>
→ MODULE <ident> ; [ <decllist> ] BEGIN <statlist> END <ident> .
<ident> → <letter> ( <letter> | <digit> )*
<digit>
→ 0|1|2|3|4|5|6|7|8|9
<letter> → a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p |
q|r|s|t|u|v|w|x|y|z|
A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|
57
Q|R|S|T|U|V|W|X|Y|Z
5章 語彙定義
5.2 語彙定義

<規則>で定義されているトークン



識別子 (先頭は英字、2文字目以降は英数字)
数値
(1桁(1文字)以上の数字)
文字列 (“と”に囲まれた文字~但し1行以内のもの)
<ident> → <letter> ( <letter> | <digit> )*
<integer> → <digit>+
<string> → “ <any character except EOF, EOL and ”> “
<digit>
<letter>
識別子
数値
文字列
→ 0|1|2|3|4|5|6|7|8|9
→ a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|
q|r|s|t|u|v|w|x|y|z|
A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|
Q|R|S|T|U|V|W|X|Y|Z
58
5章 語彙定義
5.2 語彙定義

予約語


プログラムの中で予め決められている文字列
予約語は識別子として使えないことに注意
<program>
<decllist>
<type>
<statement>
→
→
→
→
|
|
|
MODULE <ident> ; [ <decllist> ] BEGIN <statlist> END <ident> .
VAR ( <identlist> : <type> ; )+
INTEGER | STRING
<ident> := <expression>
IF <relation> THEN <statlist> [ ELSE <statlist> ] END
WHILE <relation> DO <statlist> END
<ident> "(" <literal> ")“
59
5章 語彙定義
5.2 語彙定義(3/3)

記号


区切り記号
識別子の規則で定義できない(先頭が英字、2文字目以降が英数)
→
→
→
→
→
|
|
|
<relation>
→
<expression> →
<term>
→
<factor>
→
<rel op>
→
<unary op> →
<add op>
→
<mul op>
→
<program>
<decllist>
<statlist>
<identlist>
<statement>
MODULE <ident> ; [ <decllist> ] BEGIN <statlist> END <ident> .
VAR ( <identlist> : <type> ; )+
<statement> ( ; <statement> )*
<ident> ( , <ident> )*
<ident> := <expression>
IF <relation> THEN <statlist> [ ELSE <statlist> ] END
WHILE <relation> DO <statlist> END
<ident> "(" <literal> ")”
<expression> <rel op> <expression>
<unary op> ] <term> ( <add op> [ <unary op> ] <term> )*
<factor> ( <mul op> <factor> )*
<literal> | "(" <expression> ")”
= | < | <= | <> | > | >=
+|+|*|/
60
5章 語彙定義
5.2 トークン一覧
61
5章 語彙定義
5.2 トークン識別チャート

同じ文字を持つトークンごとにチャート化
62
5章 語彙定義
5.3 語彙定義で使用された規則


この言語仕様の<規則>はスキャナでのみで使用される
これ以降(パーサ以降)は使用しないので削除しておく
<ident> → <letter> ( <letter> | <digit> )*
<integer> → <digit>+
<string> → “ <any character except EOF, EOL and ”> “
<digit>
<letter>
→ 0|1|2|3|4|5|6|7|8|9
→ a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|
q|r|s|t|u|v|w|x|y|z|
A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|
Q|R|S|T|U|V|W|X|Y|Z
63
5章 語彙定義
5.3 新しい言語仕様
→ MODULE IDENT ; [ <decllist> ] BEGIN <statlist> END IDENT .
→ VAR ( <identlist> : <type> ; )+
→ <statement> ( ; <statement> )*
→ IDENT ( , IDENT )*
→ INTEGER | STRING
→ IDENT := <expression>
| IF <relation> THEN <statlist> [ ELSE <statlist> ] END
| WHILE <relation> DO <statlist> END
| IDENT "(" <literal> ")“
<relation>
→ <expression> <rel op> <expression>
<expression> → [ <unary op> ] <term> ( <add op> [ <unary op> ] <term> )*
<term>
→ <factor> ( <mul op> <factor> )*
<factor>
→ <literal> | "(" <expression> ")“
<literal>
→ IDENT | NUMBER | STR
<rel op>
→ = | < | <= | <> | > | >=
<unary op> → + | <add op>
→ +|<mul op>
→ *|/
<program>
<decllist>
<statlist>
<identlist>
<type>
<statement>
64
6章 スキャナの構築
ステップ4

入力



トークン定義(一覧、チャート)
Primitive.cs (スキャナ実装前)
出力

Primitive.cs (スキャナー実装済み)
65
6章 スキャナの構築
6.1 Tokenクラス


Tokenクラスはテンプレートに定義済み
スキャナーは下記の情報だけを設定する
// Token
public class Token
{
public String def = “”;
public String str = “”;
public String type = “”;
}
初期設定
token.def=“”;
token.str=“EOF”;
token.type=“EOF”;
トークン定義(ユニークな名称~何でも良い)
読み込んだトークン文字列
タイプ (変数の場合、整数型か文字型かを設定)
識別子の例
token.def=“IDENT”
token.str=“abc”
token.type=EOF”
予約語の例
token.def=“BEGIN”
token.str=“BEGIN”
token.type=“EOF”
記号の例
token.def=“ASSIGN”
token.str=“:=“
token.type=“EOF”
66
6章 スキャナの構築
6.1 トークン定義


ユニークな名称であれば何でも良いが、下記を使用する
テキストではこの名称で統一しているので後で分かりやすい
67
6章 スキャナの構築
6.1 トークン定義

これは1文字、2文字から構成されるトークン
68
6章 スキャナの構築
6.2 入出力
これらはテンプレートの設定済み
// IO: Scanner + Code Generator
public class IOStream
{
public void Open(String fin, String fout) ファイルのオープン
public void Close()
ファイルのクローズ
public void PutString(String operation) ファイルへ文字列を書き込む
public int GetCharacter()
ファイルより1文字読み出す
public void UngetCharacter(int i)
ファイル(バッファ)へ1文字戻す
public bool isEOF(int i)
public bool isWhiteSpace(int i)
public bool isDigit(int i)
public bool isAlpha(int i)
public bool isSign(int i)
}
パラメータが:
EOF場合にTRUE
Whiteスペース(タブなど)の場合にTRUE
数字の場合にTRUE
英字(大文字・小文字)の場合にTRUE
符号(+/-)の場合にTRUE
69
6章 スキャナの構築
6.3 スキャナ (Main)
static void Main(string[] args)
{
・・・
io.Open(inFile, outFile);
ファイルをオープンする
//Scanner Test
token = io.GetToken();
最初のトークンを読み込む
while (token.def != “EOF”)
ファイルの終わりで無い場合
{
System.Console.WriteLine(token.def + “ ” + token.str);トークンを画面表示
token = io.GetToken();
次のトークンを読み込む
}
io.Close();
・・・
ファイルをクローズする
}
70
6章 スキャナの構築
6.3 スキャナ (GetToken)
// IO: Scanner + Code Generator
public class IOStream
{
・・・
// Scanner
public Token GetToken()
{
token.str = “”;
token.def = "EOF";
token.type = "EOF";
c = GetCharacter();
while (isWhiteSpace(c))
{
c = GetCharacter();
}
ここの部分にトークンを定義する
スキャナはIOStreamの中に定義
これがスキャナのメソッド
最初にtokenの初期設定を行う
1文字を入力する
空文字である場合は
読み飛ばす
次ページ以降を参照)
}
71
6章 スキャナの構築
6.3 スキャナ (識別子)
・・・
if (isAlpha(c))
{
while (isAlpha(c) || isDigit(c))
{
token.str = token.str + (char)c;
c = GetCharacter();
}
UngetCharacter(c);
token.def = “IDENT”;
return token;
ここは6.3 スキャナ(GetToken)の一部
最初の文字が英字
2番目以降が英数字の場合
トークン文字列に1文字を追加
次の文字を読み込む
英数字で無いので1文字を戻す
トークン定義の文字列をIDENTに設定
呼び出し元に戻る
}
72
6章 スキャナの構築
6.3 スキャナ (予約語)
・・・
if (isAlpha(c))
{
while (isAlpha(c) || isDigit(c))
・・・
UngetCharacter(c);
if
(token.str.Equals("MODULE"))
else if (token.str.Equals("BEGIN"))
else if (token.str.Equals("END"))
else if (token.str.Equals("VAR"))
else if (token.str.Equals("INTEGER"))
else if (token.str.Equals("STRING"))
else if (token.str.Equals("IF"))
else if (token.str.Equals("THEN"))
else if (token.str.Equals("ELSE"))
else if (token.str.Equals("WHILE"))
else if (token.str.Equals("DO"))
else
ここは6.3 スキャナ(GetToken)の一部
ここから
・・・
・・・
・・・
ここまでは識別子と同じ、この下に追加
予約語を1つ1つチェックしていく
{ token.def = token.str; return token; }
{ token.def = token.str; return token; }
{ token.def = token.str; return token; }
{ token.def = token.str; return token; }
{ token.def = token.str; return token; }
{ token.def = token.str; return token; }
{ token.def = token.str; return token; }
{ token.def = token.str; return token; }
{ token.def = token.str; return token; }
{ token.def = token.str; return token; }
{ token.def = token.str; return token; }
{ token.def = "IDENT"; return token; }
}
73
6章 スキャナの構築
6.3 スキャナ (数値と文字列)
・・・
else if (isDigit(c))
{
while (isDigit(c))
{
token.str = token.str + (char)c;
c = GetCharacter();
}
UngetCharacter(c);
token.def = "NUMBER";
return token;
}
ここは6.3 スキャナ(GetToken)の一部
先頭の文字が数字
else if (c == ‘“’)
{
c = GetCharacter();
while (c != ‘“’)
{
token.str = token.str + (char)c;
c = GetCharacter();
}
token.def = “STR”;
return token;
}
・・・
先頭の文字が”の場合
2番目以降も数字の場合
トークン文字列に1文字を追加
次の文字を読み込む
数字で無いので1文字を戻す
トークン定義の文字列をNUMBERに設定
呼び出し元に戻る
1文字を読み込む
終わりの”でない場合
トークン文字列に1文字を追加
次の文字を読み込む
トークン定義の文字列をSTRに設定
読み出し元に戻る
74
6章 スキャナの構築
6.3 スキャナ (記号~2文字)
・・・
else if (c == ‘<’)
{
c = GetCharacter();
if (c == ‘=’)
{
token.str = “<=”;
token.def = “LE”;
return token;
}
else if (c == ‘>’)
{
token.str = “<>”;
token.def = “NE”;
return token;
}
else
{
UngetCharacter(c);
token.str = "<";
token.def = “LT”;
return token;
}
・・・
ここは6.3 スキャナ(GetToken)の一部
先頭の文字が<の場合
次の文字を読み込む
2番目の文字が=の場合
トークン文字列を設定
トークン定義の文字列をLEに設定
呼び出し元に戻る
2番目の文字が>の場合
トークン文字列を設定
トークン定義の文字列をNEに設定
呼び出し元に戻る
2番目の文字が=でも>でもない場合
1文字を戻す
トークン文字列を設定
トークン定義の文字列をLTに設定
呼び出し元に戻る
>、>=や、:、:=も同様にして識別する
75
6章 スキャナの構築
6.3 スキャナ (記号~1文字)
・・・
ここは6.3 スキャナ(GetToken)の一部
else if (c == '=')
else if (c == '+')
else if (c == '-')
else if (c == '*')
else if (c == '/')
else if (c == ';')
else if (c == ',')
else if (c == '(')
else if (c == ')')
else if (c == '.')
{ token.str = "="; token.def = "EQ"; return token; }
{ token.str = "+"; token.def = "PLUS"; return token; }
{ token.str = "-"; token.def = "MINUS"; return token; }
{ token.str = "*"; token.def = "MULT"; return token; }
{ token.str = "/"; token.def = "DIV"; return token; }
{ token.str = ";"; token.def = "SEMICOLON"; return token; }
{ token.str = ","; token.def = "COMMA"; return token; }
{ token.str = "("; token.def = "OPEN"; return token; }
{ token.str = ")"; token.def = "CLOSE"; return token; }
{ token.str = "."; token.def = "PERIOD"; return token; }
else if (c == -1)
token; }
else
{ token.str = ""; token.def = "EOF"; token.type = ""; return
{エラー}
76
6章 スキャナの構築
6.4 チェックポイント
入力ファイル
(in.txt)
にデータ
を設定
Primitive.csを実行し
出力結果を比較
コンパイルと実行は
4章を参照
77
7章 文法定義
ステップ5

入力


言語仕様(5.3~新しい言語仕様)
出力

言語仕様(パーサで使用するもの)
78
7章 文法定義
7.1 文法変換とパーサ
変換前の言語仕様(パーサに変換できない)
↓
① EBNFをBNFに変換
② 共通項の除去
③ 再帰性の除去(オプション)
④ 分岐条件の明確化
↓
変換後の言語仕様(パーサに変換できる)
79
7章 文法定義
7.2 EBNFからBNFへの変換
変換元の言語仕様
→ MODULE IDENT ; [ <decllist> ] BEGIN <statlist> END IDENT .
→ VAR ( <identlist> : <type> ; )+
→ <statement> ( ; <statement> )*
→ IDENT ( , IDENT )*
→ INTEGER | STRING
→ IDENT := <expression>
| IF <relation> THEN <statlist> [ ELSE <statlist> ] END
| WHILE <relation> DO <statlist> END
| IDENT "(" <literal> ")“
<relation>
→ <expression> <rel op> <expression>
<expression> → [ <unary op> ] <term> ( <add op> [ <unary op> ] <term> )*
<term>
→ <factor> ( <mul op> <factor> )*
<factor>
→ <literal> | "(" <expression> ")“
<literal>
→ IDENT | NUMBER | STR
<rel op>
→ = | < | <= | <> | > | >=
<unary op> → + | <add op>
→ +|<mul op>
→ *|/
<program>
<decllist>
<statlist>
<identlist>
<type>
<statement>
80
7章 文法定義
7.2 EBNFからBNFへの変換

EBNFの文法をBNFの文法へ変換





( )を使わない
*を使わない
+を使わない
[ ]を使わない
使わないという意味は

別の形(BNF)で同等の操作に置き換える



再帰的な文法記述
εの導入
詳細は3.3を復習
81
7章 文法定義
7.2 EBNFからBNFへの変換
82
7章 文法定義
7.2 EBNFからBNFへの変換
<program>の変換
<decllist>の変換
<statlist>の変換
83
7章 文法定義
7.2 EBNFからBNFへの変換
<identlist>の変換
<statement>の変換
84
7章 文法定義
7.2 EBNFからBNFへの変換
<expression>の変換
<term>の変換
85
7章 文法定義
7.3 共通項の除去
<decllist>の変換
<statement>の変換
86
7章 文法定義
7.4 分岐条件の明確化

分岐条件の明確化




同一ノンターミナルで複数の規則がある場合
トークンを使って分岐ができれば→分岐条件は明確
分岐条件が明確の場合

<sample>→ TOKEN-1 <next> ・・・(A)

<sample>→ TOKEN-2 <next> ・・・(B)

TOKEN-1/2を使ってそれぞれ(A)/(B)に分岐可能
分岐条件が明確でない場合

<sample>→ TOKEN-1 <next> ・・・(A)

<sample>→ TOKEN-1 <next> ・・・(B)

TOKEN-1では(A)に分岐して良いか、(B)に分岐して良いか分からない
87
7章 文法定義
7.4 分岐条件の明確化




見分け方

同一ノンターミナルで複数の規則がある場合

取りうる可能性のある全てのトークンを抜き出して

重複しているトークンがあるかをチェックする
該当しない例~規則が1つしかない場合

<decllist> → VAR <decllist1>
簡単な例

<type>
→ INTEGER | STRING

取りえる可能性のあるトークンはINTEGERかSTRING
簡単な例



<statement>→ IDENT <statement1>
| IF <relation> THEN <statlist> <ifl> END
|
WHILE <relation> DO <statlist> END
IDNETの時Aの規則、IFの時Bの規則、WHILEの時にCの規則
トークンを見て、それぞれの規則に分岐できる
A
B
C
88
7章 文法定義
7.4 分岐条件の明確化

複雑な例(テキストP106)





<expression>→<expression1> <term> <expression2>
アルゴリズム的な抽出の方法はテキストにて説明
これは一見とても難しく見える・・・
背景にある理由を理解する
理解を助ける方法について



上の規則は式を導く~1, -1, 1+1, 1*1, a/b, a*b*c, (1*2)+3など
つまり、<expression2>の次はどんなトークンを導くかは、「式」の後にどん
なトークンを導くかを推定すればよい
<expression>後のトークン、<expression2>後のトークン、これは同義



<expression1> <term> <expression2> ● ←ここの部分
<expression> ● ←ここの部分
左辺と右辺は規則によって置き換わっただけ
89
7章 文法定義
7.4 分岐条件の明確化


プログラム例 (1が式を表す、●の右が次のトークン)

A:=1 ● ;
→ ; を導く

A:=(1 ● );
→ ) を導く

IF A=1 ● THEN
→THEN を導く

WHILE A<1 ● DO
→ DO を導く

IF 1 ● <>B
→ <> を導く(=比較演算子全て)

IF... THEN A:=1 ● ELSE
→ ELSE を導く

... ELSE B:=1 ● END
→ END を導く
この様に該当規則がプログラム中で使われている場所を考える


P106はこれを機械的にやっているだけに過ぎない
図と説明だけを目で追っていかずに背景をきちんと理解する
90
7章 文法定義
文法変換後の言語仕様(1/2)
<program>
→ MODULE IDENT ; <program1> BEGIN <statlist> END IDENT .
<program1> → ε
| <decllist>
<decllist>
<decllist1>
<decllist2>
→
→
→
|
<statlist>
<statlist1>
→ <statement> <statlist1>
→ ε
| ; <statement> <statlist1>
VAR <decllist1>
<identlist> : <type> ; <decllist2>
ε
<decllist1>
<identlist> → IDENT <identlist1>
<identlist1> → ε
| , IDENT <identlist1>
<type>
→ {BEGIN}
→ {VAR}
→ {BEGIN}
→ {IDENT}
→ {END, ELSE}
→ {;}
→ {:}
→ {,}
→ INTEGER | STRING
<statement> → IDENT <statement1>
| IF <relation> THEN <statlist> <ifl> END
|
WHILE <relation> DO <statlist> END
91
7章 文法定義
文法変換後の言語仕様(2/2)
<statement1>
<if1>
<relation>
<expression>
<expression1>
<expression2>
<expression3>
<term>
<term1>
<factor>
<literal>
<rel op>
<unary op>
<add op>
<mul op>
→
|
→
|
:= <expression>
( <literal>)
ε
ELSE <statlist>
→
→
→
|
→
|
→
|
<expression> <rel op> <expression>
<expression1> <term> <expression2>
ε
→ {(, IDENT, NUMBER,STR)
<unary op>
→ {+, -}
ε
→ {;, END, <>, <=, <, =, >, >=, THEN, DO, ), ELSE}
<add op> <expression3> <term> <expression2> → {+, -}
ε
→ {(, IDENT, NUMBER, STR)
<unary op>
→ {+, -}
→
→
|
→
|
<factor> <term1>
ε
→ {+, -, ;, END, <>, <=, <, =, >, >=, THEN, DO, ELSE}
<mul op> <factor> <term1>
→ {*, /}
<literal>
→ {IDENT, NUMBER, STR}
( <expression> )
→ {(}
→
→
→
→
→
IDENT | NUMBER | STR
<> | <= | < | = | > |>=
=+ | =+ | *|/
→ {END}
→ {ELSE}
92
8章 パーサの構築
ステップ6

入力



言語仕様(7.6~変換済み言語仕様)
Primitive.cs (スキャナー実装済み)
出力

Primitive.cs (Hello Worldのみ識別するパーサ)
93
8章 パーサの構築
8.1 パースツリー
MODULE HelloWorld;
BEGIN
WriteStr ( "Hello World!“ )
END HelloWorld .
正常
入力
出力
エラー
94
8章 パーサの構築
8.2 パーサの構築
Main
・・・
static void Main(string[] args)
{
・・・
io.Open(inFile, outFile);
parse.Entry();
・・・
io.Close();
・・・
}
・・・
public class Parse
{
token = io.GetToken();
Program();
XMATCH(“EOF”);
}
パーサのエントリー
パーサはこのクラスに記述する
最初のトークンを読み込む
プログラム(言語仕様)の最初を呼び出す
最後のトークンはEOF
95
8章 パーサの構築
8.2 パーサの構築
テスト用メソッド(パーサを構築していくときに使うと便利なメソッド)
private void strmsg(string msg)
メソッド開始時に呼び出すと便利
{
Console.WriteLine(msg + " started"); Console.ReadLine();
}
private void endmsg(string msg)
{
Console.WriteLine(msg + " ended");
}
メソッド終了時に呼び出すと便利
private void msg()
現在のトークン内容を表示する
{
Console.WriteLine("Token.str=" + token.str + " def=" + token.def);
}
private void stop()
エラー時にはstop();で強制終了
{
Console.ReadLine(); System.Diagnostics.Process.GetCurrentProcess().Close();
}
96
8章 パーサの構築
8.2 パーサの構築
トークンのマッチングを行うメソッド
指定されたトークンと次のトークンを比較する。マッチしない場合は、エラーとなる。
このメソッドを使うことで、マッチング処理を統一化できる上、プログラムが見やすくなる。
private void XMATCH(string s)
{
if (s.Equals(token.def))
else
}
{ token = io.GetToken(); }
{ Console.WriteLine("Parse error");stop();}
指定されたトークンと現在のトークンを比較する。通常、IF文と共に使用される。
private bool MATCH(string s)
{
if (s.Equals(token.def))
else
}
{ return true; }
{ return false; }
97
8章 パーサの構築
8.2 <program>
文法
分岐条件
<program>
→
MODULE IDENT ; <program1>
BEGIN <statlist>
END IDENT .
変換コード
public void Program()
{
XMATCH("MODULE");XMATCH("IDENT");XMATCH("SEMICOLON");
//Program1(); ~8章では限定的な例題の為に、ここはコメントとする~
XMATCH("BEGIN");Statlist();
XMATCH("END");XMATCH("IDENT");XMATCH("PERIOD");
}
98
8章 パーサの構築
8.2 <statlist>
文法
<statlist>
→
<statement> <statlist1>
分岐条件
変換コード
public void Statlist()
{
Statement();Statlist1();
}
99
8章 パーサの構築
8.2 <statlist1>
文法
分岐条件
<statlist1>
→
ε
→
; <statement> <statlist1>
{END, ELSE}
{;}
変換コード
public void Statlist1()
{
if (MATCH(“SEMICOLON”)) {XMATCH("SEMICOLON"); Statement();Statlist1();}
}
εを含むため、elseは不要
100
8章 パーサの構築
8.2 <statement>
文法
分岐条件
<statement>
→
IDENT <statement1>
→
IF <relation> THEN <statlist> <ifl> END
→
WHILE <relation> DO <statlist> END
変換コード
public void Statement()
{
if
(MATCH("IDENT")) {XMATCH("IDENT"); Statement1();}
else if (MATCH("IF"))
{XMATCH("IF"); Relation();XMATCH("THEN");
Statlist(); If1();XMATCH("END");}
else if (MATCH("WHILE")) {XMATCH("WHILE"); Relation();
XMATCH("DO"); Statlist();XMATCH("END");}
else
{エラー}
}
101
8章 パーサの構築
8.2 <statement1>
文法
分岐条件
<statement1>
→
:= <expression>
→
( <literal> )
変換コード
public void Statement1() {
if
(MATCH(“OPEN”))
{XMATCH("OPEN");Literal();XMATCH("CLOSE");}
else if (MATCH(“ASSIGN”)) {XMATCH("ASSIGN");Expression();}}
else
{エラー}
}
102
8章 パーサの構築
8.2 <literal>
文法
分岐条件
<literal>
→
IDENT
→
NUMBER
→
STR
変換コード
public void Literal() {
if
(MATCH("STR"))
else if (MATCH("IDENT"))
else if (MATCH("NUMBER"))
else
}
{XMATCH("STR");}
{XMATCH("IDENT");}
{XMATCH("NUMBER");}
{エラー}
103
8章 パーサの構築
8.3 チェックポイント
Primitive.cs
入力ファイル (in.txt)
MODULE HelloWorld;
BEGIN
WriteStr ( "Hello World!“ )
END HelloWorld .
入力
public class Parse {
・・・
8章を実装
・・・
}
正常
出力
エラー
104
9章 パーサの構築(変数と関数)
ステップ7

入力



言語仕様 (9.1~変数と関数に該当する部分)
Primitive.cs (8章で作成したパーサ)
出力

Primitive.cs (変数と関数を識別できるパーサ)
105
9章 パーサの構築(変数と関数)
9.1 変数と関数に関わる言語仕様

関数の必要性



ここでいう関数は入出力の意味
これが無いとプログラムの入出力が出来ない
変数の必要性



変数はメモリの一部に名前をつけたもの
変数の値を変化させることでプログラムは動く
変数が無いと途中経過や計算結果を保持できない
106
9章 パーサの構築(変数と関数)
9.1 変数と関数に関わる言語仕様
<program>
<program1>
→ MODULE IDENT ; <program1> BEGIN <statlist> END IDENT .
→ ε
→ {BEGIN}
| <decllist>
→ {VAR}
<decllist>
<decllist1>
<decllist2>
→
→
→
|
<statlist>
<statlist1>
→ <statement> <statlist1>
→ ε
| ; <statement> <statlist1>
→ {END, ELSE}
→ {;}
<identlist>
<identlist1>
→ IDENT <identlist1>
→ ε
| , IDENT <identlist1>
→ {:}
→ {,}
<type>
→ INTEGER | STRING
VAR <decllist1>
<identlist> : <type> ; <decllist2>
ε
<decllist1>
→ {BEGIN}
→ {IDENT}
<statement> → IDENT <statement1>
<statement1> → ( <literal>)
<literal>
→ IDENT | NUMBER | STR
107
9章 パーサの構築(変数と関数)
9.2 入力用データサンプル
変数定義を□、関数呼び出しを□で示している
108
9章 パーサの構築(変数と関数)
9.3 <program>
文法
分岐条件
<program>
→
MODULE IDENT ; <program1>
BEGIN <statlist>
END IDENT .
変換コード
public void Program()
{
XMATCH("MODULE");XMATCH("IDENT");XMATCH("SEMICOLON");
Program1(); ~8章のコメントを外す~
XMATCH("BEGIN");Statlist();
XMATCH("END");XMATCH("IDENT");XMATCH("PERIOD");
}
109
9章 パーサの構築(変数と関数)
9.3 <program1>
文法
分岐条件
<program1>
→
ε
→
<decllist>
{BEGIN}
{VAR}
変換コード
public void Program1()
{
if (MATCH(“VAR”)) {Decllist();}
}
εを含むため、elseは不要
110
9章 パーサの構築(変数と関数)
9.3 <decllist>の変換
文法
分岐条件
<decllist>
→
VAR <decllist1>
変換コード
public void Decllist()
{
XMATCH("VAR");Decllist1();
}
111
9章 パーサの構築(変数と関数)
9.3 <decllist1>
文法
分岐条件
<decllist1>
→
<identlist> : <type> ; <decllist2>
変換コード
public void Decllist1()
{
Identlist();XMATCH("COLON");Type();XMATCH("SEMICOLON");Decllist2();
}
112
9章 パーサの構築(変数と関数)
9.3 <decllist2>
文法
分岐条件
<decllist2>
→
ε
→
<decllist1>
{BEGIN}
{IDENT}
変換コード
public void Decllist2()
{
if (MATCH(“IDENT”)) {Decllist1();}
}
εを含むため、elseは不要
113
9章 パーサの構築(変数と関数)
9.3 <identlist>
文法
分岐条件
<identlist>
→
IDENT <identlist1>
変換コード
public void Identlist()
{
XMATCH("IDENT");Identlist1();
}
114
9章 パーサの構築(変数と関数)
9.3 <identlist1>
文法
分岐条件
<identlist1>
→
ε
→
, IDENT <identlist1>
{:}
{,}
変換コード
public void Identlist1()
{
if (MATCH(“COMMA”)) {XMATCH("COMMA"); XMATCH("IDENT");Identlist1();}
}
εを含むため、elseは不要
115
9章 パーサの構築(変数と関数)
9.3 <type>
文法
<type>
→
→
分岐条件
INTEGER
STRING
変換コード
public void Type()
{
if
(MATCH(“INTEGER”))
else if (MATCH("STRING"))
else
}
{XMATCH("INTEGER");}
{XMATCH("STRING");}
{エラー}
116
9章 パーサの構築(変数と関数)
9.3 <statement>
文法
<statement>
→
IDENT <statement1>
分岐条件
9章ではこの部分だけ実装する
変換コード
public void Statement()
{
if
(MATCH("IDENT")) {XMATCH("IDENT"); Statement1();}
else
{エラー}
}
117
9章 パーサの構築(変数と関数)
9.3 <statement1>
文法
<statement1>
→
( <literal> )
分岐条件
9章ではこの部分だけ実装する
変換コード
public void Statement1() {
if
(MATCH(“OPEN”))
else
{XMATCH("OPEN");Literal();XMATCH("CLOSE");}
{エラー}}
118
9章 パーサの構築(変数と関数)
9.3 <literal>
文法
分岐条件
<literal>
→
IDENT
→
NUMBER
→
STR
変換コード
public void Literal() {
if
(MATCH("STR"))
else if (MATCH("IDENT"))
else if (MATCH("NUMBER"))
else
}
{XMATCH("STR");}
{XMATCH("IDENT");}
{XMATCH("NUMBER");}
{エラー}
119
9章 パーサの構築(変数と関数)
9.3 チェックポイント

これは「文法」エラー?




変数の未定義、重複
関数の引数、タイプエラー
識別子、数値、文字列などに関連する不一致、実装課題(長さ)
結論から言うと・・・


これは「文法エラー」ではない~理由は言語仕様に沿っているから
この対応策は12章のシンボルテーブルで行う
120
9章 パーサの構築(変数と関数)
9.3 チェックポイント
Primitive.cs
入力ファイル (in.txt)
~テストファイルをコピー~
(test11-15.txt)
入力
public class Parse {
・・・
9章を実装
・・・
}
正常
出力
エラー
121
10章 パーサの構築(式と代入文)
ステップ8

入力



言語仕様 (10.1~式と代入文に該当する部分)
Primitive.cs (9章で作成したパーサ)
出力

Primitive.cs (式と代入文を識別できるパーサ)
122
10章 パーサの構築(式と代入文)
10.1 式と代入文に関わる言語仕様

代入文の必要性



代入文は変数に値を格納する役割を担う
代入文が無いと変数間の値の受け渡しが出来ない
式の必要性


式は演算(値の変更)の役割を担う
式が無いと値を変更できない
123
10章 パーサの構築(式と代入文)
10.1 式と代入文に関わる言語仕様
~9章で提示したものは除いてあることに注意~
<statement>
<statement1>
→ IDENT <statement1>
→ := <expression>
| ( <literal>)
<expression>
<expression1>
→
→
|
→
|
→
|
<expression1> <term> <expression2>
ε
→ {(, IDENT, NUMBER,STR)
<unary op>
→ {+, -}
ε
→ {;, END, <>, <=, <, =, >, >=, THEN, DO, ), ELSE}
<add op> <expression3> <term> <expression2>
→ {+, -}
ε
→ {(, IDENT, NUMBER, STR)
<unary op>
→ {+, -}
→
→
|
→
|
<factor> <term1>
ε
→ {+, -, ;, END, <>, <=, <, =, >, >=, THEN, DO, ELSE}
<mul op> <factor> <term1>
→ {*, /}
<literal>
→ {IDENT, NUMBER, STR}
( <expression> )
→ {(}
<expression2>
<expression3>
<term>
<term1>
<factor>
<unary op>
<add op>
<mul op>
→ +|→ +|→ *|/
124
10章 パーサの構築(式と代入文)
10.2 入力用データサンプル
式を□、代入文を□で示している
125
10章 パーサの構築(式と代入文)
10.3 <statement>
文法
<statement>
→
IDENT <statement1>
分岐条件
10章ではこの部分だけ実装
変換コード
public void Statement()
{
if
(MATCH("IDENT")) {XMATCH("IDENT"); Statement1();}
else
{エラー}
}
126
10章 パーサの構築(式と代入文)
10.3 <statement1>
文法
<statement1>
→
:= <expression>
→
( <literal> )
分岐条件
ここは9章で既に実装済み
変換コード
public void Statement1() {
if
(MATCH(“OPEN”))
{XMATCH("OPEN");Literal();XMATCH("CLOSE");}
else if (MATCH(“ASSIGN”)) {XMATCH("ASSIGN");Expression();}}
else
{エラー}}
127
10章 パーサの構築(式と代入文)
10.3 <expression>
文法
分岐条件
<expression>
→
<expression1> <term> <expression2>
変換コード
public void Expression()
{
Expression1();Term();Expression2();
}
128
10章 パーサの構築(式と代入文)
10.3 <expression1>
文法
分岐条件
<expression1>
→
ε
→
<unary op>
{(, IDENT, NUMBER,STR}
{+, -}
変換コード
public void Expression1()
{
if (MATCH("PLUS") || MATCH("MINUS")) {UnaryOp();}
}
εを含むため、elseは不要
129
10章 パーサの構築(式と代入文)
10.3 <expression2>
文法
分岐条件
<expression2>
→ε
{;, END, <>, <=, <, =, >, >=, THEN, DO, ), ELSE}
→ <add op> <expression3> <term> <expression2> {+, -}
変換コード
public void Expression2()
{
if (MATCH("PLUS") || MATCH("MINUS")) {ddOp();Expression3();Term();Expression2();}
}
εを含むため、elseは不要
130
10章 パーサの構築(式と代入文)
10.3 <expression3>
文法
分岐条件
<expression3>
→
ε
→
<unary op>
{(, IDENT, NUMBER, STR)
{+, -}
変換コード
public void Expression3()
{
if (MATCH("PLUS") || MATCH("MINUS")) {UnaryOp();}
}
εを含むため、elseは不要
131
10章 パーサの構築(式と代入文)
10.3 <term>
文法
<term>
→
分岐条件
<factor> <term1>
変換コード
public void Term()
{
Factor();Term1();
}
132
10章 パーサの構築(式と代入文)
10.3 <term1>
文法
分岐条件
<term1>
→ε
{+, -, ;, END,<>, <=, <, =, >, >=, THEN, DO, ELSE}
→ <mul op> <factor> <term1> {*, /}
変換コード
public void Term1()
{
if (MATCH("MULT") || MATCH("DIV")) {MultOp();Factor();Term1();}
}
εを含むため、elseは不要
133
10章 パーサの構築(式と代入文)
10.3 <factor>
文法
分岐条件
<factor>
→
<literal>
→
( <expression> )
{IDENT,
{(}
NUMBER, STR}
変換コード
public void Factor(){
if (MATCH("OPEN")) {XMATCH("OPEN");Expression();XMATCH("CLOSE");}
else
{Literal(); }
}
134
10章 パーサの構築(式と代入文)
10.3 <literal>
文法
分岐条件
<literal>
→
IDENT
→
NUMBER
→
STR
変換コード
public void Literal() {
if
(MATCH("STR"))
else if (MATCH("IDENT"))
else if (MATCH("NUMBER"))
else
}
{XMATCH("STR");}
{XMATCH("IDENT");}
{XMATCH("NUMBER");}
{エラー}
135
10章 パーサの構築(式と代入文)
10.3 <rel op>
文法
<rel op>
→
→
→
→
→
→
分岐条件
<>
<=
<
=
>
>=
変換コード
public void RelOp () {
if
(MATCH("EQ"))
else if (MATCH("NE"))
else if (MATCH("LT"))
else if (MATCH("LE"))
else if (MATCH("GT"))
else if (MATCH("GE"))
else
}
{XMATCH("EQ");}
{XMATCH("NE");}
{XMATCH("LT");}
{XMATCH("LE");}
{XMATCH("GT");}
{XMATCH("GE");}
{エラー}
136
10章 パーサの構築(式と代入文)
10.3 <unary op>
文法
分岐条件
<unary op>
→
+
→
-
変換コード
public void UnaryOp()
{
if
(MATCH("PLUS"))
else if (MATCH("MINUS"))
else
}
{XMATCH("PLUS");}
{XMATCH("MINUS");}
{エラー}
137
10章 パーサの構築(式と代入文)
10.3 <add op>
文法
分岐条件
<add op>
→
+
→
-
変換コード
public void AddOp()
{
if
(MATCH("PLUS"))
else if (MATCH("MINUS"))
else
}
{XMATCH("PLUS");}
{XMATCH("MINUS");}
{エラー}
138
10章 パーサの構築(式と代入文)
10.3 <mul op>
文法
分岐条件
<mul op>
→
*
→
/
変換コード
public void MultOp()
{
if
(MATCH("MULT"))
else if (MATCH("DIV"))
else
}
{XMATCH("MULT");}
{XMATCH("DIV");}
{エラー}
139
10章 パーサの構築(式と代入文)
10.3 チェックポイント
Primitive.cs
入力ファイル (in.txt)
~テストファイルをコピー~
(test21-24.txt)
入力
public class Parse {
・・・
10章を実装
・・・
}
正常
出力
エラー
140
11章 パーサの構築(選択文と繰り返し文)
ステップ9

入力



言語仕様 (11.1~選択文と繰り返し文に該当する部分)
Primitive.cs (10章で作成したパーサ)
出力

Primitive.cs (選択文と繰り返し文を識別できるパーサ)
141
11章 パーサの構築(選択文と繰り返し文)
11.1

選択文の必要性





選択文は条件分岐を行う役割を担っている
もし選択文が無いと、条件に応じた処理ができない
それでもプログラムではあるが、計算能力が劣る
3章のChange.txtはプログラムだろうか?
繰り返し文の必要性





繰り返し文は選択文+GOTO文で実装できる
もし無いと、全処理を明示的に記載する必要がある
それでもプログラムではあるが、計算能力が劣る
100までの素数を繰り返し文無しで書けるだろうか?
N(Nは入力した数)はどの様に処理したらいいだろう?
142
11章 パーサの構築(選択文と繰り返し文)
11.1 選択文と繰り返し文の言語仕様
~9章/10章で提示したものは除いてあることに注意~
<statement>
→ IDENT <statement1>
| IF <relation> THEN <statlist> <ifl> END
|
WHILE <relation> DO <statlist> END
<if1>
→ ε
| ELSE <statlist>
<relation>
→ <expression> <rel op> <expression>
<rel op>
→ <> | <= | < | = | > |>=
→ {END}
→ {ELSE}
143
11章 パーサの構築(選択文と繰り返し文)
11.2 入力用データサンプル
選択文と□、繰り返し文を□で示している
144
11章 パーサの構築(選択文と繰り返し文)
11.2 入力用データサンプル
選択文と□、繰り返し文を□で示している
145
11章 パーサの構築(選択文と繰り返し文)
11.2 入力用データサンプル
選択文と□、繰り返し文を□で示している
146
11章 パーサの構築(選択文と繰り返し文)
11.3 チェックポイント<statement>
文法
<statement>
→
IDENT <statement1>
→
IF <relation> THEN <statlist> <ifl> END
→
WHILE <relation> DO <statlist> END
分岐条件
9章で実装済み
変換コード
public void Statement()
{
if
(MATCH("IDENT")) {XMATCH("IDENT"); Statement1();}
else if (MATCH("IF"))
{XMATCH("IF"); Relation();XMATCH("THEN");
Statlist(); If1();XMATCH("END");}
else if (MATCH("WHILE")) {XMATCH("WHILE"); Relation();
XMATCH("DO"); Statlist();XMATCH("END");}
else
{エラー}
}
147
11章 パーサの構築(選択文と繰り返し文)
11.3 チェックポイント <if1>
文法
<if1>
→
→
分岐条件
ε
ELSE <statlist>
{END}
{ELSE}
変換コード
public void If1()
{
if (MATCH("ELSE"))
}
{XMATCH("ELSE");Statlist();}
εを含むため、elseは不要
148
11章 パーサの構築(選択文と繰り返し文)
11.3 チェックポイント <relation>
文法
分岐条件
<relation>
→
<expression> <rel op> <expression>
変換コード
public void Relation()
{
Expression();RelOp();Expression();
}
149
11章 パーサの構築(選択文と繰り返し文)
11.3 チェックポイント <rel op>
文法
<rel op>
→
→
→
→
→
→
分岐条件
<>
<=
<
=
>
>=
変換コード
public void RelOp () {
if
(MATCH("EQ"))
else if (MATCH("NE"))
else if (MATCH("LT"))
else if (MATCH("LE"))
else if (MATCH("GT"))
else if (MATCH("GE"))
else
}
{XMATCH("EQ");}
{XMATCH("NE");}
{XMATCH("LT");}
{XMATCH("LE");}
{XMATCH("GT");}
{XMATCH("GE");}
{エラー}
150
11章 パーサの構築(選択文と繰り返し文)
11.3 チェックポイント
Primitive.cs
入力ファイル (in.txt)
~テストファイルをコピー~
(test31-37.txt)
入力
public class Parse {
・・・
11章を実装
・・・
}
正常
出力
エラー
151
12章 シンボルテーブル
ステップ10

入力




12章で説明するシンボルテーブル
言語仕様(12.1~シンボルテーブルと連動する部分)
Primitive.cs (11章で作成したパーサ)
出力

Primitive.cs (シンボルテーブル実装済みのパーサ)
152
12章 シンボルテーブル
12.1 シンボルテーブルの位置づけ
問題のあるプログラム
シンボルテーブルの必要性
言語仕様には合致
↓
文法エラーではない
該当する言語仕様
しかし現実的に問題
↓
「タイプ」、「定義の有無」等の
情報を付加する
<statement> → IDENT <statement1>
<statement1>→ ( <literal>)
<literal>
→ IDENT | NUMBER | STR
153
12章 シンボルテーブル
12.1 シンボルテーブルの位置づけ
シンボルテーブル
変数定義時にテーブル登録
MODULE TEST;
VAR
I : INTEGER;
タイプ設定時にテーブル更新
BEGIN
J := I
END TEST.
参照時にテーブル情報を確認 (タイプ、有無など)
154
12章 シンボルテーブル
12.2 シンボルテーブルの登録と参照
シンボルテーブル
変数定義時にテーブル登録
Add.Symbol(TOKEN);
タイプ設定時にテーブル更新
SetSymbolTYpe(“INTEGER);
参照時にテーブル情報を確認 (タイプ、有無など)
シンボルの有無の確認
If (CheckSymbol(TOKEN)<0) {未登録} else {登録済み}
155
12章 シンボルテーブル
12.2 シンボルテーブルの登録と参照
シンボルテーブル
public class Symbol
{
private int x = 0;
private const int MAX = 128;
private int idx = -1;
Token[] tbl = new Token[MAX];
public Symbol()
{
x=++idx; tbl[x]=new
x=++idx; tbl[x]=new
x=++idx; tbl[x]=new
x=++idx; tbl[x]=new
}
・・・
}
シンボルテーブルは全てこのクラスに定義
テーブルのサイズ
登録シンボルの個数
テーブルを作成
システム入出力関数を初期設定
Token();
Token();
Token();
Token();
tbl[x].str="WriteStr"; tbl[x].def="PROC"; tbl[x].type="STRING";
tbl[x].str="WriteInt"; tbl[x].def="PROC"; tbl[x].type="INTEGER";
tbl[x].str="ReadStr"; tbl[x].def="PROC"; tbl[x].type="STRING";
tbl[x].str="ReadInt"; tbl[x].def="PROC"; tbl[x].type="INTEGER";
入出力
関数名
識別名
引数
タイプ
156
12章 シンボルテーブル
12.2 シンボルテーブルの登録と参照
シンボルテーブルのメソッド
// Symbol Table
public class Symbol
{
・・・
public void PrintSymbol()
全シンボルテーブルを表示
public void AddSymbol(Token t)
public void SetSymbolType(string type)
public int CheckSymbol(Token t)
トークンの登録
タイプの登録
トークン(=変数)の有無を確認
public int GetIndex()
public Token GetSymbol(int i)
・・・
シンボルテーブルの登録数
指定されたシンボルを返却
}
157
12章 シンボルテーブル
12.3 パーサとの連動
言語仕様 (赤字は実装したパーサ部分に記載する操作)
<identlist>
<identlist1>
<type>
→
→
|
→
|
変数の登録 IDENT <identlist1>
ε
, 変数の登録 IDENT <identlist1>
タイプ(INTEGER)の設定 INTEGER
タイプ(STRING)の設定 STRING
<statement>
<statement1>
→ IDENT <statement1>
→ := <expression> 変数(左辺)の確認
| ( <literal>)
<term>
<term1>
→ <factor> 変数(右辺)の確認 <term1>
→ ε
|
<mul op> <factor> 変数(右辺)の確認 <term1>
<factor>
→ <literal>
| ( <expression> )
→ IDENT | NUMBER | STR
<literal>
158
12章 シンボルテーブル
12.3 パーサとの連動
変数の登録
タイプの設定
public void Identlist()
{
symbol.AddSymbol(token);
XMATCH("IDENT");
Identlist1();
}
この状態の
トークンを使う
public void Identlist1()
public void Type()
{
if (MATCH("INTEGER"))
{
symbol.SetSymbolType("INTEGER");
XMATCH("INTEGER");
}
else if (MATCH("STRING"))
{
symbol.SetSymbolType("STRING");
XMATCH("STRING");
}
else
{
エラー
}
}
{
}
if (MATCH("COMMA"))
{
XMATCH("COMMA");
symbol.AddSymbol(token);
XMATCH("IDENT");
Identlist1();
}
159
12章 シンボルテーブル
12.3 パーサとの連動
変数(左辺)の確認
public void Statement()
{
if (MATCH("IDENT"))
{
Token id = new Token();
id.str = token.str;
id.def = token.def;
id.type = token.type;
XMATCH("IDENT");
Statement1(id);
}
・・・
}
public void Statement1(Token id)
{
if (MATCH("ASSIGN"))
{
XMATCH("ASSIGN");
Expression();
if (symbol.CheckSymbol(id) < 0)
{
左辺(id.str)シンボルが未定義;stop();
}
}
else if (MATCH("OPEN"))
{
XMATCH("OPEN");
Token parameter = new Token();
Literal(parameter); ~右辺のチェック~
XMATCH("CLOSE");
}
・・・
}
160
12章 シンボルテーブル
12.3 パーサとの連動
変数(右辺)の確認
public void Term()
トークン格納用
{
実際の設定は次ページ参照
Token parameter = new Token();
Factor(parameter);
if (parameter.def.Equals("IDENT") && symbol.CheckSymbol(parameter) < 0)
{
右辺(parameter.str)シンボルが未定義;stop();
}
Term1();
}
public void Term1()
{
トークン格納用
Token parameter = new Token();
実際の設定は次ページ参照
if (MATCH("MULT") || MATCH("DIV"))
{
MultOp(); Factor(parameter);
if (parameter.def.Equals("IDENT") && symbol.CheckSymbol(parameter) < 0)
{
右辺( parameter.str)が未定義;stop();
}
Term1();
}
}
161
12章 シンボルテーブル
12.3 パーサとの連動
変数(右辺)の確認 (これらのメソッドはパラメータ設定のために使用される)
public void Factor(Token parameter)
{
if (MATCH("OPEN"))
{
XMATCH("OPEN"); Expression(); XMATCH("CLOSE");
}
else
{
Literal(parameter);
}
}
public void Literal(Token parameter)
{
parameter.str = token.str;
parameter.def = token.def;
parameter.type = token.type;
}
if
(MATCH("IDENT"))
{ XMATCH("IDENT"); }
else if (MATCH("NUMBER")) { XMATCH("NUMBER"); }
else if (MATCH("STR"))
{ XMATCH("STR"); }
else
{ Console.WriteLine("Parse error - literal"); }
162
12章 シンボルテーブル
12.4 チェックポイント
力試しをしてみよう
163
13章 コードジェネレータ
ステップ11

入力



言語仕様 (13.1~HelloWorldに該当する部分)
Primitive.cs (12章で作成したパーサ)
出力

Primitive.cs (HelloWorldを出力するコンパイラ)
164
13章 コードジェネレータ
13.1 Primitive言語とアセンブラの対応
アセンブラ (マクロアセンブラ)
Primitive言語
Primitive.cs
コードジェネレータ
~HelloWorld!の各文字に同様の処理 ~
165
13章 コードジェネレータ
13.1 Primitive言語とアセンブラの対応
コードジェネレータイメージ
現時点では固定的に出力している
io.sw.WriteLine(";ml out.asm /c /coff");
io.sw.WriteLine(";link /Subsystem:console out.obj kernel32.lib iolib.lib");
io.sw.WriteLine("");
io.sw.WriteLine(".586");
io.sw.WriteLine(".model flat,stdcall");
io.sw.WriteLine("");
io.sw.WriteLine("INCLUDE iolib.inc");
io.sw.WriteLine("");
io.sw.WriteLine(".data");
io.sw.WriteLine("
Msg
db \"Hello World!\\n\",0");
io.sw.WriteLine("");
io.sw.WriteLine(".code");
io.sw.WriteLine("");
io.sw.WriteLine("_start:");
io.sw.WriteLine("
invoke OutputString, NEAR32 PTR Msg");
io.sw.WriteLine("
invoke PauseProgram");
io.sw.WriteLine("
invoke ExitProcess,0");
io.sw.WriteLine("end _start");
io.sw.WriteLine("");
io.sw.WriteLine("END");
既に「出来上がった」パーサに
出力処理を「埋め込んで」いく
Primitive.cs
(前章で作成)
・・・・・・
・・・・・・
・・・・・・
・・・・・・
・・・・・・
166
13章 コードジェネレータ
13.3 コードジェネレータ例
パーサに、①~⑥の出力処理を「追加」する
重要:パーサの「ロジック部分は変更しない」~追加するだけ
プログラム部
① プログラム部の開始時
② データ部の開始時
データ部
③ データ部の終了時
コード部
④ コード部の開始時
HelloWorld部
~HelloWorld!の各文字に同様の処理 ~
⑤ コード部の終了時
⑥ プログラム部の終了時
167
13章 コードジェネレータ
13.3 コードジェネレータ例
一番小さいプログラムに必要な言語仕様
<program>
→
MODULE IDENT ;
①の出力処理を追加
<program1>
②の出力処理を追加
③の出力処理を追加
④の出力処理を追加
BEGIN <statlist> END IDENT .
⑤の出力処理を追加
⑥の出力処理を追加
168
13章 コードジェネレータ
13.3 コードジェネレータ例
プログラム部分(①、⑥のコード生成)
169
13章 コードジェネレータ
13.3 コードジェネレータ例
データ部分(上から②、③のコード生成)
コード部分(上から④、⑤のコード生成)
170
13章 コードジェネレータ
13.3 コードジェネレータ例
HelloWorldに必要な言語仕様
<statement> → IDENT
① 関数名を次のメソッドへ送る
<statement1>
<statement1> → (
② 格納用トークンを次のメソッドへ送る
<literal>
④ 出力処理を行う
)
<literal>
→ ③ パラメータを設定する
STR
171
13章 コードジェネレータ
13.3 コードジェネレータ例
HelloWorldの出力処理
13章の場合は、パラメータに設定されているトークンは:
id.str=WriteStr
parameter.str=HelloWorld
172
13章 コードジェネレータ
13.4 チェックポイント
173
13章 コードジェネレータ
13.4 チェックポイント
Primitive.cs
入力ファイル (in.txt)
~テストファイルをコピー~
(test41.txt)
入力
public class Parse {
・・・
13章を実装
・・・
}
出力ファイル (out.asm)
出力
~4章に沿って実行し
結果を確認~
Hello
World!
174
14章 コードジェネレータ(変数と関数)
ステップ12

入力



言語仕様 (7.6から必要部分を選択したもの)
Primitive.cs (13章で作成したコンパイラ)
出力

Primitive.cs (変数と関数を生成するコンパイラ)
175
14章 コードジェネレータ(変数と関数)
14.1 入力データサンプル
変数定義を□、関数呼び出しを□で示している
32ビットの整数型を定義
・WriteStrは前章のHelloWorldと同様に実装する
・その他は該当するシステム入出力を呼び出す
176
14章 コードジェネレータ(変数と関数)
14.2 出力データサンプル
変数・定数はプログラムの入力に応じたものに変更する□
・ invokeを用いて iolib.libの入出力関数を呼び出す(13.2、付録 I 参照)
177
14章 コードジェネレータ(変数と関数)
14.3 パーサとの連動
前章で作成したメソッドに対して、新しい処理を「追加」する
178
14章 コードジェネレータ(変数と関数)
14.4 コードジェネレータの実装
データ定義: シンボルテーブルの変数データを生成
179
14章 コードジェネレータ(変数と関数)
14.4 コードジェネレータの実装
関数定義: 関数呼び出しに新しい関数を追加
180
14章 コードジェネレータ(変数と関数)
14.5 チェックポイント
①既存の下記メソッドを修正
・StrDataメソッド
・GenerateFunctionCallメソッド
②コンパイル後に実行し、出力アセンブラを確認
③アセンブル、リンク後に実行し、画面表示を確認
Primitive.cs
入力ファイル (in.txt)
~テストファイルをコピー~
(test41.txt)
入力
public class Parse {
・・・
14章を実装
・・・
}
出力ファイル (out.asm)
~4章に沿って実行し
結果を確認~
出力
Hello
World!
181
15章 コードジェネレータ(式と代入文)
ステップ13

入力



言語仕様 (7.6から必要部分を選択したもの)
Primitive.cs (14章で作成したコンパイラ)
出力

Primitive.cs (式と代入文生成するコンパイラ)
182
15章 コードジェネレータ(式と代入文)
15.1 スタック
スタックとは・・・
・データ構造
・アクセス命令はプッシュ、ポップ
・一番上にしかアクセスできない
・特徴は「Last-In/First-Out」
・プログラムで簡単に実装できる
・お皿を重ねているイメージ
183
15章 コードジェネレータ(式と代入文)
15.1 スタック
スタックと計算は相性が良い
実行すると
パースツリー
push(1)
プログラム→パーサ(言語仕様)→パースツリー
+
スタック(プッシュとポップ)
=
式の計算ができる
push(2)
(演算子による実行順番が変換されている事に注意)
push(pop()*pop())
スタックで計算
push(3)
push(pop()+pop())
184
15章 コードジェネレータ(式と代入文)
15.2 入力データサンプル
式を□、代入文を□で示している
185
15章 コードジェネレータ(式と代入文)
15.3 出力データサンプル
変数・定数はプログラムの入力に応じたものに変更する□
・システムのスタックを使用(宣言は不要)
・加算:
・減算:
・除算:
・除算:
eax=eax+ebx
eax=eax-ebx
eax=eax*ebx
eax=eax/ebx (商)、edx=剰余
186
15章 コードジェネレータ(式と代入文)
15.4 パーサとの連動
前章で作成したメソッドに対して、新しい処理を「追加」する
187
15章 コードジェネレータ(式と代入文)
15.5 コードジェネレータの実装
代入文: スタックをポップし、該当する変数に格納
変数・定数: 該当する変数・定数を受け取り、スタックにプッシュ
188
15章 コードジェネレータ(式と代入文)
15.5 コードジェネレータの実装
四則(加減乗除)演算: スタックを2回ポップ、計算結果をプッシュ
189
15章 コードジェネレータ(式と代入文)
15.5 コードジェネレータの実装
パーサの変更: 代入文
190
15章 コードジェネレータ(式と代入文)
15.5 コードジェネレータの実装
パーサの変更: 定数・変数・式
191
15章 コードジェネレータ(式と代入文)
15.6 チェックポイント
Change.txt が実行できてから
次の章へ進もう!
Primitive.cs
入力ファイル (in.txt)
~テストファイルをコピー~
(test51-53.txt)
入力
public class Parse {
・・・
15章を実装
・・・
}
出力ファイル (out.asm)
出力
~4章に沿って実行し
結果を確認~
Hello
World!
192
16章 コードジェネレータ(選択文)
ステップ14

入力



言語仕様 (7.6から必要部分を選択したもの)
Primitive.cs (15章で作成したコンパイラ)
出力

Primitive.cs (選択文を生成するコンパイラ)
193
16章 コードジェネレータ(選択文)
16.1 構造化プログラムとブロック
ブロックとは・・・
・コードをまとめたくくり
・選択文のコード生成がし易い
・IF、TRUE、FALSEブロックがある
・各ブロックには番号が付く→
選択文に関する構造をブロックを用いて、条件分岐とラベルを表現する
194
16章 コードジェネレータ(選択文)
16.2 入力データサンプル
IFブロックを□、TRUE/FALSEブロックを□で示している
195
16章 コードジェネレータ(選択文)
16.2 入力データサンプル
196
16章 コードジェネレータ(選択文)
16.3 出力データサンプル
197
16章 コードジェネレータ(選択文)
16.4 パーサとの連動
前章で作成したメソッドに対して、新しい処理を「追加」する
198
16章 コードジェネレータ(選択文)
16.5 コードジェネレータの実装
ブロック番号開始・終了: ブロック番号の生成)
①
②
・この場合の深さは2階層になる
・①~②はブロック番号
③
199
16章 コードジェネレータ(選択文)
16.5 コードジェネレータの実装
ブロック開始・終了: ブロックレベルの生成
②
①
③
⑥
④
⑤
200
16章 コードジェネレータ(選択文)
16.5 コードジェネレータの実装
条件分岐: (IF文の)比較演算子に合致した分岐命令を生成
201
16章 コードジェネレータ(選択文)
16.5 コードジェネレータの実装
パーサの変更: 選択文
202
16章 コードジェネレータ(選択文)
16.5 コードジェネレータの実装
パーサの変更: 条件分岐
203
16章 コードジェネレータ(選択文)
16.6 チェックポイント
Primitive.cs
入力ファイル (in.txt)
~テストファイルをコピー~
(test61-63.txt)
入力
public class Parse {
・・・
16章を実装
・・・
}
出力ファイル (out.asm)
出力
~4章に沿って実行し
結果を確認~
Hello
World!
204
17章 コードジェネレータ(繰り返し文)
ステップ15

入力



言語仕様 (7.6から必要部分を選択したもの)
Primitive.cs (16章で作成したコンパイラ)
出力

Primitive.cs (繰り返し文を生成するコンパイラ)
205
17章 コードジェネレータ(繰り返し文)
17.1 繰り返しにおけるブロック
ブロックは前章と同様に扱う、但し
・WHILEの時、TRUEブロックを使う
・FALSEブロックは使用しない
・下記⑦を追加
①WHILE条件式
もし真なら②に分岐
もし偽なら④へ分岐
②THENの場合はここへ
⑦ここから①に分岐
③は使用しない
④、⑤は使用しない
⑥
206
17章 コードジェネレータ(繰り返し文)
17.2 入力データサンプル
WHILEブロックを□、TRUEブロックを□で示している
207
17章 コードジェネレータ(繰り返し文)
17.3 出力データサンプル
208
17章 コードジェネレータ(繰り返し文)
17.4 パーサとの連動
前章で作成したメソッドに対して、新しい処理を「追加」する
209
17章 コードジェネレータ(繰り返し文)
17.5 コードジェネレータの実装
ブロック開始分岐: WHILEブロックへの無条件分岐命令の生成
⑦
①WHILE条件式
もし真なら②に分岐
もし偽なら④へ分岐
②THENの場合はここへ
⑦ここから①に分岐
③は使用しない
④、⑤は使用しない
⑥
210
17章 コードジェネレータ(繰り返し文)
17.5 コードジェネレータの実装
パーサの変更: 繰り返し文
211
17章 コードジェネレータ(繰り返し文)
17.6 チェックポイント
~最終テスト~
Fibonacci.txt
Prime.txt
をコンパイルして、実行しよう
思った結果が得られただろうか?
Primitive.cs
入力ファイル (in.txt)
~テストファイルをコピー~
(test71-72.txt)
入力
public class Parse {
・・・
17章を実装
・・・
}
出力ファイル (out.asm)
出力
~4章に沿って実行し
結果を確認~
おめでと
う!
212
参考資料




パーサの構築
テストプログラム
言語仕様
付録CD内容について
213
参考資料 パーサの構築
<program>
文法
分岐条件
<program>
→
MODULE IDENT ; <program1>
BEGIN <statlist>
END IDENT .
変換コード
public void Program()
{
XMATCH("MODULE");XMATCH("IDENT");XMATCH("SEMICOLON");Program1();
XMATCH("BEGIN");Statlist();
XMATCH("END");XMATCH("IDENT");XMATCH("PERIOD");
}
214
参考資料 パーサの構築
<program1>
文法
分岐条件
<program1>
→
ε
→
<decllist>
{BEGIN}
{VAR}
変換コード
public void Program1()
{
if (MATCH(“VAR”)) {Decllist();}
}
εを含むため、elseは不要
215
参考資料 パーサの構築
<decllist>の変換
文法
分岐条件
<decllist>
→
VAR <decllist1>
変換コード
public void Decllist()
{
XMATCH("VAR");Decllist1();
}
216
参考資料 パーサの構築
<decllist1>
文法
分岐条件
<decllist1>
→
<identlist> : <type> ; <decllist2>
変換コード
public void Decllist1()
{
Identlist();XMATCH("COLON");Type();XMATCH("SEMICOLON");Decllist2();
}
217
参考資料 パーサの構築
<decllist2>
文法
分岐条件
<decllist2>
→
ε
→
<decllist1>
{BEGIN}
{IDENT}
変換コード
public void Decllist2()
{
if (MATCH(“IDENT”)) {Decllist1();}
}
εを含むため、elseは不要
218
参考資料 パーサの構築
<statlist>
文法
<statlist>
→
<statement> <statlist1>
分岐条件
変換コード
public void Statlist()
{
Statement();Statlist1();
}
219
参考資料 パーサの構築
<statlist1>
文法
分岐条件
<statlist1>
→
ε
→
; <statement> <statlist1>
{END, ELSE}
{;}
変換コード
public void Statlist1()
{
if (MATCH(“SEMICOLON”)) {XMATCH("SEMICOLON"); Statement();Statlist1();}
}
εを含むため、elseは不要
220
参考資料 パーサの構築
<identlist>
文法
分岐条件
<identlist>
→
IDENT <identlist1>
変換コード
public void Identlist()
{
XMATCH("IDENT");Identlist1();
}
221
参考資料 パーサの構築
<identlist1>
文法
分岐条件
<identlist1>
→
ε
→
, IDENT <identlist1>
{:}
{,}
変換コード
public void Identlist1()
{
if (MATCH(“COMMA”)) {XMATCH("COMMA"); XMATCH("IDENT");Identlist1();}
}
εを含むため、elseは不要
222
参考資料 パーサの構築
<type>
文法
<type>
→
→
分岐条件
INTEGER
STRING
変換コード
public void Type()
{
if
(MATCH(“INTEGER”))
else if (MATCH("STRING"))
else
}
{XMATCH("INTEGER");}
{XMATCH("STRING");}
{エラー}
223
参考資料 パーサの構築
<statement>
文法
分岐条件
<statement>
→
IDENT <statement1>
→
IF <relation> THEN <statlist> <ifl> END
→
WHILE <relation> DO <statlist> END
変換コード
public void Statement()
{
if
(MATCH("IDENT")) {XMATCH("IDENT"); Statement1();}
else if (MATCH("IF"))
{XMATCH("IF"); Relation();XMATCH("THEN");
Statlist(); If1();XMATCH("END");}
else if (MATCH("WHILE")) {XMATCH("WHILE"); Relation();
XMATCH("DO"); Statlist();XMATCH("END");}
else
{エラー}
}
224
参考資料 パーサの構築
<statement1>
文法
分岐条件
<statement1>
→
:= <expression>
→
( <literal> )
変換コード
public void Statement1() {
if
(MATCH(“OPEN”))
{XMATCH("OPEN");Literal();XMATCH("CLOSE");}
else if (MATCH(“ASSIGN”)) {XMATCH("ASSIGN");Expression();}}
else
{エラー}}
225
参考資料 パーサの構築
<if1>
文法
<if1>
→
→
分岐条件
ε
ELSE <statlist>
{END}
{ELSE}
変換コード
public void If1()
{
if (MATCH("ELSE"))
}
{XMATCH("ELSE");Statlist();}
εを含むため、elseは不要
226
参考資料 パーサの構築
<relation>
文法
分岐条件
<relation>
→
<expression> <rel op> <expression>
変換コード
public void Relation()
{
Expression();RelOp();Expression();
}
227
参考資料 パーサの構築
<expression>
文法
分岐条件
<expression>
→
<expression1> <term> <expression2>
変換コード
public void Expression()
{
Expression1();Term();Expression2();
}
228
参考資料 パーサの構築
<expression1>
文法
分岐条件
<expression1>
→
ε
→
<unary op>
{(, IDENT, NUMBER,STR}
{+, -}
変換コード
public void Expression1()
{
if (MATCH("PLUS") || MATCH("MINUS")) {UnaryOp();}
}
εを含むため、elseは不要
229
参考資料 パーサの構築
<expression2>
文法
分岐条件
<expression2>
→ε
{;, END, <>, <=, <, =, >, >=, THEN, DO, ), ELSE}
→ <add op> <expression3> <term> <expression2> {+, -}
変換コード
public void Expression2()
{
if (MATCH("PLUS") || MATCH("MINUS")) {ddOp();Expression3();Term();Expression2();}
}
εを含むため、elseは不要
230
参考資料 パーサの構築
<expression3>
文法
分岐条件
<expression3>
→
ε
→
<unary op>
{(, IDENT, NUMBER, STR)
{+, -}
変換コード
public void Expression3()
{
if (MATCH("PLUS") || MATCH("MINUS")) {UnaryOp();}
}
εを含むため、elseは不要
231
参考資料 パーサの構築
<term>
文法
<term>
→
分岐条件
<factor> <term1>
変換コード
public void Term()
{
Factor();Term1();
}
232
参考資料 パーサの構築
<term1>
文法
分岐条件
<term1>
→ε
{+, -, ;, END,<>, <=, <, =, >, >=, THEN, DO, ELSE}
→ <mul op> <factor> <term1> {*, /}
変換コード
public void Term1()
{
if (MATCH("MULT") || MATCH("DIV")) {MultOp();Factor();Term1();}
}
εを含むため、elseは不要
233
参考資料 パーサの構築
<factor>
文法
分岐条件
<factor>
→
<literal>
→
( <expression> )
{IDENT,
{(}
NUMBER, STR}
変換コード
public void Factor(){
if (MATCH("OPEN")) {XMATCH("OPEN");Expression();XMATCH("CLOSE");}
else
{Literal(); }
}
234
参考資料 パーサの構築
<literal>
文法
分岐条件
<literal>
→
IDENT
→
NUMBER
→
STR
変換コード
public void Literal() {
if
(MATCH("STR"))
else if (MATCH("IDENT"))
else if (MATCH("NUMBER"))
else
}
{XMATCH("STR");}
{XMATCH("IDENT");}
{XMATCH("NUMBER");}
{エラー}
235
参考資料 パーサの構築
<rel op>
文法
<rel op>
→
→
→
→
→
→
分岐条件
<>
<=
<
=
>
>=
変換コード
public void RelOp () {
if
(MATCH("EQ"))
else if (MATCH("NE"))
else if (MATCH("LT"))
else if (MATCH("LE"))
else if (MATCH("GT"))
else if (MATCH("GE"))
else
}
{XMATCH("EQ");}
{XMATCH("NE");}
{XMATCH("LT");}
{XMATCH("LE");}
{XMATCH("GT");}
{XMATCH("GE");}
{エラー}
236
参考資料 パーサの構築
<unary op>
文法
分岐条件
<unary op>
→
+
→
-
変換コード
public void UnaryOp()
{
if
(MATCH("PLUS"))
else if (MATCH("MINUS"))
else
}
{XMATCH("PLUS");}
{XMATCH("MINUS");}
{エラー}
237
参考資料 パーサの構築
<add op>
文法
分岐条件
<add op>
→
+
→
-
変換コード
public void AddOp()
{
if
(MATCH("PLUS"))
else if (MATCH("MINUS"))
else
}
{XMATCH("PLUS");}
{XMATCH("MINUS");}
{エラー}
238
参考資料 パーサの構築
<mul op>
文法
分岐条件
<mul op>
→
*
→
/
変換コード
public void MultOp()
{
if
(MATCH("MULT"))
else if (MATCH("DIV"))
else
}
{XMATCH("MULT");}
{XMATCH("DIV");}
{エラー}
239
参考資料 テストプログラム
Change.txt
240
参考資料 テストプログラム
Fibonacci.txt
241
参考資料 テストプログラム
Prime.txt
242
参考資料 言語仕様
オリジナルの言語仕様
→ MODULE <ident> ; [ <decllist> ] BEGIN <statlist> END <ident> .
→ <letter> ( <letter> | <digit> )*
→ VAR ( <identlist> : <type> ; )+
→ <statement> ( ; <statement> )*
→ <ident> ( , <ident> )*
→ INTEGER | STRING
→ <ident> := <expression>
| IF <relation> THEN <statlist> [ ELSE <statlist> ] END
| WHILE <relation> DO <statlist> END
| <ident> "(" <literal> ")“
<relation>
→ <expression> <rel op> <expression>
<expression>→ <unary op> ] <term> ( <add op> [ <unary op> ] <term> )*
<term>
→ <factor> ( <mul op> <factor> )*
<factor>
→ <literal> | "(" <expression> ")“
<literal>
→ <ident> | <integer> | <string>
<integer>
→ <digit>+
<rel op>
→ = | < | <= | <> | > | >=
<unary op> → + | <add op>
→ +|<mul op>
→ *|/
<digit>
→ 0|1|2|3|4|5|6|7|8|9
<string>
→ " <any character except EOF, EOL and "> “
<letter>
→ a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|
A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
<program>
<ident>
<decllist>
<statlist>
<identlist>
<type>
<statement>
243
参考資料 言語仕様
スキャナー後の言語仕様
<program>
<decllist>
<statlist>
<identlist>
<type>
<statement>
<relation>
<expression>
<term>
<factor>
<literal>
<rel op>
<unary op>
<add op>
<mul op>
→ MODULE IDENT ; [ <decllist> ] BEGIN <statlist> END IDENT .
→ VAR ( <identlist> : <type> ; )+
→ <statement> ( ; <statement> )*
→ IDENT ( , IDENT )*
→ INTEGER | STRING
→ IDENT := <expression>
| IF <relation> THEN <statlist> [ ELSE <statlist> ] END
| WHILE <relation> DO <statlist> END
| IDENT "(" <literal> ")“
→ <expression> <rel op> <expression>
→ [ <unary op> ] <term> ( <add op> [ <unary op> ] <term> )*
→ <factor> ( <mul op> <factor> )*
→ <literal> | "(" <expression> ")“
→ IDENT | NUMBER | STR
→ = | < | <= | <> | > | >=
→ +|→ +|→ *|/
244
参考資料 言語仕様
文法変換後の言語仕様(1/2)
<program>
→ MODULE IDENT ; <program1> BEGIN <statlist> END IDENT .
<program1> → ε
| <decllist>
<decllist>
<decllist1>
<decllist2>
→
→
→
|
<statlist>
<statlist1>
→ <statement> <statlist1>
→ ε
| ; <statement> <statlist1>
VAR <decllist1>
<identlist> : <type> ; <decllist2>
ε
<decllist1>
<identlist> → IDENT <identlist1>
<identlist1> → ε
| , IDENT <identlist1>
<type>
→ {BEGIN}
→ {VAR}
→ {BEGIN}
→ {IDENT}
→ {END, ELSE}
→ {;}
→ {:}
→ {,}
→ INTEGER | STRING
<statement> → IDENT <statement1>
| IF <relation> THEN <statlist> <ifl> END
|
WHILE <relation> DO <statlist> END
245
参考資料 言語仕様
文法変換後の言語仕様(2/2)
<statement1>
<if1>
<relation>
<expression>
<expression1>
<expression2>
<expression3>
<term>
<term1>
<factor>
<literal>
<rel op>
<unary op>
<add op>
<mul op>
→
|
→
|
:= <expression>
( <literal>)
ε
ELSE <statlist>
→
→
→
|
→
|
→
|
<expression> <rel op> <expression>
<expression1> <term> <expression2>
ε
→ {(, IDENT, NUMBER,STR)
<unary op>
→ {+, -}
ε
→ {;, END, <>, <=, <, =, >, >=, THEN, DO, ), ELSE}
<add op> <expression3> <term> <expression2> → {+, -}
ε
→ {(, IDENT, NUMBER, STR)
<unary op>
→ {+, -}
→
→
|
→
|
<factor> <term1>
ε
→ {+, -, ;, END, <>, <=, <, =, >, >=, THEN, DO, ELSE}
<mul op> <factor> <term1>
→ {*, /}
<literal>
→ {IDENT, NUMBER, STR}
( <expression> )
→ {(}
→
→
→
→
→
IDENT | NUMBER | STR
<> | <= | < | = | > |>=
+|+|*|/
→ {END}
→ {ELSE}
246
参考資料 付録CD-ROM
Visual Studio .NET 2003 / Visual Studio 2005の
統合開発環境を使う場合(インストール後)
247
参考資料 付録CD-ROM
Visual C#/C++ 2005 Express Editionの
統合開発環境を使う場合(インストール後)
248
参考資料 付録CD-ROM
コマンドラインを用いた開発を行う場合(インストール後)
249