言語処理系の生成系MYLANGによる
プリティプリンタの作成
(昭和62年11月30日 原稿受付)
情報工学科(大学院)前田博基
山之上 卓 安 在 弘 幸
Generation of a Pretty Printer
by the Language Processor Generator MYLANG
by Hiroki MAEDA Takashi YAMANOUE Hiroyuki ANZAI
Abstract
The language processor generator MYLANG, a tool to generate compilers automatically, is based on automata theory and attribute grammaL EARTF(Extended Attributed Regular Transla.
tion Form), a notation to describe syntax and semantics of a target programming language, is the in.
put specification to the MYLANG system. The EARTF consists of three kinds of symbols, namely
:the terminal symbol to recognize input characters, the nonterlninal symbol, and the action symbol to assign a value to an attribute variable, to evaluate a given condition, and to call an action routine・
As an application of MYLANG, we generate a pretty printer. It analyzes a source program of
the programming language C, and converts it into a better form to make the structure of the prog−
ram clear. Using the pretty printer, the programmer does not have to bother himself of the prog−
ram format. We will also show a debugging tool on MYLANG which aided the programming of
the pretty printer.
付加したものであり,意味規則は構文規則とは分けて記
1.まえがき
述される。MYLANGでは,属性と意味規則はRTF上 言語処理系の生成系MYLANGは,オートマトン理 に直接に記述される。このように, RTFに対し属性と 論と属性文法を用いてコンパイラの自動生成を行うシス 意味規則を付加したものを特に属性付正規翻訳記法
テムである。 (Attributed Regular Translation Form. ARTF)と呼ぶ 対象とするプログラミング言語の構文記述には,正規 ことがある』)2)3)すなわち,Knuthの属性文法の記法 翻訳記法(Regular Translation Form, RTF)が用いられ は属性文法定義であるのに対して,ここで与えるる。これは,拡張BNFに活動記号を付加したものであ ARTFは一種の属性文法スキームである。属性文法ス る。RTFはMYLANGに入力されてオートマトンに変 キームは属性文法定義に構文解析・意味解析の仕組みま 換される。 でも含ませた記法である。
属性文法は,D. E. Knuthによって与えられた記法で 現在ではさらに, ARTFに対してRAM(Random
あり,・プログラミング言語の構文・意味記述に用いられ Access Memory)の操作を行う関数と定数マクロの機能 る。一般に属性文法は文脈自由文法に属性と意味規則を を加えた版がある。この場合にも特に拡張属性付正規翻EARTF 制御部は1つ以上のEARTF定義式からなり,実行 ↓ の流れの制御を記述する。各々のEARTF定義式にお
しら↓ いて,頭部はそのEARTF定義式を識別する非終端記
属性付構文指示翻訳系号であり,本体は各種の定義記号と超記号で動作を定義
図1.1 MYLANG したものである。
活動部は活動ルーチンの動作を記述するためのもので,
訳記法(Extended Attributed Regular Translation Form, 手続き型言語によって記述される。活動ルーチンは,そ
EARTF)と呼ぶことがある:)(図1.1) の名前を持つ活動記号によって呼び出され実行される。
我々は言語処理系の生成系MYLANGによって, C 2.2.定義記号
言語を対象としたプリティプリンタを作成した。このプ EARTFを形成する基本単位としての定義記号は,終 ログラムは約2日で作成できた。また同時に, 端記号,非終端記号,活動記号の3つである。
MYLANGの開発環境を改善するためにデバッガの開 終端記号は2つの一重引用符「 」で前後を囲まれた 発を進めている。 ものであり,入力文字の認識に用いられる。これは汎用 2章ではEARTFについて説明する。3章ではプリ のプログラミング言語にはない概念であるが,言語処理
ティプリンタについて報告する。4章ではMYLANG 系そのものを処理対象とする場合には不可欠なものであ による言語処理系の開発のための支援ッールであるデ る。これは終端記号と入力文字とのマッチングによって
バッガについて報告する。 語彙解析,構文解析を行うために必要である。. 非終端記号は不等号「〈」と「〉」で囲まれたものであ
2.拡張属性付正規翻訳記法(EARTF) 一
る。ある名前の非終端記号は,プログラムの中で,
拡張属性付正規翻訳記法(Extended Attributed Regu− EARTF定義式の頭部に必ず1度だけ現れ,その右辺の
lar Translation Form, EARTF)は,言語処理系の生成 定義式本体でその非終端記号に対する動作が定義される。系MYLANGが生成しようとする目的言語の構文と意 定義式本体の中に現れる非終端記号は他の定義式で必ず 味を記述するための記法である。この記法に基づいて書 定義されている。すなわち,その非終端記号は必ず同一 かれた記述をEARTFプログラムと呼ぶ。 MYLANG プログラムの制御部で定義されているか,またはインク はこのEARTFプログラムを読み取って目的の言語の ルードされるサブモジュールで定義されている。
処理系を生成する。ここでは,このEARTFプログラ EARTFにおける非終端記号は手続き型プログラミング ムについて述べる。 言語のサブルーチンに似ている。EARTFプログラミン 2.1.EARTFプログラム グで最初に現れる非終端記号は開始記号であり,
EARTFプログラムは,図2.1に示すように,制御 EARTFプログラムの実行はここから開始される。
部と活動部からなる。 活動記号は代入,基本入出力,条件判断,RAMの操
作などを行うためのものであり,角括弧「[」と「]」で/*?、、,1,1,、r/ .,,,。,プログラム名 囲まれる。 EARTF定義式本体に現れた活動記号は,同
/*?,tf 一プログラムの活動部で定義されているか,またはシス
$array[10]; ◆◆‥‥配列,定数の宣言 制御部
輪耐201 テムにはじめから備わっている。
〈・lal・〉=;1漂1;;;1(1:=0)] __EARTF定義式 また,$から始まる文字列は配列名を表し,@はその
くn°ntll1∵……: 次の文字がその文字のASCIIコードを表していること
灯llename: ‥・・‥サブモジュール名
?,nd*/ を示す。すなわち,@0は48と等価である。
::;lll;ぷ:::::二∴㌶翼㌶鷲r㌶
連接を表す ・ (省略される),閉包を表す * ,並列を 図2.1 MYLANGプログラム 表す + ,選択可を表す / があり,結合の強さは, *
Φ.<V.,。,Φ《wsC.ワ).; 述することは容易である。
lil:1:::;:lllll:::;:;::::;:ll二ll:::1:;:1::: この章では・EARTFプ・グラム1・よるC言言吾プリ
・F・・<V・+ ( Φり ; ティプリンタの記述とその実行例について述べる。
<い=…; @ 3.1.プログラムの説明
.s》 <v・ ,・, ・E・ ・ws( ・ !)・ 図3.1は, C言語を対象としたプリティプリンタを
二→○一→○一一〈〉一→○一→◎
記述したEARTFプログラムである。例として, if文の
甲○.= 処理部分を説明する・if文の処理は次に示すように蟻
式〈if>と〈else>で定義されている。
・E》 <T》 <us(,+ /)>
sぼ… 1芸驚㌫z∵
・‡・ F 〈elSe>= elSe 〈WS( elSe /)〉〈空白〉*
.T》 <F. <、s(,‡,/)》 (〈if>+〈ブロック〉+else〈1命令〉);
<F>
Sば… ㌫㌘ような 力さ 手
if(x<y){d=x;x=y;y=d;}
<い 定義式〈予約語〉の本体において非終端記号〈if>に実行
→ ○ が移ると,定義式〈if>が呼び出され,次のような動作が
( @Φ り 行われる。
①入力バッファの内容と文字列 ifが比較される。
図2・2欝ξ#7ζ漂㌍漂き 一致するならぱ・−C・f/)・が実行され文字 ぴ
が出力される。一致しないならば,定義式〈if>は失 と / , ・ , + の順である。また,並列接続されたな 敗する。
かで最後に実行させたいものには + の後に else を付け, ②〈ブランク〉*が実行される。〈ブランク〉はプラン 結合順位を変更させたい場合には丸括弧「(」と「)」で ク1つを認識する非終端記号であるから,ここでは 囲む。図2.2に算術式を逆ポーランド記法に変換する if と ( の間のブランクがすべて読み飛ばされる。
プログラムをEARTFで定義した例とそれに対応する
③〈丸括弧ブロック〉が実行され,オートマトンを示す。ただし,〈ws(s/)〉は文字列sを (x<y){d=x;x;y;y−d;}
出力する非終端記号であり,〈V>には変数名を認識して の部分が認識され,整形されて出力される。
その変数名を出力する処理が定義されているものとする。 ④入力バッファに改行がある場合は,〈復改〉が実行
される。3.プリティプリンタの作成 一
⑤else文が続くならば,〈else>が実行され,そこで プリティプリンタは,ソースプログラムを読み取って else以下の部分が処理される。
解析し,そのプログラムの構造がよくわかるように整形 以上の動作が実行され,上記のif文は次のような書
して出力する処理系である。この処理系はプログラムの 式で出力される。ネスティングの深さがわかるように,インデンテーショ if(X〈y){
ンや改正を行う。したがって,プログラマはプログラム d=x;x=y;y=d;
のスタイルを気にせずコーディングに集中することが可 }
能になる。 その他の定義記号を簡単に説明する。非終端記号のう
プリティプリンタの動作は構文解析を主とし,意味解 ち,サブモジュールstdioで定義されているものは次の
析の部分は少ない。ゆえにMYLANGの入力仕様記述 7つである。ここで, nameと chは入力作業領域で
であるEARTFプログラムで,プリティプリンタを記 あり,それぞれ文字列と文字が入る。
/、?p,etty./ 〈inistdio>…サブモジュールstdioの初期化
/淑?rtf
〈code(c/)〉…ASCIIコードcのキャラクタ認識
$ind[1]; /* インデント数 事/
㌫;留; 2叢‡2魏聖霞 1; (入力ポインタを進めない)
1;1811: ;1竺こ;:5.,_ド1; 〈WS(S/)〉…文字列Sの出力
・8・・<i,i武di。・<メイン・; 〈wlf>…復改コードの出力
くメイン》=t(【3ind]:;0)】<メイン1>x<メイン2>ポ<曹lf>;
<メイン1 F1?聾1:II:;了:1二∵晋1..空帥ち. 〈・1・〉 _・・m・のクリア(_・・m・← )
、メイン2.:冷裁181 1完?翼{1;;li)i ll竺把さ了〉<』たち. 〈con>・・Lnameに_chを連接
.丸括弧..・〜il:1:¶㌍蕊。1..・、・. 、・、・、、.、 (。。m。←。。m。・。h)
<丸括弧1>=〈丸括弧〉+〈1文字〉+〈文宇列〉 一 一 『
、プロ。ク..∵・ll:{!l!l;i?1;21>樫肇三;;;逸の文字・; 〈num>…数字 0 〜 9 を認識し,_chに入れる。
.プ。。ク1!:Cl!1;瓢:、;、1;lll;;fl膓ランン㌃(【$i d]/)〉); (_・h一数字)
1;讐纏()∵el…lf×インデント([$ind]/)〉) また,次はシステム既存の活動記号(標準活動記号)
<ブロック2>=<ブロック3>享[([$ind]:=[$ind]−1)]
(叩+el・…lf×インデント([$i・d】/)・) である。
〈W8( } /)×プランク〉累;
・<プ゜ツク3》
F:穫¶1::1旱;了1:二碧÷1、,),[?(o.1)] [tch(i/c)]…入力ポインタよりi文字先にある文字/を :浩まえ;鐸!e!°}!)〉[?(o=切)/ 属性cに返す。
<復改B>=<空白たち》 、
(・c。d,(・}/)×インデント(([$i,dH)!)・ [. gch(i/)]…入力ポインタをi文字進める。
+el8e〈インデント([3ind]/)〉);
・d
F;ll;1;8!:1;ll;N;ヲ;1;i6三1;; ;1・;(・獅L・<他の文字・)・; [. nametape($s/)]…_nameを配列$sに移す。
1え諺『〉,;。ll°1;、1,;:1!};;1;兇》ll°:£元冨膓ご㍊、; [. tapeout($s/)]…配列$sを出力する。
<while>= 曲Hピく冒s( ●hileソ)》<プランク>x〈丸括弧ブロック〉;
.if,.・if・.閥(・if・/)》<プランク,、.丸括弧プ。。ク・ 最後にいくつかの非終端記号を説明する。
〈復改〉/ <el8e>/ ;
・el・e・・
G・培;:・誇;∵:()1託皇了命令.)、 〈丸括弧〉…(…)を受理する。
〈丸括弧プ゜ツク‥
P㌻肥芦;〉㍍1:嘱21); 〈ブロック〉…ブロック{…}を受理する。<do>= do 〈w8Cdo /)〉〈空白〉窯くブロックB》
・.hil,・.,、C,hil,・/)〉〈丸括弧〉<プランク.、・;・..。℃;・/).; 〈他の文字〉…入力の1文字をそのまま出力する。
<ブロックB>= { くws℃{ /㍍<ブロック1>;
.、,it,h..,,,it,h・..,(,,.it,h・/). 〈1文字〉…文字定数 … を受理する。
〈プランク〉京く丸括弧〉〈空白〉享(ws( /)〉<s胃itchl》;
・8・it・hl・・ 奄奄戟垂撃戟G;lli≦Cd;ll;;芸念;x[([$1,d]:.[$i,d}1)] 〈文字列〉…文字列 … を受理する。
.c。。e。.、<c:二ζこぷliiild]/)》 } <胃8( } /) ; 〈8進数〉…3桁の数字を受理する。
:;芦;三:ヲ1㍍芸 ;彊;(<ヨ1…c8seDef>塞 ( 〈code(0}/)〉[?(0=1)0=1)】+<1文字》+else〈他の文字〉]、)/; 〈空白〉…スペース,タス復改を認識する。
<非c88eDef>=<空白>x(<ca5eOef》[?(0;1)]十else<非case>);
・ca8eD・f… c・se・・<d・f・・lt・・<c・d・(0}!)・; 〈ブランク〉…スペース,タブを認識する。
<非c88e>=[([$lnd]:=[$ind]+2)]<インデント([$ind]/)》
.非,。.。1..<F瀦lx,[1勢0;i$ln{;羅1 〈インデント(i/)〉…i段分頭を下げる。つまり,(4×
1二蒜∴;):.詰きR;.ぷ元認1.他の文字.; i)個のスペースを出力する。
<c8se>= case 《インデント([$ind]/)〉〈冒sCc8se /)〉;
・d・f・・lt・・ d・々lt ・インデ・ト([$i・d]/)〉<・・Cd・fault /)・; このようにEARTFでは対象とする言語の構文の記
〈1命令〉=[([$ind]:=[$ind]+1)]<wlf><インデント([$ind】ノ)》
,1行.={議蟹二甦く魏》㎡〉<7論ζ>li{i:㍑緩呈ldl−;;]、; 述がそのまま処理の流れになっているため,構文解析を
.講1喜∵ζ;,;(( ,;, 〈胃s( ;・/)〉 [?(0=1)] )/ ;0/c)] [([$chl]:;c)] [.tapeout($chl/)】[.8,hU/)]; 必要とするような処理を行う場合に,プログラムの記述
〈1文字〉= 《w5( /)〉〈1コード〉 〈賂( /)〉;
・文字列・・…・,8(…/)・(俳2重引用符〉<1・一ド・)パ が容易であり,またプログラムが明瞭である。
〈非2重引用符〉=( 別く卿s( /)〉[?(0=1)])/;
<P一ド>
P3;e<瑞;;挙.(;〈8進数〉+else〈他の文宇〉) 以上述べたプリティプリンタの記述とPascalで記述〈8進数〉;
撃戟G:,lll:1$ll;;;]<lll;pl:ll〜$3;1;]<1°n> したPascal向けのプリティプリンタと比較してみた。
〈コメント〉=/常 〈WS( /塞 /)〉
(・コ〃ト1・(・復改・・el,e・他の文字・))・; Pascal版はMYLANG版よりも機能が豊富であり,ま
くコメント1)=(,x/,〈冒s(,皐/,/)〉[?(0=1)])/;
〈復改〉=〈空白たち〉<インデント([$i・d]/)》; たプログラムのサイズを考慮して作成されていなかった
く空白たち〉=〈code(#NL/)〉
.空白,._1;c:ぱil{㍑llcl(1/)]<川f>+〈プランク〉〈code(#NL/)〉 )[.gch(1/)i∵ ため,単純な比較は意味がないがそれでも 1《;:六1あ1:lcglll;;;/1;i〜↓ch(l!;;・;[(i・・i−1)])、; MYLANGで書いた方が約10分の1の行数であり,か
・tdi・; なり簡潔に書けることがわかる。
?end寡/
3.2.実行結果
図3.1 プリティプリンタのプログラム 図3.2にプリティプリンタを通す前と後のCのプロ
グラムを示す。実行前の図(a)では,プログラムが左詰めで書かれているが,各行の左端のスペースは無視さ _、
れるから,左に詰めて書かなくてもよい.図(b)は実 4・MYLANGのデバッガの開発
行結果である。プログラムの書式は個人により好みがあ 今回のプリティプリンタの作成に当たっては,今回開 るので,この書式を変更したい場合がある。たとえば, 発したデバッガの助けを借りた。このデバッガはスク if文やwhile文などで ロール部分のアセンブラによる記述を除いて, C言語で if(…) 書かれている。なお,このデバッガはまだ改良中である
{ が,現在使用できる機能を含めて概要を紹介する。…… MYLANGシステムでは,ソースプログラム(すな } わちEARTFプログラム)は最終的にスタックマシン
のように,対応する中括弧を同じカラム位置にしたい場 のコードに変換されて,スタックマシン上で実行される。合には,図3.3の部分を変更するだけでよいなど,こ 今回開発したデバッガは,このスタックマシンにトレー れらの変更は極めて簡単にできる。 ス機能などを付加したものであり,実行中のコードや非
終端記号を表示する。このデバッガの持つ機能は次の通りである。
llncludl 聖ltll瓢:‖| */ ・通常実行モードと3種類のトレースモードがある。
{°id mainO トレースモードの違いによってトレース中に表示す inti。s;
f。,(i・o;i・lo:i・+)s+・i: る情報の量が異なる。また,リアルタイムでモード
while(i》0){i−一;s−=i;}
;{1:>0)put・( + ): を切り替えることができる。
1{1:<o)puts( ): ・非終端記号名とRAMのアドレスの両方にブレーク ;潟ll,(・・);杣,1,(D:} ポイントを設定できる。
}
・トレースをスキップしたい非終端記号をファイルに
(a)実行前設定できる。これは,ボトムアップでプログラムの
llnc|、dlumlltll:1;IM */ 開発を行っているとき,デバッグ済みの非終端記号 {°id main() をトレースさせないようにするためである。int i,S;
f・・(i・0;i・101i++) ・属性名と属性値を表示できる。
にに
whi|㌍翌。{; ・開始記号から現在実行中の非終端記号名までを表示 lf(,.o) するとともに,現在の非終端記号の深さを示す。
,|sePlllll;;); ・トレース結果の画面から消えた部分の数画面分は
puts(,, ,,);
・lse{ バッファに残るので,逆スクロールさせて見ること
i=10;d°{puts(・・); ができる。
}} hile(i)1 図4.1にプリティプリンタのプログラムをデバッガ }
でトレースしている様子を示す。図(a)はブレークポ
(b)実行後イントに非終端記号〈while>を設定してトレースモード
図3・2 Zリティプリンタを通す前と後のプロ を実行し,ブレークポイント〈while>で停止していると
クラムころであり,図(b)は,コードや属性の値を表示する
詳細モードを実行しているところである。〈丸括弧ブロック〉=〈丸括弧〉<空白》*〈ws( /)〉
(<ブロックC》+else〈1命令〉)1
<ブロックC>= { [([$ind]:;[$ind]+D]<wlf>〈インデント([$lnd]/)〉
〈ws( { !)〉くブロック1》〈ブランク〉*
(〈code(梱L/)〉+else〈wlf×インデント([$ind]/)〉)
[([$lnd]:=[$ind]−1)]:
図3.3 書式を変更するためのプログラムの変
更箇所
〈〉〈〉〈〉〈ブロック〉<ブロック1>〈ブロック2>〈ブロック3>〈予約語〉<ωhile>
、、e耐1呪翌ラドモ./,,_。 \
8:end 〈復改B>_o 現在実行中の
pu5h 125 非終端記号i㌧鷺ii鷲ii;il三器一・
8:begin〈丸括弧〉:uhile(i>0){i−一;s−;i;}[NU ,(, :whi|e(i>0){i−一;s−=i;}[NL]: ...×
1趣,1吾瓢品1。,、、④,、_、、,、NL]
1:誌ネ麟黙㌃:,ご: ÷一㌫フア
9: begin〈for> :whileU>0)〔i−一;5−=i;}[NL]
for :while(i>0){i−一;5−=i;}[NL]: ...×
9:end 〈fo「〉...x プレークボイント
9: begin 〈uhile> :while(i>0){i−一;s−=i;}[NU SP自CE: cont i nue CR: change tr
brk point = (1)whi|e_ (2) brk addr(ram) 三
(a) トレースモート
〈〉〈〉〈〉〈〉〈〉〈〉〈ブロック3>〈予約語〉〈for>〈丸括弧ブロック〉〈1命令〉〈インデント〉
(1015:b.21)
12:begin〈インデント(2/・)〉:s+ニi;[NL]
(1016:0.0) a=? b=0
(1017:n.1019) _曲L
(1019・u.0)・・2b・0 属性値
push a=2
(1〔〕20:i.〔〕) a=2 b=O
ush O
(1〔〕21:c.2) a− =O G。22,1.1。;、1>,∵、・・ら㌃\
(1024:仁23) a;2 b=0 \アドレス.コート
push 23(1025:n.107④ a=2 b=0 _ヲド終端記号のレベル
70:b.14) =13 pass 〈uS(23/*)〉 :s+=i;【NL]
〈ωS(*/)〉...O
(1026:L1[〕28) ×=2
(1〔〕28:u.0) ×=2
SP臼CE: cont i nue CR: change trace mode
(b)詳細モード
図4.1 デバッガの実行画面
5.あとがき 参考文献
1) 山之上,安在: 属性付正規翻訳記法と属性付構文向き翻 我々の研究室では,MYLANGシステムによる応用 訳 ,九工大研究報告, No・47, PP・61−68(1983)・
_ 2)山之上,安在: 属性付構文指示翻訳系の生成系 プログラムの開発とMYLANG自身の改良を並行して MYLANG・,情報処理学会論文誌, V。L 26, N。.1, PP 行っている。今回の論文において,プリティプリンタは 195−204(1985).
前者に位置し・〔・ガは後者に位置している・このよ 3L㌻議二難豊竺慧驚霊鷲
うに,MYLANGを使ってアプリケーションを作るこ 117.127(1986).
とによって,MYLANG自身の改良箇所を発見するこ 4)山之上・安在・吉田・杉尾・武内・椎野: 言語処理系の 生成系MYLANGによるNBSG/PDプリコンパイラの試
とができる。現在・MYLANGシステムは・実行速度 作・,情報処理学会論文誌, V。L職No 1. PP 64−73(1987)
や開発環境の改善をめざして書き直しが行われている。 5)高山泰博: 言語処理系の生成系に関する研究一標準 MYLANGシステムと動作支援機構の統合 ,九工大卒業論 最後に・比較のためにPascal版のプリティプリンタ 文, Nα47, PP.61−68(1985)
のソースリストをいただいた九州工業大学の永松正博先 6)安在研究室: MYLANG説明書(MS−DOS version)
(1986).
生に感謝します。