H19 No7 Ver1

Document Sample
H19 No7 Ver1 Powered By Docstoc
					言語プロセッサ2007
   -No.7-
   東京工科大学
コンピュータサイエンス学部
    亀田弘之
              今日の内容
1.       字句解析プログラムの作成方法
     •    手書きの方法
     •    Flexを利用する方法
2. 構文解析
     •    解析手法の種類
     •    左再帰とその除去
     •    括りだし
     •    FirstとFollow
           字句解析の実際
• 「符号なし数」の字句解析
  num → digit+ ( . digit+)? (E(+|-)?digit+)?
  => n → d+( . d+)? (E(+|-)?d+)?
  => num → d+(.d+|ε)( (E((+|-)|ε)) d+|ε) |ε)
          Flexのソースコード例                          参考

D [0-9]

%%
[\t ] { printf("Tab or Space\n"); }
{D}+(\.{D}+)?(E(\+|\-)?{D}+)? {printf("%s\n", yytext); }
. { printf("NG %s\t", yytext); }
%%
    識別子のシンタックス

• letter → a|b|c|…|z|A|B|C|…|Z
• digit → 0|1|2|…|9
• id → letter (letter|digit)*
         Flexのコード例
LETTER     [a-zA-Z]
DIGIT      [0-9]

%%
[\t ] { printf("Tab or Space\n"); }
{LETTER}({LETTER}|{DIGIT})* {printf("id=%s\n",
  yytext); }
. { printf("NG %s\t", yytext); }
%%
       符号なし数のシンタックス

•   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
トークン認識プログラム作成
• (教科書を参考に作成してみよう!)
プログラムの文法(例)
• stmt → if expr then stmt
         | if expr then stmt else stmt
         |ε
• expr → term relop term
         | term
• term → id
         | num
•   if → if
•   then → then
•   else → else
•   relop → <|<=|=|<>|>|>=
•   id → letter(letter|digit)*
•   num → digit+(.digit+)?(E(+|-)?
• delim → blank|tab|newline
• ws → delim+
  トークン-正規表現パタン
正規表現 トークン 属性値
ws    (なし) (なし)
if   if    (なし)
then then  (なし)
else else  (なし)
id   id    記号表のエントリへの
num  num   ポインタ
<    relop LT
<=   relop LE
=    relop EQ
<>   relop NE
>    relop GT
>=   relop GE
オートマトンの作成
             =

    >
0       6               7


            other
                    8
 0                   1                   2
         <                   =
                                     Return(relop,LE)


                              >
                                         3   Return(relop,NE)

                             other


>                                        4   Return(relop,LT)
         =
                 5

                      Return(relop,EQ)
             =
     6                                   7 Return(relop,GE)


                     other
                                         8   Return(relop,GT)
図. 関係演算子の遷移図
             letter


    letter            other
9             10              11

                        Return(get_token( ),
                               install_id( ))
             digit

図. 識別子とキーワードに対する遷移
         図
                                      17
12
         digit                              digit
                               -
           13      E                                   19
                                    +
digit

     .                         16
                                    digit           other

                                            18

                          E
 14                                     digit
                  15
          digit

                       digit
                                     図. 数の遷移図(1)
             digit                           digit


20
     digit
             21
                      .        22
                                     digit
                                              23

                                                     24

                      digit


              digit                 other
      25                  26                  27




                                    図. 数の遷移図(2)
単純な遷移図
        b

    a   1       a


0                   2


            b
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; }
  }
}
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; }
  }
}
 簡単な遷移図
             b

     a       26       a


25            a           27

         b        b
             28
      練習問題
1. 直前のページのオートマトンをシミュレー
   トするプログラムを作成せよ。
2. 符号なし数を処理する字句解析プログラ
   ムを作成せよ。
3. 次ページに示した(C言語の)浮動小数
   点定数を処理する字句解析プログラム
   を作成せよ。
参考: (C言語の)浮動小数点定数

                .       Numbers



  Numbers


                                            f
  Numbers   .

                    e        +              l

  Numbers                         Numbers

                    E        -              F


                                            L
今度はflexを使ってみよう!
             手順
                            ライブラリ(fl)



Flex             Lex.yy.c
          Flex                 gcc
Program




           文字列入力              a.exe     出力
   Flexプログラムの記述(1)
delim    [ \t\n]
ws       {delim}+
letter   [a-zA-Z]
digit    [0-9]
id       {letter}({letter}|{digit})*
number   {digit}+(\.{digit}+)?(E[+\-]?{digit}+)?
%%
     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);}
       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);}
%%
   Flexプログラムの記述(4)
install_id( ){
  static int id_ptr=0;
  return(id_ptr); }

install_num( ){
  static int num_ptr=0;
  return(num_ptr); }
Flexのデモ
          手順
1. Flexのプログラムを書く。
2. Flexのプログラムをflexにかける。
3. 出力ファイルlex.yy.cをgccでコンパイル
   する。

4. 出力a.exeを実行する。
5. さまざまな文字列を入力する。
             手順
                            ライブラリ(fl)



Flex             Lex.yy.c
          Flex                 gcc
Program




           文字列入力              a.exe     出力
           実際の手順
C:\> flex sample01.l
C:\> gcc lex.yy.c –lfl
C:\> a.exe



それでは、実際にやってみよう。
字句解析から構文解析へ

以上で、字句解析は終わり。
字句解析の次の処理は、構文解析でしたね。
構文解析編
  キーワード(構文解析)
• 上向き解析/下向き解析
  (bottom up & top down)
• Backtracking
• 括りだし(factoring)
• 左再帰性
• First集合/Follow集合 など
 いろいろな構文解析法
• 構文解析手法はとてもよく研究されており、
  様々な手法が知られている。
• 例えば、
 – Early法
 – Chart法
    などなど (余裕のある人はいずれ
                勉強してください)
    プチお知らせ
     自然言語処理(CS学部3年後期開講科目,担当教員:亀田)
• 処理対象の文法の性質を利用して、より
  効率的な手法がいろいろと提案されてい
  る。
• 文脈自由文法
 – Early法・Chart法 など
• 通常のプログラミング言語は、文脈自由文
  法ではないが、その構成要素の多くは文
  脈自由文法で記述可能!
• 文法の制限の仕方にもいろいろある。
    LR文法とLL文法(1)
• LR文法に対する構文解析法(LR構文解析法)
    → bottom up 型
• LL文法に対する構文解析法(LL構文解析法)
    → top down 型


        (教科書76-77ページ参照)
     LR文法とLL文法(2)
• LR文法に対する構文解析法(LR構文解析法)
    → bottom up 型 <= 自動生成向き(Bison)
• LL文法に対する構文解析法(LL構文解析法)
    → top down 型 <= 手作業可能



          (教科書76-77ページ参照)
     LL(k)文法
• 構文解析は、文法規則(書き換え規則)を
  適用しつつ進行。
• 適用すべき規則は、一般には複数個存在。
    → backtrack発生
    → 効率低下(回避すべき!)
• k文字先読で適用すべき規則が決定され
  る文法がある!(LL(k)文法と呼ぶ)
                       これは
                        すご
                        い!
        Backtrackなし!
以下、LL(1)を取り扱います
   実例で考えよう!
1. 括りだし
2. 左再帰の回避
         1.括りだし
• 文法
 S → aBd
 B → b | bc


• 入力: abcd
a   b   c   d
    S

        B
a   b       c   d
    S

    B
a   b   c   d
        ?
Backtrac発生!
              S

                  B
      a   b           c   d
    S       解析成功!

        B

a   b       c   d
• backtrack回避の方法
     → 括りだし
         1.括りだし
• 文法
 S → aBd      S → aBd
 B → b | bc   B → b (c |ε)
           左再帰の回避

  A→Aβ
                     A
無限降下だ!           A       β

             A       β
  Fermat
    左再帰の回避方法
• A→Aα|β

  A → βA’
   A’ → αA’ | ε



             (教科書81ページ参照)
        左再帰の例
E→E+T|T
T→T*F|F
F → ( E ) | id
        左再帰の回避
E→E+T|T          E → T E’
T→T*F|F          E’ → + T E’ | ε
F → ( E ) | id
        左再帰の回避
E→E+T|T          E → T E’
T→T*F|F          E’ → + T E’ | ε
F → ( E ) | id

                 T → F T’
                 T’ → * F T’ | ε

                 F → ( E ) | id
       LL(1)文法
• LL(1)文法は、1文字先読みすることで、適
  用すべき規則が一意に決まる、という性質
  を備え持っている。
• つまり、「A→α|β」に対して、1文字先読
  みすれば、 「A→α」 と「A→β」のどちらを
  適用すればいいのかが決まる。
  (効率のよい処理が望める)
でも、与えられた文法がLL(1)文法であること
をどうやって知ることができるのだろうか?
     LL(1)文法の判定法
• First
• Follow


      これは次回やりましょ
      う。少し煩雑ですが、
      難しくはありません。

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:11
posted:3/13/2012
language:Japanese
pages:62