言語理論とコンパイラ

第五回: 字句解析ツール flex

2013 年 5 月 17 日

http://www.sw.it.aoyama.ac.jp/2013/Compiler/lecture5.html

Martin J. Dürst

AGU

© 2005-13 Martin J. Dürst 青山学院大学

今日の予定

前回までのまとめ

全て同じ力を持って、お互いに変換可能、正規言語を定義・受理

コンパイラの段階

字句解析 (lexical analysis)

構文解析 (parsing; syntax analysis)

意味解析 (semantic analysis)

最適化 (optimization)

コード生成 (code generation)

コンパイラの構造

字句解析の実装

主な要点:

選択肢:

字句解析の自動化

flex の概要

cygwin の使い方 (参考)

cygwin とハードディスク (参考)

flex の動作

flex の使い方

  1. 独自のファイル処理 (正規表現によるファイルの一部の認識・変更):

    main から yylex() 関数を一回呼ぶ

  2. 構文解析から呼ばれる字句解析:

    構文解析から yylex() を繰り返し呼んで、トークンを return で返す

今日の演習・宿題では 1.、授業の後半では bison とともに 2.を使用

flex の入力形式の一例

        int num_lines = 0, num_chars = 0;
%%
\n      ++num_lines; ++num_chars;
 .       ++num_chars;
%%
main()
{
        yylex();
        printf( "# of lines = %d, # of chars = %d\n",
                num_lines, num_chars );
}

int yywrap () { return 1; }

 

flex の入力形式の骨格

宣言など (C 言語)
宣言など (C 言語)
%%
正規表現    実行文 (C 言語)
正規表現    実行文 (C 言語)
正規表現    実行文 (C 言語)
%%
関数など (C 言語)
関数など (C 言語)

 

flex の入力形式の構造

flex 専用の指示と C プログラムの一部分が混在

主に、二つの %% で区切られている三つの部分からなる:

  1. 準備・設定部分:
    C の #include、グローバル変数の定義と初期化、良く使う字句の定義など
  2. 受理する正規表現 (字句規則) とその場合に実行するプログラムの断片
  3. 残りの C のプログラム (関数など)

C 言語そのものと違って、改行、字下げが解釈を左右

 

flex の演習 1

flex の入力形式の一例」のスライドの flex 用プログラムを処理、実行

  1. flex の入力形式の一例」を test.l にコピー
  2. > flex test.llex.yy.c を作成
  3. > gcc lex.yy.ca.exe を作成
  4. > ./a <file でプログラムを実行

flex の勉強の仕方

flex の基本動作

 

flex の演習 2

一般のテキストを XML の要素の内容にする場合には次の表に示される変換が必要
flex で (その変換と) 逆変換のプログラムを作成

テキスト XML
' &apos;
" &quot;
& &amp;
< &lt;
> &gt;

flex の演習 3: 数字の発見

入力をそのまま出力、しかし数字でしたら、その前に >>>、その後に <<< をつけるプログラムを flex で作成

入力例:

abc123def345gh

出力例:

abc>>>123<<<def>>>345<<<gh

ヒント: 正規表現でつかんだ文字列は yytext として使用可能

flex の演習 4: Ruby 用字句解析

提出期限と場所: 2013 年 5 月 30 日 (木) 19:00 まで O 棟 5 階の O-529 号室の前の箱に投入

(5月24日 (金) の授業で質問できるように、早めに取りかかるのが得策)

提出形式:

Ruby の次の字句を認識、一行ごとに出力:

種類 説明 出力 (例)
インスタンス変数 先頭に @ @abc Instance variable: @abc
クラス変数 先頭に @@ @@def Class variable: @@def
メソッド名 最後に !, ?, 又は = 一文字 nil? Method: nil?
メソッドまたは局所変数 先頭が小文字 my_var Method or variable: my_var
グローバル変数 先頭は $ $global Global variable: $global
コンスタント 先頭が大文字 String Constant: String
十新数の整数 先頭は 0d, 0D, 又は 0 意外 1_234 Decimal Integer: 1234
八進数 先頭は 0 0765 Octal Integer: 501
十六進数 先頭は 0x 又は 0X 0xAB_D3 Hex Integer: 43987
二進数 先頭は 0b 又は 0B 0b1010_1100 Binary Integer: 172
コメント # から行末まで # hello Comment: hello
[エラー] 空白類意外処理できない文字一つ \ Error: '\'

発展問題: Ruby の他の字句も対象 (例: 演算子、文字列、正規表現など)。

 

flex でよく出る問題

宿題のヒント