情報工学実験 C コンパイラ第 2 回説明資料 (2017 年度 ) 担当 : 笹倉 佐藤

Similar documents
情報工学実験 C コンパイラ第 2 回説明資料 (2018 年度 ) 担当 : 笹倉 佐藤

18/12/06 情報工学実験 C コンパイラ (2018 年度 ) 担当 : 笹倉 佐藤 その 3 yacc の構造 定義部 %% 定義部の終了 規則部 %% 規則部の終了 ユーザ定義サブルーチン部 :C のプログラムを書く 形は lex と同じ 1

変数を使えるようにする arithr.y を拡張して変数を使えるようにする 変数はアルファベット小文字一文字だけからなるものとする 変数の数はたかだか 26 なので,26 個の要素をもつ配列 vbltable に格納する 一行だけで計算が終わるのではなく数式を連続で計算できるようにし,$ が入力され

コンパイラとは プログラミング言語 ( 高級言語 ) で書かれたプログラムを入力し, コンピュータが実行できる言語 ( 機械語など ) に変換するプログラムのこと例 : gcc コンパイラは対応する言語によって複雑である場合もあるし単純である場合もある 本実験では簡単な言語のコンパイラを作成する

(ver. 1.3 (2018) ) yacc 1 1 yacc yacc (Yet Another Compiler Compiler) UNIX yacc yacc y *.y yacc ) yacc *.tab.h *.tab.c C C yacc yacc UNIX yacc bison 2

PowerPoint プレゼンテーション

文法と言語 ー文脈自由文法とLR構文解析2ー

Microsoft PowerPoint - 03BNFScanner.ppt [互換モード]

char int float double の変数型はそれぞれ 文字あるいは小さな整数 整数 実数 より精度の高い ( 数値のより大きい より小さい ) 実数 を扱う時に用いる 備考 : 基本型の説明に示した 浮動小数点 とは数値を指数表現で表す方法である 例えば は指数表現で 3 書く

プログラミング基礎

Microsoft PowerPoint ppt

PowerPoint プレゼンテーション

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

Microsoft PowerPoint - 03BNFScanner-print.ppt

PowerPoint プレゼンテーション

1.

II 3 yacc (2) 2005 : Yacc 0 ~nakai/ipp2 1 C main main 1 NULL NULL for 2 (a) Yacc 2 (b) 2 3 y

Microsoft PowerPoint ppt

PowerPoint プレゼンテーション

Microsoft PowerPoint - 計算機言語 第7回.ppt

Microsoft Word - 3new.doc

プログラミング基礎

プログラミング基礎

<4D F736F F D20438CBE8CEA8D758DC F0939A82C282AB2E646F63>

プログラミング実習I

untitled

Microsoft Word - problem3.doc

コンピュータ工学講義プリント (7 月 17 日 ) 今回の講義では フローチャートについて学ぶ フローチャートとはフローチャートは コンピュータプログラムの処理の流れを視覚的に表し 処理の全体像を把握しやすくするために書く図である 日本語では流れ図という 図 1 は ユーザーに 0 以上の整数 n

PowerPoint プレゼンテーション

Microsoft PowerPoint - 08LR-conflicts.ppt [互換モード]

Microsoft Word - no202.docx

PowerPoint Presentation

kiso2-09.key

Microsoft Word - Javacc.docx

Microsoft PowerPoint - 11.pptx

Microsoft Word - no11.docx

gengo1-2

cp-7. 配列

Microsoft Word - no103.docx

C8

PowerPoint プレゼンテーション

情報処理演習 B8クラス

Microsoft PowerPoint - 説明2_演算と型(C_guide2)【2015新教材対応確認済み】.pptx

CプログラミングI

Microsoft Word - problem5.doc

untitled

Microsoft PowerPoint - CproNt02.ppt [互換モード]

FORTRAN( と C) によるプログラミング 5 ファイル入出力 ここではファイルからデータを読みこんだり ファイルにデータを書き出したりするプログラムを作成してみます はじめに テキスト形式で書かれたデータファイルに書かれているデータを読みこんで配列に代入し 標準出力に書き出すプログラムを作り

3. 標準入出力

C 言語第 3 回 2 a と b? 関係演算子 a と b の関係 関係演算子 等しい a==b 等しくない a!=b より大きい a>b 以上 a>=b より小さい a<b 以下 a<=b 状態 真偽 値 条件が満たされた場合 TRUE( 真 ) 1(0 以外 ) 条件が満たされなかった場合 F

Microsoft Word - no02.doc

Microsoft PowerPoint - C_Programming(3).pptx

memo

* ライブラリ関数 islower(),toupper() を使ったプログラム 1 /* 2 Program : trupper.c 3 Student-ID : K 4 Author : TOUME, Kouta 5 Comments : Used Library function i

kiso2-03.key

Microsoft PowerPoint - ruby_instruction.ppt

memo

オブジェクト指向プログラミング・同演習 5月21日演習課題

メソッドのまとめ

プログラミング基礎I(再)

4 月 東京都立蔵前工業高等学校平成 30 年度教科 ( 工業 ) 科目 ( プログラミング技術 ) 年間授業計画 教科 :( 工業 ) 科目 :( プログラミング技術 ) 単位数 : 2 単位 対象学年組 :( 第 3 学年電気科 ) 教科担当者 :( 高橋寛 三枝明夫 ) 使用教科書 :( プロ

ポインタ変数

PowerPoint Presentation

Prog1_10th

Microsoft Word - Cプログラミング演習(12)

スライド 1

Microsoft PowerPoint - lec10.ppt

Microsoft PowerPoint - 12.ppt [互換モード]

Report#2.docx

slide5.pptx

PowerPoint Presentation

Microsoft PowerPoint - Compiler03.pptx

解答編 第 9 章文字データの取り扱い 演習問題 9.1 文法事項 1 ) コンピュータにおける 文字データの取り扱いについて説明しなさい コンピュータでは 文字に整数の番号を割り当てて ( コード化して ) 文字コードとして扱います 実際に用いられる文字コードとして ASCII コード EUC コ

Microsoft PowerPoint L03-Syntex and Semantics-1-students ( )

Cプログラミング1(再) 第2回

Microsoft PowerPoint - C言語の復習(配布用).ppt [互換モード]

02: 変数と標準入出力

Microsoft PowerPoint - å®�æ−•è©¦é¨fi3ㆮ対ç�Œ.pptx

Microsoft PowerPoint - 12.ppt [互換モード]

C 言語第 7 回 掛け算 (multiply number) ìz1 = x1 + iy1 í îz = x + iy 割り算 (devide number) ( )( ) ( ) Þ z z = x + iy x + iy = x x - y y + i y x + x y

Report#2.docx

PowerPoint プレゼンテーション

ポインタ変数

画像ファイルを扱う これまでに学んだ条件分岐, 繰り返し, 配列, ファイル入出力を使って, 画像を扱うプログラムにチャレンジしてみよう

Taro-ポインタ変数Ⅰ(公開版).j

Java講座

Microsoft PowerPoint - 3.ppt [互換モード]

新版 明解C++入門編

Microsoft PowerPoint - 説明3_if文switch文(C_guide3)【2015新教材対応確認済み】.pptx

C プログラミング 1( 再 ) 第 4 回 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ 1

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

ex04_2012.ppt

02: 変数と標準入出力

講習No.1

PowerPoint プレゼンテーション

問 2 ( 型変換 ) 次のプログラムを実行しても正しい結果が得られない 何が間違いかを指摘し 正しく修正せよ ただし int サイズが 2 バイト long サイズが 4 バイトの処理系での演算を仮定する #include <stdio.h> int main( void ) { int a =

Microsoft PowerPoint ppt

Java プログラミング Ⅰ 3 回目変数 変数 変 数 一時的に値を記憶させておく機能型 ( データ型 ) と識別子をもつ 2 型 ( データ型 ) 変数の種類型に応じて記憶できる値の種類や範囲が決まる 型 値の種類 値の範囲 boolean 真偽値 true / false char 2バイト文

Microsoft PowerPoint - 09.pptx

Microsoft PowerPoint - Compiler03note.pptx

Transcription:

情報工学実験 C コンパイラ第 2 回説明資料 (2017 年度 ) 担当 : 笹倉 佐藤 2017.12.7

前回の演習問題の解答例 1. 四則演算のできる計算機のプログラム ( 括弧も使える ) 2. 実数の扱える四則演算の計算機のプログラム ( 実数 も というより実数 が が正しかったです ) 3. 変数も扱える四則演算の計算機のプログラム ( 変数と実数が扱える )

演習問題 1 で行うべきこと 構文木が演算の順序を反映するように規則を作る 具体的には 同じ演算子が並んだら左側から実行する 加減算より乗除算を優先して実行する 括弧の中が外より先に実行される

算術式の規則 expression : expression + mulexp expression - mulexp mulexp ; mulexp : mulexp * primary mulexp / primary primary ; primary : ( expression ) NUMBER ;

演習問題 1 解答例 (arith.y) %{ #include <stdio.h> #include arith.tab.h" extern int yylex(); extern int yyerror(); %} %token NUMBER statement : expression { prinu("= %d\n", $1);} ; expression : expression '+ mulexp {$$ = $1 + $3;} expression '- mulexp {$$ = $1 - $3;} ; mulexp {$$ = $1;} mulexp : mulexp * primary {$$ = $1 * $3;} ; mulexp / primary {if ($3 == 0) { yyerror( divide by zero ); return 0;} else $$ = $1 / $3;} primary {$$ = $1;} primary : ( expression ) {$$ = $2;} ; NUMBER {$$ = $1;} int main(void) { } if(yyparse()) { } fprinu(stderr, "Error\n"); return 1; return 0;

演習問題 1 解答例 (arith.l) %{ #include arith.tab.h %} [0-9]+ {yylval = atoi(yytext); return NUMBER;} [\t ] ; /* ignore whitespace */ \n return 0;. return yytext[0];

lex と yacc の連携 (1) lex のアクションで return した値 yacc ではトークンの種類として受け取る lex [0-9]+ {yylval = atoi(yytext); return NUMBER;} [\t ] ; /* ignore whitespace */ \n return 0;. return yytext[0]; yacc primary : ( expression ) {$$ = $2;} NUMBER {$$ = $1;} ;

lex と yacc の連携 (2) lex のアクションで return した値 yacc ではトークンの種類として受け取る lex [0-9]+ {yylval = atoi(yytext); return NUMBER;} [\t ] ; /* ignore whitespace */ \n return 0;. return yytext[0]; yacc primary : ( expression ) {$$ = $2;} NUMBER {$$ = $1;} ;

lex と yacc の連携 (3) lex で yylval に入れた値 yacc ではシンボル値として受け取れる lex [0-9]+ {yylval = atoi(yytext); return NUMBER;} [\t ] ; /* ignore whitespace */ \n return 0;. return yytext[0]; yacc primary : ( expression ) {$$ = $2;} NUMBER {$$ = $1;} ;

シンボル シンボル シンボルシンボルシンボル primary : ( expression ) {$$ = $2;} NUMBER {$$ = $1;} ; シンボル

シンボル値 $$ $1 $2 $3 primary : ( expression ) {$$ = $2;} NUMBER {$$ = $1;} ; $1

演習問題 2 で行うべきこと 演習問題 1 のプログラムで整数を実数に変える 1. lex で実数を受け取れるようにする 2. yylval で実数値を yacc に渡す

実数の正規表現の例 [0-9]+ [0-9]*\.[0-9]+ [0-9]+ は 0 から 9 までの数字の 1 個以上の繰り返し. 整数表現に対応例 :14 [0-9]*\.[0-9]+ は 0 から 9 までの数字の 0 個以上の繰り返しの後. が来て, その後 0 から 9 までの数字の 1 個以上の繰り返し.. はそのままではすべての文字にマッチしてしまうので \. にして. だけを表すようにしている. 例 :1.34

yylval を実数に yylval の型は YYSTYPE YYSTYPE はデフォルトでは int YYSTYPE を変えることで yylval とすべてのシンボル値の型が変わる #define YYSTYPE double

演習問題 2 解答例 (arithr.y) %{ #include <stdio.h> #define YYSTYPE double #include arith.tab.h" extern int yylex(); extern int yyerror(); %} %token NUMBER statement : expression { prinu("= %g\n", $1);} ; expression : expression '+ mulexp {$$ = $1 + $3;} expression '- mulexp {$$ = $1 - $3;} ; mulexp {$$ = $1;} mulexp : mulexp * primary {$$ = $1 * $3;} ; mulexp / primary {if ($3 == 0) { yyerror( divide by zero ); return 0;} else $$ = $1 / $3;} primary {$$ = $1;} primary : ( expression ) {$$ = $2;} ; NUMBER {$$ = $1;} int main(void) { } if(yyparse()) { } fprinu(stderr, "Error\n"); return 1; return 0;

演習問題 2 解答例 (arithr.l) %{ #define YYSTYPE double #include arith.tab.h %} [0-9]+ [0-9]*\.[0-9]+ {yylval = atof(yytext); return NUMBER;} [\t ] ; /* ignore whitespace */ \n return 0;. return yytext[0];

演習問題 3 で行うべきこと 1. 演習問題 2 のプログラムで変数を使えるようにする 2. 一行だけで計算が終わるのではなく数式を連続で計算できるようにし,$ が入力されたら終了するようにする

変数を使えるようにする arithr.y を拡張して変数を使えるようにする 変数はアルファベット小文字一文字だけからなるものとする 変数の数はたかだか 26 なので,26 個の要素をもつ配列 vbltable に格納する 配列 vbltable は yacc の宣言部で宣言する

%union どの変数が使われるのかを知るためには lex プログラムから変数名を受け取らなければならない 数字が入力された時は実数を, 変数が入力された時には整数 ( 配列の添え字に使う ) を受け取るように複数種類の型の値を yylval に入れて lex プログラムから yacc プログラムへ値を渡したい そのための %union %union を使うと YYSTYPE の型が共用体になる

共用体とは C のデータ型の一つ 一つの変数を場合によって別の型で使えるようにするための仕組み あまり使われることはない ここでは yylval を double で使ったり int で使ったりするために利用する 詳しくは C の教科書を参照のこと

%union 宣言の使い方例 yacc プログラムの宣言部にシンボルの型を定義する %union { double dval; int vblno; } C の共用体として実現される yacc プログラムの各シンボルにどの型を取るかを教えてあげなければならない トークンの場合 %token <dval> NUMBER %token <vblno> NAME 非終端記号のシンボルの場合 %type <dval> expression

演習 : 変数も使える計算機 (arithrv.[ly]) arithr.[ly] を拡張する %union 行を arithrv.y に加える 変数の値を格納する配列 vbltable[26] を arithrv.y で宣言する 変数のトークンを NAME として arithrv.l で読み込めるようにする 変数への代入を可能にするために arithrv.y に statement : NAME = expression expression を付け加える NAME を expression の中で使えるようにする statement を複数行読めるようにし,$ が来たら終わるようにする 各トークン, 必要な非終端記号に型を指定すること

演習問題 3 解答例 (arithrv.y) %{ #include <stdio.h> #include arith.tab.h" extern int yylex(); extern int yyerror(); double vbltable[26]; %} %union{ } double dval; int vblno; %token <vblno> NAME %token <dval>number %type <dval> expression mulexp primary statement_list : statement \n statement_list statement \n ; ; statement : NAME = expression { vbltable[$1] = $3; prinu( %c = %g\n, $1 + a, $3);} expression { prinu("= %g\n", $1);} ( 中略 ) primary : ( expression ) {$$ = $2;} ; NUMBER {$$ = $1;} NAME {$$ = vbltable[$1];} ( 後略 )

演習問題 3 解答例 (arithrv.l) %{ #include arith.tab.h %} [0-9]+ [0-9]*\.[0-9]+ {yylval = atof(yytext); return NUMBER;} [\t ] ; /* ignore whitespace */ [a- z] {yylval.vblno = yytext[0] - 'a'; return NAME; } "$" {return 0; /* end of input */} \n. return yytext[0]; 注 ) lex が return 0; すると入力終了の意味になる.

演習問題 4 基本言語仕様を構文解析する yacc,lex プログラムを作成する まずは正しいプログラムは何のエラーもなく通るようにする. コード生成はまだしなくてよい. アクション部は何も書かなくてよい. エラーがあれば error と出力するようにする

基本言語仕様 < プログラム > ::= < 変数宣言部 > < 文集合 > < 変数宣言部 > ::= < 宣言文 > < 変数宣言部 > < 宣言文 > < 宣言文 > ::= define < 識別子 >; array < 識別子 > [< 数 >]; < 文集合 > ::= < 文 > < 文集合 > < 文 > < 文 > ::= < 代入文 > < ループ文 > < 条件分岐文 > < 代入文 > ::= < 識別子 > = < 算術式 >; < 算術式 > ::= < 算術式 > < 加減演算子 > < 項 > < 項 > < 項 > ::= < 項 > < 乗除演算子 > < 因子 > < 因子 > < 因子 > ::= < 変数 > (< 算術式 >) < 加減演算子 > ::= + - < 乗除演算子 > ::= * / < 変数 > ::= < 識別子 > < 数 > < 識別子 >[< 数 >] < ループ文 > ::= while (< 条件式 >) { < 文集合 > } < 条件分岐文 > ::= if (< 条件式 >) { < 文集合 > } if (< 条件式 >) { < 文集合 > } else { < 文集合 > } < 条件式 > ::= < 算術式 > < 比較演算子 > < 算術式 > < 比較演算子 > ::= == '<' '>' < 識別子 > ::= < 英字 > < 英数字列 > < 英字 > < 英数字列 > ::= < 英数字 > < 英数字列 > < 英数字 > < 英数字 > ::= < 英字 > < 数字 > < 数 > ::= < 数字 > < 数 > < 数字 > < 英字 > ::= 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 < 数字 > ::= 0 1 2 3 4 5 6 7 8 9

この言語で書けるプログラムの例 define a; define a1; define b; array c[3]; a = 2800; b = (a + 5) *3; c[0] = 0; c[1] = 1; c[2] = 2; if (b> 3000) { b = 3000; } a1 = c[0]; while(a1 < c[2]){ b = b / 2; a1 = a1 + c[1]; }

この言語でエラーとなるプログラムの例 例 1 例 2 int a; a = 0; define a; array c[3]; a = 0; while (a < 3) { c[a] = a; }

演習問題 4 で行うべきこと 何をトークンとして扱うか 終端記号はすべてトークン 基本言語仕様のうち正規表現で書けるものはトークンとして lex で切り出す

基本言語仕様 < プログラム > ::= < 変数宣言部 > < 文集合 > < 変数宣言部 > ::= < 宣言文 > < 変数宣言部 > < 宣言文 > < 宣言文 > ::= define < 識別子 >; array < 識別子 > [< 数 >]; < 文集合 > ::= < 文 > < 文集合 > < 文 > < 文 > ::= < 代入文 > < ループ文 > < 条件分岐文 > < 代入文 > ::= < 識別子 > = < 算術式 >; < 算術式 > ::= < 算術式 > < 加減演算子 > < 項 > < 項 > < 項 > ::= < 項 > < 乗除演算子 > < 因子 > < 因子 > < 因子 > ::= < 変数 > (< 算術式 >) < 加減演算子 > ::= + - < 乗除演算子 > ::= * / < 変数 > ::= < 識別子 > < 数 > < 識別子 >[< 数 >] < ループ文 > ::= while (< 条件式 >) { < 文集合 > } < 条件分岐文 > ::= if (< 条件式 >) { < 文集合 > } if (< 条件式 >) { < 文集合 > } else { < 文集合 > } < 条件式 > ::= < 算術式 > < 比較演算子 > < 算術式 > < 比較演算子 > ::= == '<' '>' < 識別子 > ::= < 英字 > < 英数字列 > < 英字 > この線から下はlexで < 英数字列 > ::= < 英数字 > < 英数字列 > < 英数字 > < 英数字 > ::= < 英字 > < 数字 > < 数 > ::= < 数字 > < 数 > < 数字 > < 英字 > ::= 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 < 数字 > ::= 0 1 2 3 4 5 6 7 8 9

基本言語仕様 < プログラム > ::= < 変数宣言部 > < 文集合 > < 変数宣言部 > ::= < 宣言文 > < 変数宣言部 > < 宣言文 > < 宣言文 > ::= define < 識別子 >; array < 識別子 > [< 数 >]; < 文集合 > ::= < 文 > < 文集合 > < 文 > < 文 > ::= < 代入文 > < ループ文 > < 条件分岐文 > < 代入文 > ::= < 識別子 > = < 算術式 >; < 算術式 > ::= < 算術式 > < 加減演算子 > < 項 > < 項 > < 項 > ::= < 項 > < 乗除演算子 > < 因子 > < 因子 > < 因子 > ::= < 変数 > (< 算術式 >) < 加減演算子 > ::= + - < 乗除演算子 > ::= * / < 変数 > ::= < 識別子 > < 数 > < 識別子 >[< 数 >] < ループ文 > ::= while (< 条件式 >) { < 文集合 > } < 条件分岐文 > ::= if (< 条件式 >) { < 文集合 > } if (< 条件式 >) { < 文集合 > } else { < 文集合 > } < 条件式 > ::= < 算術式 > < 比較演算子 > < 算術式 > < 比較演算子 > ::= == '<' '>' < 識別子 > ::= < 英字 > < 英数字列 > < 英字 > < 英数字列 > ::= < 英数字 > < 英数字列 > < 英数字 > < 英数字 > ::= < 英字 > < 数字 > < 数 > ::= < 数字 > < 数 > < 数字 > 具体的には赤字がトークンあとはこの線より上の終端記号がトークン < 英字 > ::= 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 < 数字 > ::= 0 1 2 3 4 5 6 7 8 9

トークン それぞれのトークンごとに種類を分ける例 : 識別子, 数, プラス記号, マイナス記号, define, array. 今はまだ yacc のアクションを書かないので型について考える必要はない lex もトークンの名前を return するだけでよい