• 検索結果がありません。

プログラミング言語処理系論 (4) Design and Implementation of Programming Language Processors

N/A
N/A
Protected

Academic year: 2021

シェア "プログラミング言語処理系論 (4) Design and Implementation of Programming Language Processors"

Copied!
29
0
0

読み込み中.... (全文を見る)

全文

(1)

プログラミング言語処理系論

(4)

Design and Implementation of

Programming Language Processors

佐藤周行

(情報基盤センター/電気系専攻融合情報学

(2)

今回の予定

† 言語規格を読むことの続き „ BNFだけでできることは限られてくる „ 「文法の定義+制約」という記述の発明 † 文法から、パーサを作る † BNFをそのまま解釈する † BISON,YACCを動かしてみます

(3)

今回のはじめ

† さて、しばらくXMLの規格文書を読んでみま しょう „ 前回の続き „ 具体的に、次ページのXML documentを規格の 文法を用いて生成してみよう

(4)

<?xml version="1.1" ?> <!– Address Book -->

<!DOCTYPE addressbook SYSTEM "addressbook.dtd"> <addressbook> <personal number="0001"> <name>A</name> <address>Kanagawa</address> <tel>00-0000-0000</tel> <email addr="[email protected]"/> </personal> <personal number="0002"> <name>B</name> <address>Tokyo</address> <tel>11-1111-1111</tel> <email/> </personal> </addressbook>

(5)

BNFのポイント(前回の繰り返し)

† 文法+制約条件が言語の定義のこつです „ 「制約条件」を軽視してはいけません。ここにCFG だけでは記述しきれないさまざまなルールが自然 言語で記述されています „ 文法部分をシンプルに保ちながら、自然言語の記 述力を活かす事で、プログラミング言語の定義の 手法は完成しました(制約が守られているかどう かのチェックにはチェック用のプログラムを書くこと が必要になります)

(6)

Parserの構成

† 文法が与えられた。 † 文字列が一つ与えられた。 † その文字列が、文法に則って生成されたかど うかをチェックせよ = 文字列を生成する生成列をひとつ与えよ † 文字列から生成列を作ることを「Parse」という

(7)

† 生成例

document Æ (prolog element Misc*) Æ XMLDecl Misc* (doctypedecl

Misc*)? element MIsc*

Æ <?xml VersionInfo EncodingDecl? SDDecl? S? ?> Misc* (doctypedecl Misc*)? element Misc*

Æ …

† 普通はTreeの形で書く。これをパース木とい

(8)

パース木の例

† みにくいけど…

<?xml version = “1.1” ?> <address> Bunkyo-ku </address> S VersionInfo Eq “VersionNum”

VersionInfo EncodingDecl? SDDecl? S? XMLDecl Misc* (…)?

prolog element Misc*

document

Stag Etag

CharData* content

(9)

Parser

† Parserを作ろう = 文字列が与えられたとき、パース木を生 成するプログラムを作ろう † XMLの場合は簡単です。手でかける。 „ (課題1)XMLの文法がLL(1)であることを示し、 XMLのパーサを書け。

(10)

Parser Generator

† 文法の定義がBNFで与えられている以上、 BNFからそのままParserが生成されればとて も便利 † 効率的にParserが生成できる文法のクラスが 研究されてきた(LL(k), LR(k), LALR) † 以降では、Parser Generatorツールである Yacc(Bison)の説明を行なう

(11)
(12)

DragonBookの例

%{ #include <ctype.h> #include <stdio.h> %} %token DIGIT %%

lines : lines expr '¥n'

{printf("%d¥n", $2);} | lines '¥n'

| ;

expr : expr '+' term {$$ = $1+$3;}

| term ;

term : term '*' factor {$$ = $1 * $3;} | factor ; factor : '(' expr ')' {$$ = $2;} |DIGIT ; %% yylex() { int c; c = getchar(); if (isdigit(c)) { yylval = c - '0'; return DIGIT; } return c; }

(13)

Bisonの入力

%{ #include <ctype.h> #include <stdio.h> %} %token DIGIT %%

lines : lines expr '¥n' {printf("%d¥n", $2);} | lines '¥n'

| ;

expr : expr '+' term {$$ = $1+$3;} | term

;

term : term '*' factor {$$ = $1 * $3;} | factor ; factor : '(' expr ')' {$$ = $2;} |DIGIT ; %% † トークンの定義 † BNFでルールを書く S : S1 S2… {action} † SÆS1 S2 † ルールに対してactionが定義 されているときは、パースのと きにそのactionを実行する † $nは、n番目のシンボルの パースの結果出てくる値を表 す($$)

(14)

なぜか?

† Yaccの例として出てくるものは、まず電卓。 „ 理由(推測):標準的な教科書が導入例としてまず 電卓を定義し、定着してしまった „ (推測)式(expression)の定義は、それなりに大 切だった。 „ 次のステップ(文の定義…)に進むには、勉強する ことが多すぎる † 電卓は、yaccの例としてはあまりよくない。 „ Semantic actionの過大評価 „ 1パスパースの過大評価

(15)

dc.c

#include <stdio.h> main() { return yyparse(); } yyerror() {

fprintf(stderr, "FATAL ERROR¥n"); exit(1);

(16)

% bison –v dc.y

% cc –O dc.c dc.tab.c –o dc % ./dc

(課題2) dc.outputを解析し、どのような受理機械が 生成されたか述べよ

(課題3) linesの定義の1行目が lines expr となっ ていて、 expr lines となっていない理由を受理機 械の動作から説明せよ

(17)

Parseの流れ

3 + 4 * 5 ¥n DIGIT factor term expr DIGIT factor DIGIT factor term term expr ε lines lines SHIFT REDUCE

(18)

† Def Token: パースの単位 † Shift: パース時にトークンを読み進める † Reduce: パース時にルールを(逆に)適用して、右 辺から左辺に変換(還元)する † どのタイミングでshift/reduceをするのかについて はここでは説明しないが、判断のアルゴリズムが存 在するという意味でうまくいくようになっている文法を 扱う

(19)

BISONの出力

† パース木は作ってくれるが、それをもとにどの ような出力を構成するかはこちらの自由 † 直接解釈して値を出力 † 解析木をそのまま出力 † 計算のためのコードを出力 † …

(20)

Semantic actionの利用

3 + 4 * 5 ¥n DIGIT.3 Factor.3 Term.3 Expr.3 DIGIT.4 Factor.4 DIGIT.5 Factor.5 Term.4 Term.20 Expr.23 lines ε lines SHIFT REDUCE

(21)

プログラミング言語への進化

† コンパイラシステムの構築

„ 仮想マシンとマシン上の機械語の定義

„ 仮想マシン上での実行

† 変数の導入

† 制御構文の導入(compound, if, while)

(22)

優先度制御を利用したソースの合理化

expr : VARIABLE ASSIGN expr

| '{' compound '}' | expr '+' expr | expr '-' expr | expr '*' expr | expr GE expr | expr GT expr | expr LE expr | expr LT expr | expr EQ expr | '(' expr ')' |DIGIT |VARIABLE

| '-' expr %prec UMINUS | ; 優先度を制御する行 %left GE GT LE LT EQ %left '+' '-' %left '*' '/' %right UMINUS

(23)

compound: compound ';' expr

| expr ;

expr : VARIABLE ASSIGN expr | '(' expr ')' '?' expr ':' expr | '{' compound '}' | WH '(' expr ')' expr | expr '+' expr | expr '-' expr | expr '*' expr | expr GE expr | expr GT expr | expr LE expr | expr LT expr | expr EQ expr | '(' expr ')' |DIGIT |VARIABLE |VARIABLE '(' ')'

| '-' expr %prec UMINUS |

;

(24)

† コードセグメントの出現 „ 関数コードの保存 † データセグメントの出現 „ では、一般的には、何を用意するとプログラムの 実行に十分なのか? „ 「実行環境」(次回)

(25)

パス

† Def. Pass „ ソースプログラム(および中間生成物)を処理する 一単位。 † Def. One-Pass „ パス一つ(パースを終了させるまで)でコード生成 まで済ませる † Def. Multi-Pass „ 複数のパスから構成されるもの。一般的にはパー スをした後で、解析(最適化等)をするパスを追加 する

(26)

複数パスの表現

† ソースファイル中での表現 main(int ac, char **av) { if (ac >= 2){ if (!strcmp(*++av, "-d")) debug = 1; } code = yyparse(); if (!code) exit(1); nextPass(Entry); } Node *Entry; Top: … {Entry = …}; /* 最初か最後に、後々の 処理のエントリーポイン トを設定しておく */

(27)

パスの考え方

† 近年の考え方では、パースまでと、パース以 後の最適化をわけています。 † パースまででできることは高が知れていると認 識が一般的になりました。 „ 最適化ルーチン † インタラクティブな言語では、パースまでの処 理と、それ以後の処理(最適化等)のバランス が問題になっています。

(28)

今回触れなかったこと

† 処理の一単位となる「トークン」をうまく切り分 ける必要があるので… „ yylexはまじめにかきましょう † パース時のエラー処理 „ 非常に重要なことはわかるのだが…

(29)

次回への

Prolog

† コンパイラがコードを生成したとき、それを実 行するとはどういうことか? † 実行環境の理解 „ Virtual machine „ Hosted environment „ Freestanding environment

参照

関連したドキュメント

2021] .さらに対応するプログラミング言語も作

に関して言 えば, は つのリー群の組 によって等質空間として表すこと はできないが, つのリー群の組 を用いればクリフォード・クラ イン形

つまり、p 型の語が p 型の語を修飾するという関係になっている。しかし、p 型の語同士の Merge

計量法第 173 条では、定期検査の規定(計量法第 19 条)に違反した者は、 「50 万 円以下の罰金に処する」と定められています。また、法第 172

今回の調査に限って言うと、日本手話、手話言語学基礎・専門、手話言語条例、手話 通訳士 養成プ ログ ラム 、合理 的配慮 とし ての 手話通 訳、こ れら

平成 27

平成 27

融資あっせんを行ってきております。装置装着補助につきましては、14 年度の補助申 請が約1万 3,000