中部大学工学部 卒業論文 PostScriptを出力するDBNコンパイラの作成

中部大学工学部
卒業論文
PostScript を出力する DBN コンパイラの作成
田中 佑典
2004 年 3 月
A Graduation Thesis of College of Engineering, Chubu University
A proposal of DBN compiler with PostScript output
Yusuke Tanaka
目次
第1章
はじめに
1
第2章
Desgin By Numbers
3
2.1 DBN のアプリケーション . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
2.2 アンケートによる DBN の評価 . . . . . . . . . . . . . . . . . . . . . . . . .
4
2.3 DBN のコマンド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
2.3.1
Paper コマンド . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
2.3.2
Pen コマンド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
2.3.3
Set コマンド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
2.3.4
Set 配列コマンド . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
2.3.5
Repeat コマンド . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
2.3.6
Same?コマンド,NotSame?コマンド . . . . . . . . . . . . . . . . .
6
2.3.7
Smaller?コマンド,NotSmaller?コマンド . . . . . . . . . . . . . . .
7
2.3.8
Command コマンド . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
2.3.9
計算・コマンド . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
第3章
PostScript
9
3.1 PostScript 言語の特徴 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.1.1
ページ記述言語 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.1.2
PostScript インタプリタ . . . . . . . . . . . . . . . . . . . . . . . . 10
3.1.3
PostScript プログラムの構造 . . . . . . . . . . . . . . . . . . . . . . 11
3.1.4
PostScript はスタック思考言語 . . . . . . . . . . . . . . . . . . . . 11
3.2 PostScript での DBN コマンドの実現 . . . . . . . . . . . . . . . . . . . . . 11
3.2.1
白黒・カラー . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.2.2
変数の定義 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
iii
3.2.3
繰り返し . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.2.4
PostScript での点 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.2.5
条件による動作の選択 . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2.6
命令ブロックの定義 . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2.7
計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.3 ビットマップ画像とベクトル画像 . . . . . . . . . . . . . . . . . . . . . . . 15
3.3.1
ビットマップ画像 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.3.2
ベクトル画像 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.3.3
ビットマップ画像とベクトル画像の比較 . . . . . . . . . . . . . . . 16
第4章
コンパイラについて
17
4.1 コンパイラ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2 インタプリタとコンパイラ . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2.1
インタプリタ型言語 . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2.2
コンパイラ型言語 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.3 コンパイラの構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.4 Yacc と Lex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
第5章
Yacc,Lex による DBN2PS コンパイラの実現
21
5.1 DBN と PostScript の比較 . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5.1.1
カラーの場合 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.2 DBN プログラムの複雑なとき . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.3 Illustrator による加工 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
5.3.1
第6章
Illustrator により加工できる利点 . . . . . . . . . . . . . . . . . . . 27
おわりに
29
謝 辞
31
参考文献
33
付 録 A プログラム
35
A.1 DBN プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
A.2 PostScript プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
iv
A.3 Yacc プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
A.4 Lex プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
v
図目次
2.1 DBN のアプリケーション . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
2.2 二次利用を目的としたプログラミング環境 . . . . . . . . . . . . . . . . . .
5
4.1 BASIC に代表されるプログラム言語処理方式 . . . . . . . . . . . . . . . . 18
4.2 C,FORTRAN,pascal など多くのプログラム言語処理方式 . . . . . . . . . 19
5.1 Desin By Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.2 PostScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.3 DBN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.4 PostScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.5 DBN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.6 PostScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.7 Illustrator を用いて加工した図形 . . . . . . . . . . . . . . . . . . . . . . . 27
vii
表目次
2.1 アンケート結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
3.1 DBN コマンドと PostScript のオペレータ . . . . . . . . . . . . . . . . . . . 14
3.2 算術オペレータについて . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.3 ビットマップ画像とベクトル画像の比較 . . . . . . . . . . . . . . . . . . . 16
ix
第1章
はじめに
アーティストやグラフィックデザイナーのためのプログラミング入門者として,Design By
Numbers(DBN) が提案され,多くの教育機関で用いられている [1].DBN は最小限の簡単
なコマンドの組合わせであるプログラムにより図形を表示することが可能である.しか
し,表示をした図形はビットマップ画像であるため,作成したデータを紙媒体等への二次
利用ができないという問題点や,Illustrator 等で加工が困難とう問題があり,
そこで,本研究では DBN 言語を用いて作成したプログラムをベクトルデータを扱う
PostScript へ出力するコンパイラの作成を目的とする.
1
第2章
Desgin By Numbers
Design By Numbers(DBN) は MIT(マサチューセッツ工科大学) メディア・ラボの前田ジョ
ンらによって作成され,プログラミング入門者のためにデザインされたプログラミング環
境である.DBN は,図形を描くプログラムの実現が容易である.線を描く等の命令(コ
マンド)で,コンピュータという計算メディアの素材を扱いながら,いかに簡潔で美しい
表現を行うかが追求できる言語である.コマンドを組み合わせたプログラムにより図形を
描画できる.
これにより,視覚的に実行結果を確認することができるため,プログラミングの基礎を
学習する環境として有効とされている.
2.1
DBN のアプリケーション
http://dbn.media.mit.edu/ のサイトにて DBN を動作したり,ダウンロードすることが
できる.Java で作られているためブラウザが異なっても動作することができる.DBN の
アプリケーションを図 2.1 に示す.
3
第 2 章 Desgin By Numbers
図 2.1: DBN のアプリケーション
プログラムと書かれてある左の部分の白い場所にプログラムを書き.プログラムの実行
と書かれているボタンを押すことにより,書いたプログラムを実行できる.実行すると,
図形表示と書かれている場所に図形を表示する.
2.2
アンケートによる DBN の評価
デザインを専攻するプログラミング初心者の大学生を対象として DBN によるプログラ
ミング講義行った.表 2.1 に講義の終了後のプログラミングに対する学生のアンケート結
果を
表 2.1: アンケート結果
2003 年
2002 年
学習前
学習後
学習前
学習後
好き
6人
14 人
3人
12 人
嫌い
13 人
6人
14 人
2人
無回答
2人
3人
2人
5人
表 2.1 より,DBN を学習することでプログラミングが嫌いであった学生の半数以上が,
学習後好きになっていることがわかる.特にプログラムや計算結果を図形として視覚的に
表示する点が評価された.
4
2.3. DBN のコマンド
しかし,問題点として DBN で表示される画像はビットマップであるため,作成した作
品を紙等の高解像の媒体で扱うことが困難であるという不満が多かった.
そこで,本研究では図 2.2 に示すようなプログラミング環境を考える.まず,利用者は
DBN アプリケーションを用いてプログラムを作成し実行する.完成したプログラムを二
次利用したいときは,本研究 DBN2PS コンパイラを用いて PostScript へ変換する.これ
により,紙媒体等への利用や Illustrator 等で手作業による加工が可能となる.本研究では
この DBN2PS コンパイラを実現する.
図 2.2: 二次利用を目的としたプログラミング環境
2.3
DBN のコマンド
作成したコンパイラを使用することで,DBN プログラムを PostScript プログラムに出
力できる DBN のコマンドを紹介しておく.
2.3.1
Paper コマンド
Paper コマンドは用紙の色を設定する.白黒やカラーの色が 0∼100 の 101 種類から設
定できる.白黒の場合は Paper 0 のように記述して使用し,0 が白で 100 が真黒である.
カラーの場合は Paper 0 0 0 のように記述して使用し,左から赤,緑,青で 0∼100 の濃
度を組み合わせ色を設定することができる.
2.3.2
Pen コマンド
Pen コマンドは線など,何かを描く時の色を設定する.Pen 0 や Pen 0 50 100 と色を設
定することができる.Paper コマンドと同じように白黒の場合,0(白)∼100(真黒) の 101
種類からグレーの濃淡別に選択することができる.カラーも同様,Paper コマンドで説明
5
第 2 章 Desgin By Numbers
したように,左の数字から赤,緑,青となっており,0∼100 の数字で色を組み合わせる
ことができる.
2.3.3
Set コマンド
Set コマンドは Set の後にある変数にその後にある値を代入する.Set V 10 のように記
述して使用する.これは,変数 V に 10 を代入するという意味である.
2.3.4
Set 配列コマンド
Set 配列コマンドは,[] の中に位置,その後に色を設定することにより,その位置に設
定した色で点を描画する.Set [10 10] 100 のように記述して使用する.これは 10,10 の
点に 100 の色で点を描く意味である.
2.3.5
Repeat コマンド
Repeat コマンドは Repeat の後にある値からその後にある値まで同じことを繰り返す.
Repeat A 0 100 のように記述して使用する.この意味は変数 A を 0 から 1 ずつ増やして
いき,100 になるまで繰り返すという意味である.
2.3.6
Same?コマンド,NotSame?コマンド
Same?コマンドは,後に置かれた 2 つの値を比較して,値が同じの場合その以下に示す
プログラムを実行する.NotSame?コマンドは Same?コマンドとは逆に,値が違う場合そ
の以下に記述してあるプログラムを実行する.
Same?コマンド,NotSame?コマンドは Same? C 1 のように記述して使用する.この意
味は変数 C は 1 ですか?という意味であり,この質問が正しい時その以下に記述してある
プログラムを実行する.
6
2.3. DBN のコマンド
2.3.7
Smaller?コマンド,NotSmaller?コマンド
Smaller?コマンドは,後に置かれた 2 つの値を比較して,最初の値が次の値より小さい
場合その以下に記述してあるプログラムを実行する.NotSmaller?コマンドは,最初の値
が次の値より小さくない場合その以下に記述してあるプログラムを実行する.
Smaller?コマンド,NotSmaller?コマンドは Smaller? A 50 のように記述して使用する.
この意味は A は 50 より小さいですか?という意味であり,この質問が正しい時,その以
下に記述してあるプログラムを実行する.
2.3.8
Command コマンド
Command コマンドは,命令ブロックに名前を付ければ,その命令ブロックは名前が呼
び出されるたびに実行する.命令ブロックの名前は,新しく登場したコマンドのように使
用することができる.
Command コマンドの使用例は以下に示す.
Command
{
Line
Line
Line
Line
}
Rectangle L B R T
L
R
R
L
B
B
T
T
R
R
L
L
B
T
T
B
Paper 0
Pen 100
Rectangle 30 40 70 90
この例では,Command コマンドを使用し命令ブロック (Rectangle L B R T Line... )
を設定し,そして Paper,Pen でそれぞれの色を決め,Command コマンドで設定した命
令を実行している.L B R T にはそれぞれ 30 40 70 90 が入る.
2.3.9
計算・コマンド
計算は,括弧 () で囲まれた中の計算を行う.
コメントは,//を最初に書くことによりその後にメッセージをつけることができる.こ
のときのメッセージはプログラムには影響されない.
7
第3章
PostScript
PostScript(ポストスクリプト) は,強力なグラフィック機能を持ったプログラミング言語
である.これは,ページ記述言語と呼ばれることが多い.なぜなら,PostScript 言語を用
いると,印刷したいページの中身を記述することができるからである.1つのページは,
必ず1つのグラフィックとして扱われ,そのグラフィックの中には次のような要素が入っ
ている.それらはページ内で位置情報を指定することができる.文字や図形は,べジェ曲
線をしたベクターデータとして表現されているため,出力装置の最大解像度での精細な出
力が可能である.また,PS ファイルの1形式として,Encapsulated PostScript ファイル
(EPS ファイル,EPSF) というものがある.
• 幾何基本図形
直線,弧,円,曲線など.
• テキスト
さまざまな書体が使え,大きさと向きは任意.テキストの文字はグラフィックオブ
ジェクトとして扱われる.
• ビットマップ
グラフィックの内容をオブジェクトではなく,直交格子上に並んだ無数のピクセル
(画像)で記述したもの.
9
第 3 章 PostScript
PostScript 言語の特徴
3.1
• 強力なグラフィックス機能を備えた汎用プログラム言語である.
• プログラミング機能を備えたページ記述言語である.
• プリンタやディスプレイなどのラスタ出力デバイスを制御する対話システムである.
• ページ記述は,アプリケーションおよびデバイスに依存せず,文章の変換が可能な
形式で作成される.
3.1.1
ページ記述言語
ページ記述言語は,プログラムを簡潔に記述し,メモリとデータの転送量を抑えながら
特定の出力装置に依存しないファイルを生成する.
3.1.2
PostScript インタプリタ
PostScript プログラミング言語の命令は,プロセッサを直接制御するのではなく,PostScript
インタプリタというものによって翻訳される.この PostScript インタプリタは,システ
ム構成によっては,RIP(Raster Image Processor= ラスタイメージプロセッサ) と呼ばれ
ることもある.たいていインタプリタでは,ディスプレイリストというものを組み立てる
ようになっている.ディスプレイリストは,ページの中身をコンパクトな形ですべて含ん
だデータ構造である.このディスプレイリストの助けによって,インタプリタは次のよう
な出力を生成する.
• インタプリタは,プリンタでは出力エンジンを制御し,イメージセッタではレーザ
ビームを制御する.
• たいていの RIP では,PostScript ファイルを普通のプリンタが理解できる命令に変
化することができ,ページを画面に表示することもできる.
• RIP によっては,PostScript ファイルをラスタライズ(ラスタ化) したものを,ビッ
トマップ画像形式で保存できるものもある.
10
3.2. PostScript での DBN コマンドの実現
• インタプリタのなかには,ページをラスタライズするだけでなく,オブジェクト指
向の画像形式にも変換できるものもいくつかある.
3.1.3
PostScript プログラムの構造
PostScript のプログラムは,空白などのデリミタで区切られた一連の単語からでき,そ
の単語のことをトークンと呼ぶ.トークンは,PostScript インタプリタの一部であるス
キャナというプログラムによって解析され,オブジェクトに変換される.このオブジェク
トがインタプリタによって実行される.PostScript ではインタプリタが扱うことができる
基本データのことをオブジェクトと呼ぶ.
3.1.4
PostScript はスタック思考言語
PostScript は,引数である文字列のほうが先にあり,関数に相当するオペレータが後で
ある.これがスタック指向言語特有の逆ポーランド記法である.
逆ポーランド記法で書かれたプログラムは,スタックを使うと効率的に実行することが
でき,PostScript インタプリタ内部には,オペランド・スタックというスタックがある.
オブジェクトが入力されると,PostScript インタプリタはオブジェクトの種別をチェッ
クする.オブジェクトには,大きく分けて二つの種別があり,リテラルと実行可能の二つ
に分けられる.
3.2
3.2.1
PostScript での DBN コマンドの実現
白黒・カラー
白黒の場合,0.0 setgray などで白黒を指定することができる.0∼1 までの数値で指定
することができ,0 が真黒で 1 が白である.
カラーの場合,1.0 0.0 0.0 setrgbcolor で色を指定することができる.左の数値から赤,
緑,青とあっている.0.0∼1.0 の濃度で組み合わせて色を指定する.0.0 は濃度 0,1.0 は
最大濃度である.
11
第 3 章 PostScript
3.2.2
変数の定義
名前が付けられたデータは「変数」(variable) と呼ぶ.そしてデータに名前を付けるこ
とを,変数を「定義する」(define) と言う.
変数を定義したいときは,まずデータに付ける名前をスタックにプッシュし,次にその
名前を付けるデータをプッシュし,そして def というオペレータを実行する.
使用例.
/a 100 def
3.2.3
繰り返し
制御オペレータの中には実行可能配列の実行を何回も繰り返すというものがある.その
一つに repeat というものがある.
repeat を使い動作を繰り返したいときは,まず,繰り返したい回数をスタックにプッ
シュし,次に実行可能配列をプッシュして,それから repeat を実行する.
使用例.
/A 10 def
12{
100 A moveto
50 0 lineto
/A A 1 add def
}repeat
0.0 setgray
stroke
3.2.4
PostScript での点
DBN のコマンドでは Set 配列コマンドに使用.
PostScript では,円弧を描くオペレータ arc,arcn,arct,arcto などがある.しかし,
arct,arcto は直線と直線がつながっている部分を丸くしたいときに使うものである.点
を書くことに使用したいので,arc,arcn について以下に説明を示す.
• arc (x y r angle1 angle2 arc) x,y は中心点,r は半径,angle1 は x 軸から円弧の開
始点までの角度,angle2 は x 軸から 2 番目の端点までの角度を指定する.角度は反
12
3.2. PostScript での DBN コマンドの実現
時計回りで指定する.
• arcn (x y r angee1 angle2 arcn) arcn は arc と基本的に同じであるが,角度が時計回
りで指定する.
使用例.
newpath
50 50 0.5 0 360 arc
closepath
0.5 setgray
stroke
3.2.5
条件による動作の選択
DBN のコマンドでは Same?,NotSame?,Smaller?,NotSmaller?コマンドに使用.
PostScript では,if という制御オペレータを使用することで,条件が成り立っていると
きだけ実行可能配列を実行することができる.
if を使い動作を選択的に実行したいときは,まず真偽値をスタックにプッシュし,次に
実行可能配列をプッシュし,そのあとに if を実行する.if は実行可能配列と真偽値をポッ
プし,その真偽値が true の場合,実行配列を実行する.
使用例.
50 50 eq {
0 0 moveto
100 100 lineto
} if
0.0 setgray
stroke
Same?,NotSame?,Smaller?,NotSmaller?コマンドに使用したオペレータを表 3.1 に
示す.
3.2.6
命令ブロックの定義
postScript では,def オペレータを使用することで,複数の命令を定義することができ,
1 つの命令で実行することができる.
使用例は次のようになる.
13
第 3 章 PostScript
表 3.1: DBN コマンドと PostScript のオペレータ
DBN のコマンド
PostScript のオペレータ
Same?
eq(equal; 等しい)
NotSame?
ne(not equal; 等しくない)
Smaller?
lt(less than; より小さい)
NotSmaller?
gt(greater than; より大きい)
/Rectangle {
newpath
Line 10 10 moveto
Line 50 50 lineto
0.0 setgray
stroke
} def
Rectangle
この例では Rectangle という命令を定義している.その命令は括弧の中に書いてある線
を引く命令である.
Rectangle L B R T のように Rectangle の後に変数がある場合は次のようなプログラム
を使用する.
/Rectangle {
/L
/B
/R
/T
exch
exch
exch
exch
def
def
def
def
newpath
L T moveto
L B lineto
0.0 setgray
stroke
} def
60 70 40 30 Rectangle
14
3.3. ビットマップ画像とベクトル画像
計算
3.2.7
PostScript の計算では,算術オペレータを使用し実行する.使用するオペレータは表 3.2
に示す.
表 3.2: 算術オペレータについて
3.3
算術オペレータ
使用例
オペレータの説明
add
num1 num2 add
num1 と num2 を加算した値を返す
sub
num1 num2 sub
num1 から num2 を引いた結果を返す
mul
num1 num2 mul
num1 に num2 を掛けた積を返す
div
num1 num2 div
num1 を num2 で割った値を返す
ビットマップ画像とベクトル画像
DBN アプリケーションの表示結果であるビットマップ画像と PostScript の扱うベクト
ル画像について説明する.
3.3.1
ビットマップ画像
ビットマップ画像は、画像の形状を数式でなく、決まった数の点状の画素の集合で構成
されている.画質は、一定の長さ当たりに存在する画素数の密度、つまり、解像度 (pix-
els/inch) で決まる.よって、点状の画素の集合で構成されているために、画像を拡大し
すぎると、曲線部分、斜め線部分でギザギザが目立つようなる.ビットマップ画像は、グ
ラデーションのような色変化のある画像、連続的に複雑に色変化をする写真画像に適し
ている.画像フォーマットの PICT 形式、BMP 形式、JPEG 形式、GIF 形式、TIFF 形
式、Photoshop 形式等の大多数で、このビットマップ画像の方式を採用している.ビット
マップ画像を扱える代表的なビットマップ系グラフィックソフトとして Adobe Photoshop,
Fractal Design Painter などが上げられる.
15
第 3 章 PostScript
3.3.2
ベクトル画像
ベクトル画像は,画像の直線,曲線等の凹凸をベクトル計算という数式に置き換えて構
成されている.画像の形状を線と面で定義した数式により構成されているため画像を拡大
縮小しても,まったく画質が損なわれることがない.ベクトル画像は,非常にシャープな
直線と曲線で構成されている文字やイラストに最も適している.また,ベクトル画像は,
画像を点状の画素の集合で構成されてないので,解像度とうい概念がない.画像フォー
マットの EPSF 形式は,このベクトル画像の方式を採用してる.ベクトル画像を扱える代
表的なドロー系グラフィックソフトとして Adobe Illustrator, Macromedia FreeHand など
が上げられる.
3.3.3
ビットマップ画像とベクトル画像の比較
表 3.3 にビットマップ画像とベクトル画像の比較を示す.
表 3.3: ビットマップ画像とベクトル画像の比較
16
ビットマップ画像
ベクトル画像
一般的な呼び方
ペイント系
ドロー系
代表的なソフト
Adobe Photshop
Adobe Illustrator
代表的なツール
エアブラシツール
ペンツール (パス)
拡大時のジャギ
大
全くない
データ容量
大
小
特徴
ピクセル情報
べジェ曲線
第4章
コンパイラについて
本研究では,DBN プログラムを PostScript プログラムに出力するコンパイラを Yacc,Lex
を用い作成した.
4.1
コンパイラ
コンピュータが仕事を行うには,プログラムが必要であり,このプログラムは基本的に
C,Fortran,Pascal などといった高級言語を記述されている.この高級言語で書かれたプ
ログラムは直接コンピュータが理解して実行できないので,何か解釈システム (翻訳シス
テム) が必要となる.この解釈システムに当たるのがコンパイラ (compiler) である.
4.2
4.2.1
インタプリタとコンパイラ
インタプリタ型言語
BASIC に代表されるインタプリタ言語は,プログラムに一行ずつ解釈し,CPU に命令
して実行するタイプの言語である.したがって,プログラムが未完成の場合や論理的にミ
スがある場合にも任意のところまで実行したり,途中で中断することが容易である.しか
し,プログラムを逐次解釈する方式のため,実行速度が遅いという欠点もある.
インタプリタ型言語の特徴をまとめると以下のようになる.
• プログラムをメモリから命令ごとを読み取り,それを解釈し実行する
17
第 4 章 コンパイラについて
• 長所:プログラムが完全なものでなくても実行可能
• 短所:実行に時間がかかる
エディタ
メモリ
一行呼び出し
実行
インタプリタ
:
図 4.1: BASIC に代表されるプログラム言語処理方式
4.2.2
コンパイラ型言語
コンパイラ型言語はコーティングされたプログラムをコンパイラによって機械語に翻訳
して実行するタイプの言語である.そのため実行速度がインタプリタ型言語に比較して速
く,大規模で効率的な処理が必要な場合にはこのタイプのプログラム言語が有利である.
しかし,プログラムをコーディングする際には文法の誤りやプログラムの論理的な誤りな
どがあると実行できないため、初心者にはなかなか利用しにくい面がある。
コンパイラ型言語の特徴をまとめると以下のようになる.
• プログラムを全て機械語に翻訳して実行式のプログラムにして実行する
• 長所:プログラムの実行速度が速い
• 短所:文法,論理的にも完全なプログラムが必要
4.3
コンパイラの構造
コンパイラは論理的に見るとフェーズ (phase) と呼ばれる幾つかの部分システムに分け
られる.それを次に示す.
18
4.4. Yacc と Lex
エディタ
メモリ
実行
コンパイラ
オブジェクト
プログラム
リンカ
実行形式
プログラム
ライブラリ
図 4.2: C,FORTRAN,pascal など多くのプログラム言語処理方式
• 字句解析系 (laxical analyzer)
プログラムを文法上の基本単位であるトークン (token) の列に変換する.トークン
は予約語,ラベル,識別子,特殊記号,数などである.
• 構文解析系 (syntax analyzer)
トークン列はこのフェーズでプログラム言語の文法 (構文) 規則によって,より抽象
度の高いレベルにまとめられて,解析木が構成される.
• 中間コード生成系 (intermediate code generator)
構文解析系の出力である解析木を入力として受け取り,出力としてアセンブリ (機
械) コードを抽象化した命令である中間コードの列を生成する.
• コード最適化 (code optimization)
中間コード列を入力として受け取り,より実行効率の良い,あるいは所有記憶量の
より小さい等価な中間コード列に変換する.
• コード生成系 (code generator)
中間コードから機械 (またはアセンブリ) コードへの変換を行う.このフェーズでは
効率よく計算を行うためのレジスタ割付け,命令コードの選択などが行われる.
4.4
Yacc と Lex
Yacc と Lex は,プログラミング言語のコンパイラやイランスレータを作るためのシス
テムである.字句解析部を生成する Lex,構文解析部を生成する Yacc は,一般にコンパ
19
第 4 章 コンパイラについて
イラを生成するためのコンパイラであるので,コンパイラ・コンパイラと呼ばれる.Lex
は正規表現,Yacc は BNF 法と呼ばれている記法に従って記述する.
• Lex 字句の定義から字句解析プログラム (C 言語) を自動生成する.
作成するプログラム lex.yy.c
• Yacc 文法の定義から構文解析プログラム (C 言語) を自動生成する.
生成するプログラム y.tab.c , y.tab.y
20
第5章
Yacc,Lex による DBN2PS コン
パイラの実現
Yacc,Lex を使用し DBN プログラムを PostScript プログラムへ出力するコンパイラを作
成した.Yacc のプログラムは約 600 行,Lex のプログラムは約 40 行である.プログラム
は付録 A に掲載しておく.
5.1
DBN と PostScript の比較
DBN アプリケーションの表示結果を図 5.1,作成した DBN2PS コンパイラに DBN プ
ログラムを入力し実行した際の表示結果を図 5.2 に示す.
入力した DBN プログラムを以下に示す.
Paper 0
Repeat A 0 100
{
Pen A
Line 100 0 0 A
Line 0 0 A 100
}
DBN2PS コンパイラが出力した PostScript プログラムを以下に示す.
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox:0 0 100 100
newpath
0 0 moveto
21
第 5 章 Yacc,Lex による DBN2PS コンパイラの実現
0 100 lineto
100 100 lineto
100 0 lineto
closepath
1.0 setgray fill
newpath
/A -1 def
101{
/A A 1 add def
/pen 100 A sub 100 div def
newpath
100 0 moveto
0 A lineto
pen setgray
stroke
newpath
0 0 moveto
A 100 lineto
pen setgray
stroke
} repeat
図 5.1: Desin By Numbers
図 5.2: PostScript
図 5.1 と図 5.2 の図形を比較すると,DBN による出力図形はビットマップデータである
ため拡大するとジャギが発生する.一方,PostScript はベクトルデータのため,拡大して
もジャギが発生しない.これにより,紙等の高解像度の触媒に出力しても,作成した図形
を美しく再現することができる.
22
5.2. DBN プログラムの複雑なとき
5.1.1
カラーの場合
DBN プログラムがカラーを用いた場合の表示結果を 5.3 に示す.作成したコンパイラ
にカラーを用いた DBN プログラムを入力し,実行した際の表示結果を図 5.4 に示す.こ
のときの DBN プログラムと DBN2PS コンパイラが出力した PostScript プログラムは付
録 A に掲載しておく.
図 5.3: DBN
図 5.4: PostScript
カラーの時も同様に,DBN と PostScript の表示結果を比較すると,PostScript により
作成した図形は紙等の高解像度の媒体に出力しても美しく再現することができる.
5.2
DBN プログラムの複雑なとき
DBN プログラムが以下に示すように複雑だった場合のときを示す.
Command Rectangle L B R T
{
Line L B R B
Line R B R T
Line R T L T
Line L T L B
}
Command Person PH PV
{
Rectangle (PH-4) PV PH (PV+2)
Rectangle (PH+4) PV PH (PV+2)
Rectangle (PH-3) (PV+2) PH (PV+8)
Rectangle (PH+3) (PV+2) PH (PV+8)
23
第 5 章 Yacc,Lex による DBN2PS コンパイラの実現
Rectangle (PH-5) (PV+6) (PH-3) (PV+14)
Rectangle (PH+5) (PV+6) (PH+3) (PV+14)
Rectangle (PH-2) (PV+14) (PH+2) (PV+19)
}
Command Pyramid U V
{
Person U V
Person (U+16) V
Person (U-16) V
Person (U-8) (V+14)
Person (U+8) (V+14)
Person U (V+28)
}
Paper 0
Pen 100
Pyramid 50 16
DBN プログラムを入力し作成したコンパイラが出力した PostScript プログラムを以下
に示す.
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox:0 0 100 100
newpath
/Rectangle {
/L exch def
/B exch def
/R exch def
/T exch def
newpath
L B moveto
R B lineto
pen setgray
stroke
newpath
R B moveto
R T lineto
pen setgray
stroke
newpath
R T moveto
L T lineto
pen setgray
stroke
24
5.2. DBN プログラムの複雑なとき
newpath
L T moveto
L B lineto
pen setgray
stroke
} def
newpath
/Person {
/PH exch def
/PV exch def
PV 2 add PH PV PH 4 sub Rectangle
PV 2 add PH PV PH 4 add Rectangle
PV 8 add PH PV 2 add PH 3 sub Rectangle
PV 8 add PH PV 2 add PH 3 add Rectangle
PV 14 add PH 3 sub PV 6 add PH 5 sub Rectangle
PV 14 add PH 3 add PV 6 add PH 5 add Rectangle
PV 19 add PH 2 add PV 14 add PH 2 sub Rectangle
} def
newpath
/Pyramid {
/U exch def
/V exch def
V U Person
V U 16 add Person
V U 16 sub Person
V 14 add U 8 sub Person
V 14 add U 8 add Person
V 28 add U Person
} def
25
第 5 章 Yacc,Lex による DBN2PS コンパイラの実現
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox:0 0 100 100
newpath
0 0 moveto
0 100 lineto
100 100 lineto
100 0 lineto
closepath
1.0 setgray fill
/pen 0.0 def
16 50 Pyramid
DBN アプリケーションの表示結果を図 5.5 に示す.PostScript プログラムが出力したグ
ラフィックを図 5.6 に示す.
図 5.5: DBN
図 5.6: PostScript
図 5.5 と図 5.6 を比較すると,複雑なプログラムであった場合も,作成したコンパイラ
を用いることにより,同じように再現することができる.
26
5.3. Illustrator による加工
5.3
Illustrator による加工
DBN2PS コンパイラが出力する PostScript プログラムのため,Illustrator 等によって開
くことができ,加工することが可能となる.
5.3.1
Illustrator により加工できる利点
• 拡大・縮小しても画像が変わらない
• パス・オブジェクトで構成されているため,編集や修正ができる.
• ビットマップ画像に変換することができる.
図 5.7 に Illustrator によって加工した例を示す.これは図 5.2 に表示した PostScript の
図形に対して,移動,回転,拡大操作を施したものである.
図 5.7: Illustrator を用いて加工した図形
27
第6章
おわりに
本研究では,DBN プログラムをベクトルデータを扱う PostScript に変換するコンパイラ
を作成した.作成したコンパイラは,DBN コマンドの Paper,Pen,Line,Set,Repeat,
Set[],Same?,NotSame?,Smaller?,NotSmaller?,Command コマンド,計算・コメント
が PostScript プログラムへ変換できる.そして,DBN プログラムの表示図形を PostScript
として出力することができるため,Illustrator 等のアプリケーションにおいて,手作業に
よる加工が可能となる.
29
謝 辞
本研究を行うにあたり,終始懇切なるご指導を頂きました中部大学工学部 藤吉弘亘 助
教授に謹んで深謝します.
最後に,本研究で用いたプログラムの開発において協力して頂いた藤吉研究室の皆様に
感謝致します.
31
参考文献
[1] John Maeda: “ Design By Numbers” http://dbn.media.mit/edu/
[2] Adobe Systems,桑沢 清志 (訳): “PostScript リファレンスマニュアル 第3版”
[3] “PostScript 詳細解説”
[4] John R.Levine, Tony Mason, Doug Brown, 村上 列 (訳): “lex & yacc”
[5] “情報工学実験 1 2”
[6] “PostScript 実習マニュアル” http://www.summa.jp/tutorial/pdf/psman.pdf
33
付 録A
A.1
プログラム
DBN プログラム
図 5.3 に表示した DBN プログラムを掲載する.
paper 0 0 50
repeat A 0 20
{
pen 0
line 0 (74+A) 100 (6+A)
line 0 (6+A) 100 (74+A)
}
repeat B 0 7
{
pen 100 0 0
line 0 (77+B) 50 (43+B)
line 0 (8+B) 50 (43+B)
line 50 (50+B) 100 (16+B)
line 50 (50+B) 100 (84+B)
}
repeat C 0 100
{
pen 0
line 40 C 60 C
line C 40 C 60
}
repeat D 0 100
{
pen 100 0 0
line 44 D 56 D
line D 44 D 56
35
付 録A
プログラム
}
repeat E 0 16
{
pen 100
line 0 E 100 E
line 0 (100-E) 100 (100-E)
}
A.2
PostScript プログラム
図 5.4 に表示した PostScript プログラムを掲載する.
%!PS-Adobe-3.0
%%BoundingBox:0 0 100 100
newpath
0 0 moveto
0 100 lineto
100 100 lineto
100 0 lineto
closepath
0.0 0.0 0.5 setrgbcolor fill
newpath
/A -1 def
21{
/A A 1 add def
/pen 1.0 def
newpath
0 74 A add moveto
100 6 A add lineto
pen setgray
stroke
newpath
0 6 A add moveto
100 74 A add lineto
pen setgray
stroke
} repeat
newpath
36
A.2. PostScript プログラム
/B -1 def
8{
/B B 1 add def
/pencolorR 1.0 def
/pencolorG 0.0 def
/pencolorB 0.0 def
newpath
0 77 B add moveto
50 43 B add lineto
pencolorR pencolorG pencolorB setrgbcolor
stroke
newpath
0 8 B add moveto
50 43 B add lineto
pencolorR pencolorG pencolorB setrgbcolor
stroke
newpath
50 50 B add moveto
100 16 B add lineto
pencolorR pencolorG pencolorB setrgbcolor
stroke
newpath
50 50 B add moveto
100 84 B add lineto
pencolorR pencolorG pencolorB setrgbcolor
stroke
} repeat
newpath
/C -1 def
101{
/C C 1 add def
/pen 1.0 def
newpath
40 C moveto
60 C lineto
pen setgray
stroke
37
付 録A
プログラム
newpath
C 40 moveto
C 60 lineto
pen setgray
stroke
} repeat
newpath
/D -1 def
101{
/D D 1 add def
/pencolorR 1.0 def
/pencolorG 0.0 def
/pencolorB 0.0 def
newpath
44 D moveto
56 D lineto
pencolorR pencolorG pencolorB setrgbcolor
stroke
newpath
D 44 moveto
D 56 lineto
pencolorR pencolorG pencolorB setrgbcolor
stroke
} repeat
newpath
/E -1 def
17{
/E E 1 add def
/pen 0.0 def
newpath
0 E moveto
100 E lineto
pen setgray
stroke
newpath
38
A.3. Yacc プログラム
0 100 E sub moveto
100 100 E sub lineto
pen setgray
stroke
} repeat
A.3
Yacc プログラム
今回作成した Yacc のプログラムを掲載する.
39
付 録A
プログラム
// Lex で定義した字句を宣言
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%token
%left
%left
NL
PAPER
LINE
NUMBER
PEN
QUIT
WORD
SET
REPEAT
LKAKKO
RKAKKO
LPOP
RPOP
LKA
RKA
SAME
NOTSAME
SMALLER
NOTSMALLER
COMMAND
KOME
ADDOP SUBOP
MULOP DIVOP
%%
s
: list
;
list
:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40
/* empty */
list NL
list paper NL { printf(" \n"); }
list pen NL { printf(" \n"); count=0;}
list penc NL { printf(" \n"); count=0;}
list line NL { printf(" \n"); count=0;}
list set
NL { printf(" \n"); count=0;}
list setdot NL { printf(" \n"); count=0;}
list repeat NL {printf(" \n"); }
list l NL {printf(" \n"); }
list r NL {printf(" \n"); }
list same NL {printf(" \n"); count=0;}
list notsame NL {printf(" \n"); count=0;}
list smaller NL {printf(" \n"); count=0; }
list notsmaller NL {printf(" \n"); count=0;}
list command NL { printf(" \n"); count=0;}
A.3. Yacc プログラム
| list command2 NL { printf(" \n"); count=0;}
| list kome NL { printf(" \n"); }
| quit NL
;
// Paper コマンド (グレーと カラー)
// Paper 数字 の規則を構成
paper
: PAPER expr
{
printf("%%!PS-Adobe-3.0 EPSF-3.0 \n");
printf("%%%BoundingBox:0 0 100 100 \n");
printf("newpath \n");
printf("0 0 moveto \n");
printf("0 100 lineto \n");
printf("100 100 lineto \n");
printf("100 0 lineto \n");
printf("closepath \n");
printf("%2.1f setgray fill \n",(100 - (double)$2) / 100); }
| PAPER expr expr expr
{
printf("%%!PS-Adobe-3.0 \n");
printf("%%%BoundingBox:0 0 100 100 \n");
printf("newpath \n");
printf("0 0 moveto \n");
printf("0 100 lineto \n");
printf("100 100 lineto \n");
printf("100 0 lineto \n");
printf("closepath \n");
printf("%2.1f %2.1f %2.1f setrgbcolor fill \n",
(double)$2/100, (double)$3/100, (double)$4/100 ); }
;
// Pen コマンド (グレー)
// Pen 数字,Pen 変数,Pen 式,の規則を構成
pen
: PEN expr
{ printf("/pen %2.1f def \n", (100 - (double)$2) / 100);
line = 0 ; }
| PEN word
{ printf("/pen 100 %s sub 100 div def \n", $2);
line = 0; }
| PEN siki
{ printf("/pen 100 %s sub 100 div def \n", sikiname[$2]);
line = 0; }
;
41
付 録A
プログラム
// Pen コマンド (カラー)
// Pen 数字 変数 式 などの様々な規則を構成
// line = 1 を設定 (線を引くときカラーと設定するため)
penc
: PEN penc1 penc2 penc3
{ line = 1; }
;
penc1
: expr
{ printf("/pencolorR
| word
{ printf("/pencolorR
| siki
{ printf("/pencolorR
;
: expr
{ printf("/pencolorG
| word
{ printf("/pnecolorG
| siki
{ printf("/pencolorG
;
: expr
{ printf("/pencolorB
| word
{ printf("/pencolorB
| siki
{ printf("/pencolorB
;
penc2
penc3
%2.1f def \n", (double)$1/100); }
%s 100 div def \n", $1); }
%s 100 div def \n", sikiname[$1]); }
%2.1f def \n", (double)$1/100); }
%s 100 div def \n", $1); }
%s 100 div def \n", sikiname[$1]); }
%2.1f def \n", (double)$1/100); }
%s 100 div def \n", $1); }
%s 100 div def \n", sikiname[$1]); }
// Line コマンド
// Line 数字 数字 変数 式など様々な規則を構成
// line = 0 のときはグレー,line = 1 のときはカラー
line
42
: LINE line1
{ if(line == 0){
printf("pen setgray \n");
printf("stroke \n");
line = 0;
} else if(line == 1){
printf("pencolorR pencolorG pencolorB setrgbcolor \n");
printf("stroke \n");
line = 1;
}
}
;
A.3. Yacc プログラム
line1
line2
: line2 expr expr
{ printf("%d %d
| line2 expr word
{ printf("%d %s
| line2 expr siki
{ printf("%d %s
| line2 word expr
{ printf("%s %d
| line2 word word
{ printf("%s %s
| line2 word siki
{ printf("%s %s
| line2 siki expr
{ printf("%s %d
| line2 siki word
{ printf("%s %s
| line2 siki siki
{ printf("%s %s
;
lineto \n", $2,$3); }
lineto \n", $2,$3); }
lineto \n", $2,sikiname[$3]); }
lineto \n", $2,$3); }
lineto \n", $2,$3); }
lineto \n", $2,sikiname[$3]); }
lineto \n", sikiname[$2],$3); }
lineto \n", sikiname[$2],$3); }
lineto \n", sikiname[$2],sikiname[$3]); }
: expr expr
{ printf("newpath \n");
printf("%d %d moveto \n",
| expr word
{ printf("newpath \n");
printf("%d %s moveto \n",
| expr siki
{ printf("newpath \n");
printf("%d %s moveto \n",
| word expr
{ printf("newpath \n");
printf("%s %d moveto \n",
| word word
{ printf("newpath \n");
printf("%s %s moveto \n",
| word siki
{ printf("newpath \n");
printf("%s %s moveto \n",
| siki expr
{ printf("newpath \n");
printf("%s %d moveto \n",
| siki word
{ printf("newpath \n");
printf("%s %s moveto \n",
| siki siki
{ printf("newpath \n");
printf("%s %s moveto \n",
;
$1,$2); }
$1,$2); }
$1,sikiname[$2]); }
$1,$2); }
$1,$2); }
$1,sikiname[$2]); }
sikiname[$1],$2); }
sikiname[$1],$2); }
sikiname[$1],sikiname[$2]); }
43
付 録A
プログラム
// Set コマンド
// Set 変数 (数字,変数,式) の規則を構成
set
: SET word expr
{ printf("/%s %d def \n", $2, $3); }
| SET word word
{ printf("/%s %s def \n", $2, $3); }
| SET word siki
{ printf("/%s %s def \n", $2, sikiname[$3]); }
;
// Set[] コマンド
// Set [ 数字 数字 ] 色 などの規則を構成
setdot
: setdot1 LKA setdot2 RKA setdot3
{ printf(" stroke \n"); }
setdot3
: expr
{ printf(" closepath \n");
printf(" %2.1f setgray \n",(100 - (double)$1) / 100); }
| word
{ printf(" closepath \n");
printf(" /setdotpen 100 %s sub 100 div def \n", $1);
printf(" setdotpen setgray \n"); }
| siki
{ printf(" closepath \n");
printf(" /setdotpen 100 %s sub 100 div def \n", sikiname[$1]);
printf(" setdotpen setgray \n"); }
| setdotco
{ printf(" pencolorR pencolorG pencolorB setrgbcolor \n"); }
;
// Set[] コマンドのカラー時の色の設定
// 色部分を数字,変数,式などの規則を構成
setdotco : setred setgreen setblue
;
setred
44
: expr
{ printf(" closepath
printf("/pencolorR
| word
{ printf(" closepath
printf("/pencolorR
| siki
{ printf(" closepath
printf("/pencolorR
;
\n");
%2.1f def \n", (double)$1/100); }
\n");
%s 100 div def \n", $1); }
\n");
%s 100 div def \n", sikiname[$1]); }
A.3. Yacc プログラム
setgreen : expr
{ printf("/pencolorG %2.1f def \n", (double)$1/100); }
| word
{ printf("/pencolorG %s 100 div def \n", $1); }
| siki
{ printf("/pencolorG %s 100 div def \n", sikiname[$1]); }
;
setblue
: expr
{ printf("/pencolorB %2.1f def \n", (double)$1/100); }
| word
{ printf("/pencolorB %s 100 div def \n", $1); }
| siki
{ printf("/pencolorB %s 100 div def \n", sikiname[$1]); }
;
setdot2
: expr expr
{ printf("%d
| expr word
{ printf("%d
| expr siki
{ printf("%d
| word expr
{ printf("%s
| word word
{ printf("%s
| word siki
{ printf("%s
| siki expr
{ printf("%s
| siki word
{ printf("%s
| siki siki
{ printf("%s
setdot1
%d 0.5 0 360 arc
\n", $1,$2); }
%s 0.5 0 360 arc \n", $1,$2); }
%s 0.5 0 360 arc \n", $1,sikiname[$2]); }
%d 0.5 0 360 arc \n", $1,$2); }
%s 0.5 0 360 arc \n", $1,$2); }
%s 0.5 0 360 arc \n", $1,sikiname[$2]); }
%s 0.5 0 360 arc \n", sikiname[$1],$2); }
%s 0.5 0 360 arc \n", sikiname[$1],$2); }
%s 0.5 0 360 arc \n", sikiname[$1],sikiname[$2]); }
: SET
{ printf(" newpaht \n"); }
;
// Repeat コマンド
// Repeat 変数 数字 の規則を構成
repeat
: REPEAT word expr expr
{
kakkocount += 1;
printf(" newpath \n");
printf(" /%s %d def \n", $2, $3-1);
45
付 録A
プログラム
printf(" %d{ \n", 1+$4-$3);
printf(" /%s %s 1 add def \n", $2, $2);
}
;
// 左括弧 {
l
: LKAKKO
;
// 右括弧 }
// kakkocount の値によって出力を変更
r
: RKAKKO
{
if (kakkocount >= 1 && kakkocount < 10 ){
printf(" } repeat \n");
kakkocount -= 1;
}
if(kakkocount >= 10 && kakkocount < 100){
printf(" } if \n");
kakkocount -= 10;
}
if(kakkocount >= 100){
printf(" } def \n");
kakkocount -= 100;
}
}
;
// Same?コマンド
// Same? 数字 変数などの規則を構成
// NotSame? Smaler? NotSmaller も同様
same
same1
46
: SAME same1
{ kakkocount += 10;
;
: expr expr
{ printf(" %d %d eq
| expr word
{ printf(" %d %s eq
| expr siki
{ printf(" %d %s eq
| word expr
{ printf(" %s %d eq
| word word
{ printf(" %s %s eq
| word siki
}
{ \n", $1,$2); }
{ \n", $1,$2); }
{ \n", $1,sikiname[$2]); }
{ \n", $1,$2); }
{ \n", $1,$2); }
A.3. Yacc プログラム
{ printf("
| siki expr
{ printf("
| siki word
{ printf("
| siki siki
{ printf("
;
%s %s eq { \n", $1,sikiname[$2]); }
%s %d eq { \n", sikiname[$1],$2); }
%s %s eq { \n", sikiname[$1],$2); }
%s %s eq { \n", sikiname[$1],sikiname[$2]); }
// NotSame?コマンド
notsame
: NOTSAME notsame1
{ kakkocount += 10;
notsame1 : expr expr
{ printf(" %d %d ne
| expr word
{ printf(" %d %s ne
| expr siki
{ printf(" %d %s ne
| word expr
{ printf(" %s %d ne
| word word
{ printf(" %s %s ne
| word siki
{ printf(" %s %s ne
| siki expr
{ printf(" %s %d ne
| siki word
{ printf(" %s %s ne
| siki siki
{ printf(" %s %s ne
;
}
{ \n", $1,$2); }
{ \n", $1,$2); }
{ \n", $1,sikiname[$2]); }
{ \n", $1,$2); }
{ \n", $1,$2); }
{ \n", $1,sikiname[$2]); }
{ \n", sikiname[$1],$2); }
{ \n", sikiname[$1],$2); }
{ \n", sikiname[$1],sikiname[$2]); }
// Smaller?コマンド
smaller
: SMALLER smaller1
{ kakkocount += 10;
;
smaller1 : expr expr
{ printf(" %d %d lt
| expr word
{ printf(" %d %s lt
| expr siki
{ printf(" %d %s lt
| word expr
{ printf(" %s %d lt
| word word
{ printf(" %s %s lt
}
{ \n", $1,$2); }
{ \n", $1,$2); }
{ \n", $1,sikiname[$2]); }
{ \n", $1,$2); }
{ \n", $1,$2); }
47
付 録A
プログラム
| word siki
{ printf("
| siki expr
{ printf("
| siki word
{ printf("
| siki siki
{ printf("
;
%s %s lt { \n", $1,sikiname[$2]); }
%s %d lt { \n", sikiname[$1],$2); }
%s %s lt { \n", sikiname[$1],$2); }
%s %s lt { \n", sikiname[$1],sikiname[$2]); }
// NotSmaller? コマンド
notsmaller
: NOTSMALLER notsmaller1
{ kakkocount += 10; }
;
notsmaller1 : expr expr
{ printf(" %d %d gt { \n",
| expr word
{ printf(" %d %s gt { \n",
| expr siki
{ printf(" %d %s gt { \n",
| word expr
{ printf(" %s %d gt { \n",
| word word
{ printf(" %s %s gt { \n",
| word siki
{ printf(" %s %s gt { \n",
| siki expr
{ printf(" %s %d gt { \n",
| siki word
{ printf(" %s %s gt { \n",
| siki siki
{ printf(" %s %s gt { \n",
;
$1,$2); }
$1,$2); }
$1,sikiname[$2]); }
$1,$2); }
$1,$2); }
$1,sikiname[$2]); }
sikiname[$1],$2); }
sikiname[$1],$2); }
sikiname[$1],sikiname[$2]); }
// Commnad コマンド (定義時)
// Command 数字 変数 式など様々な規則を構成
command
comman5
48
:
|
|
|
|
;
COMMAND
COMMAND
COMMAND
COMMAND
COMMAND
comman1
comman1
comman1
comman1
comman1
comman2
comman2 comman3
comman2 comman3 comman4
comman2 comman3 comman4 comman5
: word
{ printf(" /%s exch def \n", $1); }
| expr
A.3. Yacc プログラム
comman4
comman3
comman2
comman1
{ printf(" /%d exch def \n",
| siki
{ printf(" /%s exch def \n",
;
: word
{ printf(" /%s exch def \n",
| expr
{ printf(" /%d exch def \n",
| siki
{ printf(" /%s exch def \n",
;
: word
{ printf(" /%s exch def \n",
| expr
{ printf(" /%d exch def \n",
| siki
{ printf(" /%s exch def \n",
;
: word
{ printf(" /%s exch def \n",
| expr
{ printf(" /%d exch def \n",
| siki
{ printf(" /%s exch def \n",
;
: word
{
printf(" newpath \n");
printf(" /%s { \n", $1);
kakkocount += 100; }
;
$1); }
sikiname[$1]); }
$1); }
$1); }
sikiname[$1]); }
$1); }
$1); }
sikiname[$1]); }
$1); }
$1); }
sikiname[$1]); }
// Commnad コマンド (実行時)
// 変数 数字 式 など様々な規則を構成
command2 : word co1
{ printf("%s \n",$1); }
;
co1
: word
{ printf("%s
| expr
{ printf("%d
| siki
{ printf("%s
| word co2
{ printf("%s
| expr co2
", $1); }
", $1); }
", sikiname[$1]); }
", $1); }
49
付 録A
co2
co3
co4
co5
50
プログラム
{ printf("%d
| siki co2
{ printf("%s
;
: word
{ printf("%s
| expr
{ printf("%d
| siki
{ printf("%s
| word co3
{ printf("%s
| expr co3
{ printf("%d
| siki co3
{ printf("%s
;
: word
{ printf("%s
| expr
{ printf("%d
| siki
{ printf("%s
| word co4
{ printf("%s
| expr co4
{ printf("%d
| siki co4
{ printf("%s
;
: word
{ printf("%s
| expr
{ printf("%d
| siki
{ printf("%s
| word co5
{ printf("%s
| expr co5
{ printf("%d
| siki co5
{ printf("%s
;
: word
{ printf("%s
| expr
{ printf("%d
| siki
", $1); }
", sikiname[$1]); }
", $1); }
", $1); }
", sikiname[$1]); }
", $1); }
", $1); }
", sikiname[$1]); }
", $1); }
", $1); }
", sikiname[$1]); }
", $1); }
", $1); }
", sikiname[$1]); }
", $1); }
", $1); }
", sikiname[$1]); }
", $1); }
", $1); }
", sikiname[$1]); }
", $1); }
", $1); }
A.3. Yacc プログラム
{ printf("%s
| word co6
{ printf("%s
| expr co6
{ printf("%d
| siki co6
{ printf("%s
;
: word
{ printf("%s
| expr
{ printf("%d
| siki
{ printf("%s
| word co7
{ printf("%s
| expr co7
{ printf("%d
| siki co7
{ printf("%s
;
: word
{ printf("%s
| expr
{ printf("%d
| siki
{ printf("%s
;
co6
co7
kome
", sikiname[$1]); }
", $1); }
", $1); }
", sikiname[$1]); }
", $1); }
", $1); }
", sikiname[$1]); }
", $1); }
", $1); }
", sikiname[$1]); }
", $1); }
", $1); }
", sikiname[$1]); }
: KOME word
;
// 数字のみ計算
expr
:
|
|
|
|
|
;
expr ADDOP expr { $$ = $1
expr SUBOP expr { $$ = $1
expr MULOP expr { $$ = $1
expr DIVOP expr { $$ = $1
LPOP expr RPOP { $$ = $2;
NUMBER { $$ = $1; }
+
*
/
}
$3;
$3;
$3;
$3;
}
}
}
}
// 変数の入った計算
// ( 数字 + 変数 ) など様々な規則を構成
siki
:
LPOP expr ADDOP word RPOP
{ sprintf(sikiname[count], "%d %s add", $2,$4);
$$ = count;
51
付 録A
プログラム
|
|
|
|
|
|
|
|
|
|
52
count++;
}
LPOP word ADDOP expr RPOP
{ sprintf(sikiname[count],
$$ = count;
count++;
}
LPOP word ADDOP word RPOP
{ sprintf(sikiname[count],
$$ = count;
count++;
}
LPOP expr SUBOP word RPOP
{ sprintf(sikiname[count],
$$ = count;
count++;
}
LPOP word SUBOP expr RPOP
{ sprintf(sikiname[count],
$$ = count;
count++;
}
LPOP word SUBOP word RPOP
{ sprintf(sikiname[count],
$$ = count;
count++;
}
LPOP expr MULOP word RPOP
{ sprintf(sikiname[count],
$$ = count;
count++;
}
LPOP word MULOP expr RPOP
{ sprintf(sikiname[count],
$$ = count;
count++;
}
LPOP word MULOP word RPOP
{ sprintf(sikiname[count],
$$ = count;
count++;
}
LPOP expr DIVOP word RPOP
{ sprintf(sikiname[count],
$$ = count;
count++;
}
LPOP word DIVOP expr RPOP
"%s %d add", $2,$4);
"%s %s add", $2,$4);
"%d %s sub", $2,$4);
"%s %d sub", $2,$4);
"%s %s sub", $2,$4);
"%d %s mul", $2,$4);
"%s %d mul", $2,$4);
"%s %s mul", $2,$4);
"%d %s div", $2,$4);
A.3. Yacc プログラム
{ sprintf(sikiname[count], "%s %d div", $2,$4);
$$ = count;
count++;
}
| LPOP word DIVOP word RPOP
{ sprintf(sikiname[count], "%s %s div", $2,$4);
$$ = count;
count++;
}
;
// 変数など (アルファベット 26 文字)
word
: WORD { $$ = $1; }
;
// 数字 (0 から 9 を組み合わせた数字)
quit
: QUIT
{ printf("showpage \n"); }
;
%%
#include "lex.yy.c"
int line=0, count=0, kakkocount =0;
char sikiname[100][100];
yyerror(char *s)
{
fprintf(stderr, "%s\n", s);
}
main()
{
return yyparse();
}
53
付 録A
プログラム
A.4
Lex プログラム
今回作成した Lex のプログラムを掲載する.
54
A.4. Lex プログラム
%%
[ \t]+
;
%{
// 字句を定義 (DBN コマンド,括弧,数字,アルファベット,記号など)
%}
Paper
paper
Line
line
Pen
pen
Quit
Set
set
Repeat
repeat
"{"
"}"
"+"
"-"
"*"
"/"
"("
")"
"["
"]"
Same"?"
same"?"
NotSame"?"
notsame"?"
Smaller"?"
samller"?"
NotSmaller"?"
notsmaller"?"
Command
commnad
"//"
|
return(PAPER);
|
return(LINE);
|
return(PEN);
return(QUIT);
|
return(SET);
|
return(REPEAT);
return(LKAKKO);
return(RKAKKO);
return(ADDOP);
return(SUBOP);
return(MULOP);
return(DIVOP);
return(LPOP);
return(RPOP);
return(LKA);
return(RKA);
|
return(SAME);
|
return(NOTSAME);
|
return(SMALLER);
|
return(NOTSMALLER);
|
return(COMMAND);
return(KOME);
[0-9]+
{ yylval=atoi(yytext); return(NUMBER); }
[a-zA-Z]+ { yylval=strdup(yytext); return(WORD); }
\n
return(NL);
%%
55
PostScript を出力する DBN コンパイラの作成
田中 佑典
(中部大学工学部情報工学科)
2004 年 3 月