コンパイラ 2011年10月6日 酒居敬一@A468(sakai.keiichi@kochi-tech.ac.jp) http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/COMP/2011/index.html.

Slides:



Advertisements
Similar presentations
プログラミング言語論 プログラミング言語の構 文 水野嘉明. 目次 1. プログラミング言語の構文 2. BNF 3. 文脈自由文法 4. 構文図式 2.
Advertisements

プログラミング言語論 第3回 BNF 記法について(演習付き) 篠埜 功. 構文の記述 プログラミング言語の構文はどのように定式化できるか? 例1 : for ループの中に for ループが書ける。 for (i=0; i
2.5 プログラムの構成要素 (1)文字セット ① ASCII ( American Standard Code for Interchange ) JIS コードと同じ ② EBCDIC ( Extended Binary Coded Decimal for Information Code ) 1.
和田俊和 資料保存場所 /2/26 文法と言語 ー正規表現とオートマトンー 和田俊和 資料保存場所
プログラミング言語論 第10回(演習) 情報工学科 木村昌臣   篠埜 功.
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
言語処理系(1) 金子敬一.
コンパイラ 2011年10月17日
プログラミング言語としてのR 情報知能学科 白井 英俊.
文法と言語 ー文脈自由文法とLR構文解析2ー
コンパイラ 第9回 コード生成 ― スタックマシン ―
プログラミング言語論 第6回 型 情報工学科 篠埜 功.
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
プログラミング言語論 第4回 式の構文、式の評価
アルゴリズムとデータ構造 2011年6月13日
言語処理系(5) 金子敬一.
言語処理系(8) 金子敬一.
  【事例演習6】  数式インタプリタ      解 説     “インタプリタの基本的な仕組み”.
コンパイラ 2012年10月15日
コンパイラ 2012年10月22日
情報処理Ⅱ 第4回 2007年10月29日(月).
コンパイラ 2011年10月24日
岩村雅一 知能情報工学演習I 第8回(後半第2回) 岩村雅一
プログラムの制御構造 選択・繰り返し.
言語プロセッサ 第7回目 平成27年11月16日.
情報処理Ⅱ 第2回 2007年10月15日(月).
プログラミング言語論 第3回 BNF記法について(演習付き)
FlexとBison+アルファ -実習編-
プログラミング演習I 2003年5月7日(第4回) 木村巌.
岩村雅一 知能情報工学演習I 第8回(C言語第2回) 岩村雅一
コンパイラ 第13回 上昇型構文解析(1) 38号館4階N-411 内線5459
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
言語プロセッサ 第8回目 平成22年11月22日.
文法と言語 ー文脈自由文法とLR構文解析2ー
フロントエンドとバックエンドのインターフェース
第5章 計算とプログラム 本章で説明すること ・計算の概観と記述法 ・代表的な計算モデル ・プログラムとプログラム言語.
プログラミング言語論 第9回 情報工学科 木村昌臣 篠埜 功.
コンパイラ 2011年10月20日
コンパイラ 2012年10月4日
プログラミング言語入門 2013 (C言語 初級) 演習期間 担当 参考資料 採点 10/24 - 1/23 (全10回) 松澤,鈴木,児玉
C言語ファミリー C# 高級言語(抽象的) Java オブジェクト指向 C++ C 機械語(原始的)
C++ 構文解析 構文解析器の状態保存と復元
参照されないリテラル 長谷川啓
コンパイラ 2012年10月1日
文法と言語 ー文脈自由文法とLR構文解析ー
オブジェクト指向言語論 第三回 知能情報学部 新田直也.
情報処理Ⅱ 第3回 2007年10月22日(月).
コンパイラ 2012年10月29日
アルゴリズムとデータ構造 2012年6月11日
情報処理Ⅱ 第2回 2005年10月14日(金).
情報処理Ⅱ 第2回 2006年10月13日(金).
アルゴリズムとデータ構造1 2009年6月15日
情報処理Ⅱ 2005年10月28日(金).
言語プロセッサ 第12日目 平成20年1月9日.
コンパイラ 2012年10月11日
プログラミング 4 文字列.
岩村雅一 知能情報工学演習I 第8回(後半第2回) 岩村雅一
岩村雅一 知能情報工学演習I 第8回(C言語第2回) 岩村雅一
アルゴリズムとデータ構造 2010年6月17日
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
文法と言語 ー文脈自由文法とLR構文解析2ー
:: の扱い 長谷川啓.
情報処理Ⅱ 第2回 2004年10月12日(火).
第3回簡単なデータの入出力.
情報処理Ⅱ 小テスト 2005年2月1日(火).
1.2 言語処理の諸観点 (1)言語処理の利用分野
情報処理Ⅱ 第3回 2004年10月19日(火).
C言語講座 四則演算  if ,  switch 制御文.
情報処理Ⅱ 2006年10月27日(金).
分岐(If-Else, Else if, Switch) ループ(While, For, Do-while)
Presentation transcript:

コンパイラ 2011年10月6日 酒居敬一@A468(sakai.keiichi@kochi-tech.ac.jp) http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/COMP/2011/index.html

コンパイラの構成と プログラム言語の形式的な記述 コンパイラの構成と プログラム言語の形式的な記述 式(Expression)と文(Statement) 算術式の中置期法と後置記法 コンパイラの論理的な構成 コンパイラの物理的な構成 プログラム言語の形式的な記述方法 バッカス記法 構文図式(→次回)

式(Expression)と文(Statement) 式はそれ自体が値を持つもの。 一般的には値・変数・演算子・関数を組み合わせたもの。 式として認識される範囲は言語仕様に依存する。 文は手続きを表すことが多い。 改行文字まででひとつの文とする言語 特別な記号で区切ったり、次行と結合したりもできる。 文脈依存文法。 区切り文字で区切る言語 Pascalは、';'が区切り文字になっている。 区切りが特に無い言語 Cは、';'が式を文とする記号。

算術式の中置期法と後置記法 四則演算では演算には優先順位がある。 通常の式では変数と変数の間に演算子がある。 乗除算は加減算に優先する、括弧はそれらより優先する。 通常の式では変数と変数の間に演算子がある。 中に演算子を置くので中置記法という。 学群実験の経験より、計算機は優先順位など知らない。 機械語として書かれた順に処理するだけ。 通常の式を機械語に変換するに先立って、書き換える。 そのひとつが後置記法。 演算子を被演算対象の後に置く。

後置記法の例 中置記法のA+B*C-Dは、ABC*+D-という後置記法になる。 優先順位に基づき((A+(B*C))-D)というように解釈する。 演算対象を読んだらそのまま出力する 演算子を読んだら、それより優先度の高い演算子があれば スタックから取り出し順に出力しておいて、スタックに積む。 式を読み終わったら全部順に取り出し出力する。 入力 A B D C + ー * ( ) 出力 スタック

コンパイラの場合 後置記法の式を機械語(中間語)に変換する。 ABC*+D-の場合 変数または定数を入力したらスタックに積む。 mul B,C, W1 add A,W1, W2 sub W2,D,W3 変数または定数を入力したらスタックに積む。 演算子を入力したらスタックから右辺・左辺を取り出し出力 最後にスタックに残ったものが式の答え 入力 A B C * + D ー スタック C B B W1 D A A A A W2 W2 W3 出力 *,B,C W1 +,A,W1 W2 ー,W2,D W3

コンパイラの論理的な構成 コンパイラは図のように各フェーズに分かれて処理する。 その過程で中間情報として名前表や中間語を保持する。 字句解析 構文解析 意味解析 最適化とコード生成 その過程で中間情報として名前表や中間語を保持する。 ソース プログラム 目的 中間情報(中間語、名前表) 字句 解析 コード 生成 構文 意味 最適化

字句解析 ソースプログラムを字句と呼ばれる基本要素に分解する。 int a,b,c,d;の例 a=b+c*d;の例 予約語 int int a,b,c,d;の例 a=b+c*d;の例 予約語 int 記号セミコロン 記号コンマ 名前 a 名前 b 名前 c 名前 d 名前 a 名前 b 名前 c 名前 d 記号乗算 記号加算 記号等号 記号セミコロン

構文解析 分解された字句の並びが、構文規則に合うかどうか調べる。 関数名、変数名といった名前は名前表に登録される。 名前 a 名前 b 名前 a 名前 b 名前 c 名前 d 記号乗算 記号加算 記号等号 エントリ番号 名前 データ型 番地 領域長 1 a int 12 4 2 b 16 3 c 20 d 24 5 $wk1 28 6 $wk2 32

意味解析 式は複数の演算に分解される。 式の場合、例えば、変数の型や型変換の可否を調べる。 最初の例にあったように、4つ組の中間語出力を生成 する際に $wk1や$wk2といった一時記憶を使う。 乗算 名前表 #3 名前表 #4 名前表 #5 加算 名前表 #2 名前表 #6 名前表 #5 名前表 #1 代入 名前表 #6

最適化 例えば、最適化前のフェーズの中間語表現 代入はデータを移動するだけなので、加算命令の結果の 行き先に指定すれば代入が不要になる(無用命令削除)。 他に、共通部分式の括り出し、定数伝播、演算強度の 低減、ループ内不変式のループ外への括り出し、 などを行う。 加算 名前表 #2 名前表 #6 名前表 #5 名前表 #1 代入 名前表 #6 加算 名前表 #2 名前表 #1 名前表 #5

コード生成 中間語として表されたプログラムを機械語に変換する。 この段階の中間語はプロセッサに依存しない仮想機械 の命令で、それを変換する。 コード生成するために、より前の段階で中間語生成に 制約を設けている。 この段階の中間語はプロセッサに依存しない仮想機械 の命令で、それを変換する。 演算命令にメモリオペランドの使えるアーキテクチャ Load   Reg#1,Addr#20 Multiply Reg#1,Addr#24 Add    Reg#1,Addr#16 Store   Reg#1,Addr#12 演算命令にメモリオペランドの使えないアーキテクチャ Load   Reg#2,Addr#24 Multiply Reg#1,Reg#2,Reg#1 Load   Reg#2,Addr#16 Add    Reg#1,Reg#2,Reg#1 かなり違うので前段階で 制約として違いを盛り込む。

コンパイラの物理的な構成 パスとは、コンパイラ内部で中間語を順次出力する段階。 ワンパスコンパイラの例 プログラムとして分離しているかどうかではない。 ワンパスコンパイラの例 最適化しないことが多い。 ソース プログラム 目的 字句 解析 コード 生成 構文 意味 ひどいクロスコンパイラがあったなぁ~

普通のコンパイラ 最適化のパスがコード生成前にある。 3パスコンパイラの例 商用コンパイラではもっとパス数が多い。 パス3 パス2 パス1 ソース プログラム 目的 字句 解析 コード 生成 構文 意味 最適化 中間語

プログラム言語の形式的な記述方法 プログラミング言語の文法、つまり、生成規則。 生成規則が厳密であること。 プログラムを書くとは、文法に基づいてソースプログラムを 生成すること。だから、生成規則と呼んでいる。 コンパイラではソースプログラムが生成規則から生成されうる 文であるかどうかを判断し、目的プログラムを出力する。 生成規則に則らない記述はエラーとなる。 生成規則を意図的にゆるめている(シンタックスシュガー)場合もある。 もちろん、意図されないものはコンパイラの欠陥。 生成規則が厳密であること。 そのために、形式的な記述法が必要。 ソースプログラムが書きやすいこと。 素で書きやすいこと。シンタックスシュガーは必要悪。

バッカス記法(Backus Naur Form, BNF) <>で囲まれたものを構文要素と呼ぶ。 例では字句を定義しているが、字句解析済みの場合もある。 Javaのように名前に日本語文字集合が使える場合は、 こんなに単純に記述できない。ASCII文字集合なら簡単。 →の左側の要素は右側で構成される。 |は「または」を意味する。 <数字>→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 <名前>→<英字>|<名前><英字>|<名前><数字>

%token int_const char_const float_const id string enumeration_const %% translation_unit : external_decl | translation_unit external_decl ; external_decl : function_definition | decl function_definition : decl_specs declarator decl_list compound_stat | declarator decl_list compound_stat | decl_specs declarator compound_stat | declarator compound_stat decl : decl_specs init_declarator_list ';' | decl_specs ';' decl_list : decl | decl_list decl decl_specs : storage_class_spec decl_specs | storage_class_spec | type_spec decl_specs | type_spec | type_qualifier decl_specs | type_qualifier storage_class_spec : 'auto' | 'register' | 'static' | 'extern' | 'typedef' type_spec : 'void' | 'char' | 'short' | 'int' | 'long' | 'float' | 'double' | 'signed' | 'unsigned' | struct_or_union_spec | enum_spec | typedef_name type_qualifier : 'const' | 'volatile' struct_or_union_spec : struct_or_union id '{' struct_decl_list '}' | struct_or_union '{' struct_decl_list '}' | struct_or_union id struct_or_union : 'struct' | 'union' struct_decl_list : struct_decl | struct_decl_list struct_decl init_declarator_list : init_declarator | init_declarator_list ',' init_declarator init_declarator : declarator | declarator '=' initializer struct_decl : spec_qualifier_list struct_declarator_list ';' spec_qualifier_list : type_spec spec_qualifier_list | type_qualifier spec_qualifier_list struct_declarator_list : struct_declarator | struct_declarator_list ',' struct_declarator struct_declarator : declarator | declarator ':' const_exp | ':' const_exp enum_spec : 'enum' id '{' enumerator_list '}' | 'enum' '{' enumerator_list '}' | 'enum' id enumerator_list : enumerator | enumerator_list ',' enumerator enumerator : id | id '=' const_exp declarator : pointer direct_declarator | direct_declarator direct_declarator : id | '(' declarator ')' | direct_declarator '[' const_exp ']' | direct_declarator '[' ']' | direct_declarator '(' param_type_list ')' | direct_declarator '(' id_list ')' | direct_declarator '(' ')' pointer : '*' type_qualifier_list | '*' | '*' type_qualifier_list pointer | '*' pointer type_qualifier_list : type_qualifier | type_qualifier_list type_qualifier param_type_list : param_list | param_list ',' '...' param_list : param_decl | param_list ',' param_decl param_decl : decl_specs declarator | decl_specs abstract_declarator | decl_specs id_list : id | id_list ',' id initializer : assignment_exp | '{' initializer_list '}' | '{' initializer_list ',' '}' initializer_list : initializer | initializer_list ',' initializer type_name : spec_qualifier_list abstract_declarator | spec_qualifier_list abstract_declarator : pointer | pointer direct_abstract_declarator | direct_abstract_declarator direct_abstract_declarator: '(' abstract_declarator ')' | direct_abstract_declarator '[' const_exp ']' | '[' const_exp ']' | direct_abstract_declarator '[' ']' | '[' ']' | direct_abstract_declarator '(' param_type_list ')' | '(' param_type_list ')' | direct_abstract_declarator '(' ')' | '(' ')' typedef_name : id stat : labeled_stat | exp_stat | compound_stat | selection_stat | iteration_stat | jump_stat labeled_stat : id ':' stat | 'case' const_exp ':' stat | 'default' ':' stat exp_stat : exp ';' | ';' compound_stat : '{' decl_list stat_list '}' | '{' stat_list '}' | '{' decl_list '}' | '{' '}' stat_list : stat | stat_list stat selection_stat : 'if' '(' exp ')' stat | 'if' '(' exp ')' stat 'else' stat | 'switch' '(' exp ')' stat iteration_stat : 'while' '(' exp ')' stat | 'do' stat 'while' '(' exp ')' ';' | 'for' '(' exp ';' exp ';' exp ')' stat | 'for' '(' exp ';' exp ';' ')' stat | 'for' '(' exp ';' ';' exp ')' stat | 'for' '(' exp ';' ';' ')' stat | 'for' '(' ';' exp ';' exp ')' stat | 'for' '(' ';' exp ';' ')' stat | 'for' '(' ';' ';' exp ')' stat | 'for' '(' ';' ';' ')' stat jump_stat : 'goto' id ';' | 'continue' ';' | 'break' ';' | 'return' exp ';' | 'return' ';' exp : assignment_exp | exp ',' assignment_exp assignment_exp : conditional_exp | unary_exp assignment_operator assignment_exp assignment_operator : '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '&=' | '^=' | '|=' conditional_exp : logical_or_exp | logical_or_exp '?' exp ':' conditional_exp const_exp : conditional_exp logical_or_exp : logical_and_exp | logical_or_exp '||' logical_and_exp logical_and_exp : inclusive_or_exp | logical_and_exp '&&' inclusive_or_exp inclusive_or_exp : exclusive_or_exp | inclusive_or_exp '|' exclusive_or_exp exclusive_or_exp : and_exp | exclusive_or_exp '^' and_exp and_exp : equality_exp | and_exp '&' equality_exp equality_exp : relational_exp | equality_exp '==' relational_exp | equality_exp '!=' relational_exp relational_exp : shift_expression | relational_exp '<' shift_expression | relational_exp '>' shift_expression | relational_exp '<=' shift_expression | relational_exp '>=' shift_expression shift_expression : additive_exp | shift_expression '<<' additive_exp | shift_expression '>>' additive_exp additive_exp : mult_exp | additive_exp '+' mult_exp | additive_exp '-' mult_exp mult_exp : cast_exp | mult_exp '*' cast_exp | mult_exp '/' cast_exp | mult_exp '%' cast_exp cast_exp : unary_exp | '(' type_name ')' cast_exp unary_exp : postfix_exp | '++' unary_exp | '--' unary_exp | unary_operator cast_exp | 'sizeof' unary_exp | 'sizeof' '(' type_name ')' unary_operator : '&' | '*' | '+' | '-' | '~' | '!' postfix_exp : primary_exp | postfix_exp '[' exp ']' | postfix_exp '(' argument_exp_list ')' | postfix_exp '(' ')' | postfix_exp '.' id | postfix_exp '->' id | postfix_exp '++' | postfix_exp '--' primary_exp : id | const | string | '(' exp ')' argument_exp_list : assignment_exp | argument_exp_list ',' assignment_exp const : int_const | char_const | float_const | enumeration_const 出典:http://www.cs.man.ac.uk/~pjj/bnf/c_syntax.bnf

拡張BNF {}:{}の中の要素を0個以上並べたもの。 []:[]の中の要素を0または1個書いたもの。 これを使うとこのように<名前>を書き直せる。 <名前>→<英字>{<英字>|<数字>} BNFで使う記号 <>{}[]|→ はメタ記号と呼ぶ。 <>で囲んだ構文要素を非終端記号 <>で囲まないものを終端記号と呼ぶ。 プログラマがソースプログラムに書けるのは終端記号だけ。 構文解析に先立って字句解析があるときは、終端記号の 一部は字句としてまとめられている。