言語プロセッサ2012 -No.4東京工科大学 コンピュータサイエンス学部 亀田弘之 これからの内容 1. 字句解析プログラムの作成方法 • • 手書きの方法 Flexを利用する方法 • • • • 解析手法の種類 左再帰とその除去 括りだし FirstとFollow 2. 構文解析 2 正規表現の練習 • PCを立ち上げてください。 • HTMLのソースコードから情報を抽出して みよう! 3 字句解析の実際 • 「符号なし数」の字句解析 num → digit+ ( . digit+)? (E(+|-)?digit+)? => n → d+( . d+)? (E(+|-)?d+)? => num → d+(.d+|ε)( (E((+|-)|ε)) d+|ε) |ε) 4 Flexのソースコード例 参考 D [0-9] %% [\t ] { printf("Tab or Space\n"); } {D}+(\.{D}+)?(E(\+|\-)?{D}+)? {printf("%s\n", yytext); } . { printf("NG %s\t", yytext); } %% 5 識別子のシンタックス • letter → a|b|c|…|z|A|B|C|…|Z • digit → 0|1|2|…|9 • id → letter (letter|digit)* 6 Flexのコード例 LETTER DIGIT [a-zA-Z] [0-9] %% [\t ] { printf("Tab or Space\n"); } {LETTER}({LETTER}|{DIGIT})* {printf("id=%s\n", yytext); } . { printf("NG %s\t", yytext); } %% 7 符号なし数のシンタックス • • • • • digit → 0|1|2|3|4|5|6|7|8|9 digits → digit digit* optional_fraction → . digits |ε optional_exponent → (E(+|-|ε)digits)|ε num → digits optional_fraction optional_exponent 8 トークン認識プログラム作成 • (教科書を参考に作成してみよう!) 9 プログラムの文法(例) 10 • stmt → if expr then stmt | if expr then stmt else stmt |ε • expr → term relop term | term • term → id | num 11 • • • • • • if → if then → then else → else relop → <|<=|=|<>|>|>= id → letter(letter|digit)* num → digit+(.digit+)?(E(+|-)? 12 • delim → blank|tab|newline • ws → delim+ 13 トークン-正規表現パタン 正規表現 トークン 属性値 (なし) (なし) ws if (なし) if then (なし) then else (なし) else id 記号表のエントリへの id num ポインタ num relop LT < relop LE <= relop EQ = relop NE <> relop GT > relop GE >= 14 オートマトンの作成 15 = 0 > 6 7 other 8 16 1 0 < = 2 Return(relop,LE) > 3 Return(relop,NE) 4 Return(relop,LT) other > = 5 Return(relop,EQ) 6 = 7 Return(relop,GE) other 図. 関係演算子の遷移図 8 Return(relop,GT) 17 letter 9 letter 10 digit other 11 Return(get_token( ), install_id( )) 図. 識別子とキーワードに対する遷移図 18 17 digit 12 13 digit digit - E 19 + . 16 other digit 18 E 14 digit 15 digit digit 図. 数の遷移図(1) 19 digit digit 20 digit 21 . 22 digit 23 24 digit 25 digit 26 other 27 図. 数の遷移図(2) 20 単純な遷移図 b a a 1 2 0 b 21 state = 0; while(TRUE) { switch(state) { case 0: c = nextChar( ); /* 先読み */ switch(c){ case ‘a’: state = 1; break; case ‘b’: state = 2; break; } case 1: c = nextChar( ); switch(c){ case ‘a’: state = 2; break; case ‘b’: state = 1; break; } } } 22 state = 0; while(TRUE) { switch(state) { case 0: c = nextChar( ); /* 先読み */ switch(c){ case ‘a’: state = 1; break; case ‘b’: state = 2; break; } case 1: c = nextChar( ); switch(c){ case ‘a’: state = 2; break; case ‘b’: state = 1; break; } } } 23 簡単な遷移図 b a a 26 a 25 b 28 27 b 24 練習問題 1. 直前のページのオートマトンをシミュレー トするプログラムを作成せよ。 2. 符号なし数を処理する字句解析プログラ ムを作成せよ。 3. 次ページに示した(C言語の)浮動小数 点定数を処理する字句解析プログラム を作成せよ。 25 参考: (C言語の)浮動小数点定数 . Numbers Numbers Numbers f . e + Numbers l Numbers E - F L 26 今度はflexを使ってみよう! 27 手順 ライブラリ(fl) Flex Program Flex Lex.yy.c 文字列入力 gcc a.exe 出力 28 Flexプログラムの記述(1) delim ws letter digit id number %% [ \t\n] {delim}+ [a-zA-Z] [0-9] {letter}({letter}|{digit})* {digit}+(\.{digit}+)?(E[+\-]?{digit}+)? 29 Flexプログラムの記述(2) {ws} { /* do nothing */ } If {return(IF);} Then {return(THEN);} else {return(ELSE);} {id} {yylval = install_id( ); return(ID);} {number} {yylval = install_num(); return(NUMBER);} 30 Flexプログラムの記述(3) “<” “<=“ “=“ “<>” “>“ “>=“ %% {yylval = LT; return(RELOP);} {yylval = LE; return(RELOP);} {yylval = EQ; return(RELOP);} {yylval = NE; return(RELOP);} {yylval = GT; return(RELOP);} {yylval = GE; return(RELOP);} 31 Flexプログラムの記述(4) install_id( ){ static int id_ptr=0; return(id_ptr); } install_num( ){ static int num_ptr=0; return(num_ptr); } 32 Flexのデモ 33 手順 1. Flexのプログラムを書く。 2. Flexのプログラムをflexにかける。 3. 出力ファイルlex.yy.cをgccでコンパイル する。 4. 出力a.exeを実行する。 5. さまざまな文字列を入力する。 34 手順 ライブラリ(fl) Flex Program Flex Lex.yy.c 文字列入力 gcc a.exe 出力 35 実際の手順 C:\> flex sample01.l C:\> gcc lex.yy.c –lfl C:\> a.exe それでは、実際にやってみよう。 36 字句解析から構文解析へ 以上で、字句解析は終わり。 字句解析の次の処理は、構文解析でしたね。 37 構文解析編 38 キーワード(構文解析) • 上向き解析/下向き解析 (bottom up & top down) • Backtracking • 括りだし(factoring) • 左再帰性 • First集合/Follow集合 など 39 いろいろな構文解析法 • 構文解析手法はとてもよく研究されており、 様々な手法が知られている。 • 例えば、 – Early法 – Chart法 などなど (余裕のある人はいずれ 勉強してください) プチお知らせ 自然言語処理(CS学部3年後期開講科目,担当教員:亀田) 40 • 処理対象の文法の性質を利用して、 より効率的な手法がいろいろと提案 されている。 41 • 文脈自由文法 – Early法・Chart法 など • 通常のプログラミング言語は、文脈自由文 法ではないが、その構成要素の多くは文 脈自由文法で記述可能! • 文法の制限の仕方にもいろいろある。 42 LR文法とLL文法(1) • LR文法に対する構文解析法(LR構文解析法) → bottom up 型 • LL文法に対する構文解析法(LL構文解析法) → top down 型 (教科書76-77ページ参照) 43 LR文法とLL文法(2) • LR文法に対する構文解析法(LR構文解析法) → bottom up 型 <= 自動生成向き(Bison) • LL文法に対する構文解析法(LL構文解析法) → top down 型 <= 手作業可能 (教科書76-77ページ参照) 44 LL(k)文法 • 構文解析は、文法規則(書き換え規則)を 適用しつつ進行。 • 適用すべき規則は、一般には複数個存在。 → backtrack発生 → 効率低下(回避すべき!) • k文字先読で適用すべき規則が決定され る文法がある!(LL(k)文法と呼ぶ) Backtrackなし! これは すご い! 45 以下、LL(1)を取り扱います 46 実例で考えよう! 1. 括りだし 2. 左再帰の回避 47 1.括りだし • 文法 S → aBd B → b | bc • 入力: abcd 48 a b c d 49 S B a b c d 50 S B a b c ? d 51 Backtrac発生! S B a b c d 52 S 解析成功! B a b c d 53 • backtrack回避の方法 → 括りだし 54 1.括りだし • 文法 S → aBd B → b | bc S → aBd B → b (c |ε) 55 左再帰の回避 A→Aβ A A Fermat β A 無限降下だ! β 56 左再帰の回避方法 • A→Aα|β A → βA’ A’ → αA’ | ε (教科書81ページ参照) 57 左再帰の例 E→E+T|T T→T*F|F F → ( E ) | id 58 左再帰の回避 E→E+T|T T→T*F|F F → ( E ) | id E → T E’ E’ → + T E’ | ε 59 左再帰の回避 E→E+T|T T→T*F|F F → ( E ) | id E → T E’ E’ → + T E’ | ε T → F T’ T’ → * F T’ | ε F → ( E ) | id 60 LL(1)文法 • LL(1)文法は、1文字先読みすることで、適 用すべき規則が一意に決まる、という性質 を備え持っている。 • つまり、「A→α|β」に対して、1文字先読 みすれば、 「A→α」 と「A→β」のどちらを 適用すればいいのかが決まる。 (効率のよい処理が望める) 61 でも、与えられた文法がLL(1)文法であること をどうやって知ることができるのだろうか? 62 LL(1)文法の判定法 • First • Follow これは後日やりましょ う。少し煩雑ですが、 難しくはありません。 でも重要ですよ! 63
© Copyright 2024 ExpyDoc