Lex & YACCを急に触ってみた

この前の土日に急にLex & YACCを触りたくなって、ここ数日ずっと触っていた。
http://www.linux.or.jp/JF/JFdocs/Lex-YACC-HOWTO.html を見ながら勉強中。


Lexのみの部分ならば例題を見ながらで動くんだけど、YACCの章に入るとこのページを見ながらだけではちっとも進まない。
どこからどこまでが.lなのか.yの部分なのか分からなくてずっと止まっていた。
別のサイトとか見ながらやっと完成したのでソースを載せておく。


example4.l

%{
#include <stdio.h>
#include "example4.tab.h"

void yyerror(const char *str)
{
	fprintf(stderr,"error: %s\n",str);
}


int yywrap(void)
{
	return 1;
}
%}
%%
[0-9]+                  return NUMBER;
heat                    return TOKHEAT;
on|off                  return STATE;
target                  return TOKTARGET;
temperature             return TOKTEMPERATURE;
\n                      /* 改行は無視 */;
[ \t]+                  /* ホワイトスペースは無視 */;
%%


example4.y

%{
#include <stdio.h>
#include <stdlib.h>
%}
%token NUMBER
%token TOKHEAT
%token STATE
%token TOKTARGET
%token TOKTEMPERATURE
%%
commands :
         | commands command
         ;
command : heat_switch
         | target_set
         ;
heat_switch : TOKHEAT STATE
         {
         	printf("\tHeat turned on or off\n");
         }
         ;
target_set : TOKTARGET TOKTEMPERATURE NUMBER
         {
         	printf("\tTemperature set\n");
         }
         ;
%%

int main(void)
{
	yyparse();
	return 0;
}


コンパイル

$ flex example4.l 
$ bison -d example4.y
$ gcc lex.yy.c example4.tab.c -o example4
$ ./example4


今風にlex、yaccでは無くflex、bisonを使用する。
ちなみにlexはflexへのシンボリックリンクだね。
けどbisonとyaccは違うね。

$ which lex
/usr/bin/lex
$ ls -l /usr/bin/lex
lrwxrwxrwx 1 root root 4 2008-06-20 23:33 /usr/bin/lex -> flex

$ which yacc
/usr/bin/yacc
$ ls -l /usr/bin/yacc 
lrwxrwxrwx 1 root root 22 2008-04-03 01:38 /usr/bin/yacc -> /etc/alternatives/yacc

$ which bison
/usr/bin/bison
$ ls -l /usr/bin/bison
 -rwxr-xr-x 1 root root 219932 2007-08-07 07:54 /usr/bin/bison


ポイントとしてはyyerror()、yywrap()をexample4.lに書いたらうまくいった。
example4.yに書くとコンパイルは出来るけど実行してもprintf()が動いてくれない。
理由はよく分からないけど。
もう少し勉強しないと。


しかし、年に何回かこういう風に衝撃的に色々やりたくなる事がある。
ある意味病気だな。