by JEWELRY BaB
--
更新履歴
2003/9/1 ハマリポイントその7追記
2002/9/14 bisonのライセンスについて追記
2002/9/8 初稿




flex / bison をWIN32に導入するまで
Project GnuWin32でWin32で走るコンパイル済み実行ファイルがダウンロード出来ます。ダウンロードします。ありがたくいただきます。
展開して、
を、パスの通っているフォルダに。

環境変数 BISON_SIMPLE を設定する。
例) D:\Tool の場合
SET BISON_SIMPLE=D:\Tool\bison.simple



あとは、煮るな焼くなり。





参考(になる・にした)日本語のWEB
マニュアル・ドキュメント

実例・ソース





参考書は?
実際に参考にしたのは、





ハマリポイント
1)日本語がうまいこといかない(flex)
実行時オプション
-8
追加で、うまくいきました。





2)行番号がほしい(flex)
lex であれば yylineno 変数があるが、flex にはない。

オプション(覚えていません)で有効にすることは出来るが、-C オプションで同時に使用できない場合があるのでやっぱだめ。

解決法は、
\n
が来たら用意しておいた変数をカウントするようなルールを作っておけばOK。
注意点は%startで指定しているすべてのスタート条件に対しておこなうこと。


参考 http://www.geocities.co.jp/SiliconValley-Oakland/3432/man/flex/flex-ja_9.html#SEC67





3)リエントランスなのを作りたい
lexファイル、Cソースを書くところで
#undef YY_DECL
#define YY_DECL int yylex(YYSTYPE* yylval)
を記述。

bison ソースファイルで、
%pure_parser
を指定。

bison で出力するパーサーソースファイルがC++用であれば、%unionの直後ぐらいに
%{
int yylex(YYSTYPE* yylval);
%}
を記述。
参考 http://www.sip.eee.yamaguchi-u.ac.jp/kou/bison-flex.html

実際に呼ぶときは、
yyin = fopen(filename, "r");
yyrestart(yyin);
yyparse();
fclose(yyin);
こんな感じ。 yyparse 前に、yyrestart を呼ぶと。
参考 http://www.gnu.org/manual/flex/html_mono/flex.html で reent を検索。





4)ライセンスは?
ともにGNU。
だが、
flex は not GNU(意味不明、モノ自体がGNUディレクトリの外にある)。
bison は version 1.25 から商用利用が可能らしい。

参照 http://www.tokumaru.org/bbs/bbs_backnumber_006.htm

気になるなら、森公一郎氏公開のkmyaccを使わせていただくのもいいかも(未確認)。

(2002/9/14追加)
bison 1.35の「bison.simple」ファイルには以下の記述がある。
通常はbisonが出力した構文解析ルーチンCソースに埋め込まれる。
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
軽く日本語に訳してみると、
/* 特例として、このファイルがBisonが出力したファイルであれば、
あなたは、この出力ファイルを制限なしに使用することが出来る。
この特例は、Bisonのバージョンが1.24の時にFSFにより追加された。*/
OKっぽいね。





5)コンソールがなれない
MENISYS氏公開のbison & flex compiler for Windows GUIを使わせていただくのもいいかも(未確認)。
ソースコードジェネレータという面からみて本格的に導入するのであれば、makefile を書く方が絶対。
遊びなら適当に。でもきっと後々プロジェクトサイズがでかくなるから、早いうちにmakefileつくっておいたほうがいいよ。





6)makefileがよくわからない
実際につかっているものです。Borland make用です。適当に参考にしてください。
もっとキレイに書けるはずです。
探すと、makefileジェネレータ的なモノもあると思うのでそれを利用するのもいいかも。
################################################
## コンパイラ                                 ##
################################################
CC              = bcc32
CFLAGS          = -O2 -OS -Ov -Oi -Og -6 -X -a16 -d -y- -v- -H -Hc -x-
FLEXFLAGS       = -Cfa -8
BISONFLAGS      = -d -y
NAME            = bvm
ALLOBJS         = $(LEXYACCOBJS) $(BABSTDOBJS) $(OBJS) $(OTHEROBJS)
LEXYACCOBJS     = lexer.obj parser.obj dev_flexbison.obj
OTHEROBJS       = ..\filectrl2\filectrl2.obj
BABSTDOBJS      =                               \
        $(BABSTDDIR)\BaBProperty.obj            \
        $(BABSTDDIR)\BaBStream.obj              \
        $(BABSTDDIR)\BaBString.obj              \
        $(BABSTDDIR)\BaBStringList.obj          \
        $(BABSTDDIR)\BaBMemoryIO.obj
OBJS            =                               \
        ArgTypeCheck.obj                        \
        CPrePro.obj                             \
        Execute\BvmArray.obj                    \
        Execute\BvmBuildinFunction.obj          \
        Execute\BvmCriticalSection.obj          \
        Execute\BvmEventFlag.obj                \
        Execute\BvmProcess.obj                  \
        Execute\BvmSema.obj                     \
        Execute\BvmStringHolder.obj             \
        Execute\BvmSyncObjectBase.obj           \
        Execute\BvmThread.obj                   \
        GotoManager.obj                         \
        IdManager.obj                           \
        InstractionManager.obj                  \
        JumpManager.obj                         \
        CompileManager.obj                      \
        LineManager.obj                         \
        PragmaManager.obj                       \
        StringManager.obj                       \
        Symbol.obj                              \
        SymbolManager.obj                       \
        DynamicLinkManager.obj                  \
        dllmain.obj




################################################
## ディレクトリ                               ##
################################################
BABSTDDIR       = ..\BaBSTD
WZDIR           = "C:\Program Files\WZ EDITOR"




################################################
##                                            ##
################################################
all :                                           \
        parser.cpp                              \
        parser.hpp                              \
        lexer.cpp                               \
        $(NAME).dll                             \
        _test.exe                               \
        bvmC\include\BuildinFunction.h          \
        bvmC\include\BuildinFunctionType.h      \
        $(WZDIR)\$(NAME).dll                    \
        $(WZDIR)\MACRO\$(NAME).h

clean :
        -del parser.cpp
        -del parser.hpp
        -del lexer.cpp
        -del *.obj
        -del $(NAME).dll
        -del Project1.exe
        -del _test.exe
        -del *.inc
        -del *.tds
        -del *.~*
        -del Execute\*.obj
        -del Execute\*.~*
        -del bvmC\*.obj
        -del bvmC\*.tds
        -del bvmC\*.~*
        -del bvmC\*.lib
        -del bvmC\$(NAME).dll
        -del bvm_vc.*
        -del bvm_vc\Debug\*.* /Q
        -del bvm_vc\Release\*.* /Q

fb : parser.cpp parser.hpp lexer.cpp

parser.cpp parser.hpp : $(NAME).y
        bison  -oparser.cpp $(BISONFLAGS) $(NAME).y

lexer.cpp : $(NAME).l
        flex  -olexer.cpp $(FLEXFLAGS) $(NAME).l

_test.exe : _test.cpp $(ALLOBJS) $(NAME).h
        $(CC) $(CFLAGS) _test.cpp $**
#..\new_over\new_over.cpp

bvmC\include\BuildinFunction.h : Execute\BuildinFunction.h
        copy Execute\BuildinFunction.h bvmC\include\BuildinFunction.h
bvmC\include\BuildinFunctionType.h : Execute\BuildinFunctionType.h
        copy Execute\BuildinFunctionType.h bvmC\include\BuildinFunctionType.h

$(WZDIR)\$(NAME).dll : $(NAME).dll
        copy $(NAME).dll $(WZDIR)\$(NAME).dll
$(WZDIR)\MACRO\$(NAME).h : $(NAME).h
        copy $(NAME).h $(WZDIR)\MACRO\$(NAME).h

$(NAME).dll : $(ALLOBJS)
        $(CC) $(CFLAGS) -WD -e$(NAME) $**
        copy $(NAME).dll bvmC\

.cpp.obj :
        $(CC) $(CFLAGS) -o$@ -c $<
					



7)%unionでメンバーに(C++の)クラスを指定できない(bison)
%union部は、C++でのunionに展開されるので%unionのメンバーにクラスを指定できないことになります。
C++言語ではunionメンバーに、クラスと言うよりは明示的なコンストラクタとかデストラクタとかいろんな演算子とか、とにかくそんなのがいるとダメということです、きっと。
考えればそうだよね、インスタンスができるときにどのコンストラクタを呼ぶの?全部呼ぶの?ってコンパイラが困ります、きっと。
話がそれました。

回避するには、そのクラスのポインタをメンバーにするのがてっとり早いです。
それでも、実体をメンバーに納めたいケースに出会った場合はどうしましょう。

自分はstructとして扱うことで回避しました。
具体的には#define, #undef を使いました。

例)
bison 構文解析ソースファイル (*.y)で
%{
#define union struct
%}

%union{
  union{         // structになってしまうけど、気持ちの問題
    int           Int;
    float          Float;
    bvm::E_Opecode    Opecode;
    C_Symbol *      Symbol;
    C_Symbol::E_Kind   SymbolKind;
    bvm::E_Type      SymbolType;
    int           String;
  };
  C_StringSymbol     Name;        // これがクラス
  S_FunctionInfo     FunctionInfo;    // これがクラス
}
%{
#undef union
%}

flex字句解析ソースファイル(*.l) で
// parser.hpp は bison をかけたときにできるヘッダーファイル。
%{
#define union struct
#include "parser.hpp"
#undef union
%}