FlexとBison -実習編-

FlexとBison+アルファ
-実習編東京工科大学
コンピュータサイエンス学部
亀田弘之
内容
1. 実例紹介
2. 基礎練習
– FlexとBisonの書き方・実行手順
3. 実習1
– HTMLのタグを抜き出す
4. 実習2
– 電卓作成
5. 実践的演習
– Pascalパーザ作成
1.実例紹介
2.基礎練習
• Flexの書き方・実行手順
Flex書き方
%%
%%
Flex書き方
各種定義
%{
C言語のコード
%}
%%
Flexの記述
パターン
アクション の列
%%
C言語のコード
実行手順
ライブラリ(fl)
Flex
Program
Flex
Lex.yy.c
文字列入力
gcc
a.exe
出力
7
電卓作成
解説文
概要
簡単な電卓ソフトウェア。
例えば、1+2 と入力すると、計算結果として 3
を表示する。
(1+2)*4 ならば 12、 1+2*4 ならば 9
と表示する。
ただし、変数は使えない。
機能:
キーボードから入力された数式(変数や四則演算以
外の関数は含まないもの)に対して、
その計算結果を画面に出力する。
使い方:
起動方法:コマンドラインにおいて、calc と入力する。
数式入力方法:キーボードから入力する。
プログラムの説明
lexer.l の説明
機能の説明
Flex (Fastlex ) のプログラムで、数式の構文構成要
素 (token) を切り出すプログラムを
自動生成する。生成されるプログラムはC言語で
書かれたものとなる。
ソースコードの説明
大きく3つの部分から構成されている。
1) ヘッダー等の情報
2) トークンの認識・切り出し
3)C言語のソースコード
parser.yの説明
機能の説明
数式の構文解析を行う。このソースプログラムを
Bisonで処理すると、
C言語で書かれた簡易電卓プログラムが生成され
る。
電卓作成(2)
コンパイルの仕方と動作例
% bison -d parser.y
% flex lexer.l
% gcc -o calc parser.tab.c -lfl
% ./calc.exe
1: 1 + 2
3
2: (1+2)*4
12
3:
ソースコード(lexer.l)
%{
#include "parser.tab.h"
#include <stdio.h>
int tokenValue = NONE;
int lineNumber = 1;
%}
%%
[ \t]+
{ /* do nothing */ }
\n { return(ENDOFLINE); }
[0-9]+
{ tokenValue = strtol(yytext, NULL, 10); return(NUMBER); }
"+" { return(PLUS); }
"-" { return(MINUS); }
"*" { return(MULTIPLY); }
"/" { return(DIVIDE); }
"(" { return(LPAR); }
")" { return(RPAR); }
.
{ tokenValue = yytext[0]; return(NONE); }
%%
ソースコード(parser.y)
%{
extern int tokenValue;
extern int lineNumber;
#define prompt printf("\n%5d : ", ++lineNumber)
%}
%start lines
%token PLUS MINUS MULTIPLY DIVIDE LPAR RPAR NONE ENDOFLINE
NUMBER
%%
lines :
|
;
/* null string epsylon */
expression { printf("%d", $1); prompt; } ENDOFLINE lines
expression
|
|
;
:
expression PLUS term { $$ = $1 + $3; }
expression MINUS term { $$ = $1 - $3; }
term { $$ = $1; }
term :
|
|
;
term MULTIPLY factor { $$ = $1 * $3; }
term DIVIDE
factor { $$ = $1 / $3; }
factor { $$ = $1 }
factor :
|
|
;
LPAR expression RPAR
{ $$ = $2; }
NUMBER
{ $$ = tokenValue; }
MINUS NUMBER { $$ = -tokenValue; }
%%
#include
"lex.yy.c"
main(){
printf("%5d : ", lineNumber);
yyparse();
return 0;
}
yyerror(char *s){
printf("%s\n", s);
}
コンパイラの動作概要
• 結局コンパイラはどう動いているのか?
概要を理解しよう
(教科書2.3 p.15~19 を参照のこと)
プログラムの一部(Pascal言語)
Program example;
Var abc, e3, fg: real;
Begin
abc := e3*2.56 + abc/e3;
end
abc := e3*2.56 + abc/e3; の処理
変数名表(1)
番号
変数名
データ型
アドレス
0
1
演算記号表(8)
2
番号
演算
0
:=
1
+
2
-
0
3
*
1
4
/
定数表(2)
番号
2
変数名
データ型
アドレス
abc := e3*2.56 + abc/e3; の処理
変数名表(1)
演算記号表(8)
番号
変数名
データ型
アドレス
番号
演算
0
abc
real
100
0
:=
1
e3
real
104
1
+
2
fg
real
108
2
-
3
*
4
/
定数表(2)
番号
変数名
データ型
アドレス
0
2.56
real
500
1
2
出力:(1,0)(1,1)(2,0)(8,3)(1,0)(1,1)(8,4)(8,1)(8,0)
スタック
_(8,1)(8,1
)(8,4)
その他参考コード
1.
2.
3.
4.
(コード1) lexer.lとparser.y
(コード2) lexer2.lとparser2.y
(コード3) lexer3.lとparser3.y
(コード4) lexer4.lとparser4.y
(Webページに挙げてあります。)
試験へ向けて
• 教科書の 3.1 バッカス記法 と 3.2 構文図式
は、試験に出ます。勉強しておいてください。