スキップしてメイン コンテンツに移動

bison/flex

Bison / Flexを導入してみる

開発環境

OSはWindows、IDEはVisual Studio (2022) で行います。
マイプログラミング言語が作れるようになるらしいです。使ってみたかっただけです。
Windows向けにポーティングされたWinFlexBisonを使う方法とWSL上でBison/Flexを動かす方法の2つを調べました。

WinFlexBison


ライセンスはFlexがBSD, Bison GPLv3となっています。ただし、Bisonを使ったからと言って生成物にはGPLは波及しない(仕組み上、生成物にコピーが含まれるが特例扱いだった気がします)なので、その辺は大丈夫(なはず)です。

ページを見るとDownloadsリンクがあるので、そちらから安定板(win_flex_bison-version.zip)をダウンロードします。

bison flex downloads

プロジェクト作成

一連の流れについてはこちらのページが詳しいです。
設定だけでなく次のページ以降に実際の開発についても記述があるのでおすすめです。

概要としては
  1. メイン(開発する言語)のソリューションおよびプロジェクトを作成
  2. FlexおよびBisonのファイルを配置するためのプロジェクトを作成
  3. カスタムビルドルールを設定
といった感じです。

WSL2 + Bison / Flex

WinFlexBisonはWindows上で動かすには最適でバイナリをプロジェクトに登録しておけばバージョンの問題とかも気にしなくて良くなるという利点があります。ただ、現在だとWSLでオリジナルのBison/Flexを動かせるのでそちらを使うという手もあります。

・WSL(Ubuntu)をインストール
    > wsl --install
・UbuntuにBison/Flexをインストール
    いずれもパスワードの入力が必要。
    > wsl sudo apt-get update
    > wsl sudo apt-get install -y bison flex

Windowsで動かすにあたっていくつか注意点があります。
1.unistd.h
Flexのコードに #define YY_NO_UNISTD_H を追加してください。

オリジナルのFlexが生成するコードにはunistd.hを使用するものが含まれますが、Windows(Visual Studio)にはunistd.hがないためコンパイルエラーとなってしまいます。そこでunistd.hを使わない宣言を追加する必要があります。

2. POSIX関数名
Microsoftは色々考えてPOSIX関数名は非推奨にしたそうです。関数自体は用意していてアンダースコアがPrefixとして付いています。そういうこともあってisattyとfilenoはそのままだと動きません。そこで以下のいずれかの方法で対応する必要があります。

A. 別名を定義
マクロで別名を定義することでMicrosoftが用意した関数を呼び出します。

#if defined(_WIN32)
#define YY_NO_UNISTD_H
#include <io.h>
#define isatty _isatty
#define fileno _fileno
#endif

B. 警告を抑制
B-1. プリプロセッサ定義
オプションのプリプロセッサ定義に_CRT_NONSTDC_NO_WARNINGSを追加します。これにより非推奨の関数名を使うことが許容されます。
B-2. ファイル内の非推奨警告を抑制
#pragmaを使ってファイル内の非推奨警告を抑制する方法もあります。

#if defined(_WIN32)
#define YY_NO_UNISTD_H
#include <io.h>
#pragma warning(disable : 4996)
#endif

個人的にはプロジェクト設定での対応は好みではないのですが、Windows以外でも動かすかもしれず、そこでもPOSIX関数を使うかもしれないのであればB-1で良いと思います(実際には_CRT_SECURE_NO_WARNINGSとか他の抑制も必要になって鬱陶しいのでC4996自体を抑制したくなったりします)
逆に非推奨は非推奨として認めるべしって感じであれば都度適切に対応するAが良いでしょう。
B-2はB-2で修正内容と影響範囲のバランスが取れてますよね。

BisonやFlexによるコード生成についてはビルド前イベントとして登録しておけば覚えなくても良いので楽ちんです。登録内容は以下のものでどうでしょう。
  • wsl flex -oFlexの出力ファイル名 Flexの定義ファイル名
    • Flexの実行
  • powershell -Command "(Get-Content Flexの出力ファイル名) -replace '\r?\n', \"`r`n\" | Set-Content Flexの出力ファイル名"
    • Flexの出力ファイルの改行コードをCRLF(\r\n)に統一
  • wsl bison -dv -oBisonの出力ファイル名.cpp Bisonの定義ファイル名
    • Bisonの実行
  • powershell -Command "(Get-Content Bisonの出力ファイル名.hpp) -replace '\r?\n', \"`r`n\" | Set-Content Bisonの出力ファイル名.hpp"
    • Bisonの出力ヘッダの改行コードをCRLF(\r\n)に統一
    • 出力をcppにした場合はhpp、cならh
  • powershell -Command "(Get-Content Bisonの出力ファイル名.cpp -replace '\r?\n', \"`r`n\" | Set-Content Bisonの出力ファイル名.cpp"
    • Bisonの出力ソースの改行コードをCRLF(\r\n)に統一

言語名がClangなら以下のような感じ
wsl flex -oClang.flex.cpp Clang.l
powershell -Command "(Get-Content Clang.flex.cpp) -replace '\r?\n', \"`r`n\" | Set-Content Clang.flex.cpp"
wsl bison -dv -oClang.tab.cpp Clang.y
powershell -Command "(Get-Content Clang.tab.hpp) -replace '\r?\n', \"`r`n\" | Set-Content Clang.tab.hpp"
powershell -Command "(Get-Content Clang.tab.cpp) -replace '\r?\n', \"`r`n\" | Set-Content Clang.tab.cpp"

「毎回コード生成するのは…」と思うお方はバッチファイルにしてプロジェクトに配置するのもありですね。

細かな話

公式マニュアルを読んでみると歴史的な経緯によるLALRパーサの挙動で謎のConfilictとかあるけどすまんな、みたいな話があったりします。
回避方法(%define lr.type ielr, LRテーブルのタイプをIELRにする)も載っていたりするので、本格的に開発を進める前にやはり眺めておいた方が良いでしょう。

それとよく見かける使用方法はC言語としてコードを生成しますが、C++としてコードを生成することも可能です。
やはり、先ほどのマニュアルにも記載はありますが、以下のページにも奮闘の記録があるので参考にするとよろしいでしょう。


コメント

このブログの人気の投稿

KoeMill V.0.9.0.0 リリース

KoeMillのV.0.9.0.0をリリース KoeMillは、音声認識による文字起こしを行うソフトウェアです。音声認識モデルにはWhisperが採用されており動画や音声から自動的に高品質な文字起こしができるため、煩雑な手作業を省くことができます。 オフラインで動作するため、ネットワークの遅延などによる遅れやプライバシーに関する懸念もありません。また、GPUを利用することで高速な処理を実現します。 ダウンロードページ

CapCap V.0.9.2.7 リリース

CapCapのV.0.9.2.7をリリース 主な変更内容 HTTP POST設定でヘッダの設定に対応 HTTP POST設定でJSONのオブジェクトおよび配列に対応 HTTP POST設定を大項目ごとに折りたためる機能に対応 サンプルプリセット(ChatGPT API)を追加 プリセット複製時に複製先の変更が複製元に及んでいた不具合を修正 HTTP POST設定 新たにリクエストヘッダを設定できるようになりました。これによりAuthorizationによる認証などヘッダが必要なAPIにも対応できるようになりました。合わせて、これまで設定することが出来なかったJSON ObjectおよびArrayについても設定できるようになりました。 ChatGPT APIについて サンプルプリセットを追加しました。HTTP POSTのヘッダおよびJSON ArrayとObjectに対応したため、その対応例となります。 継続的に使おうとすると費用が発生することになるので、無料枠が残っている間に遊んでもらえると幸いです。 DLページ: Home

CapCap V0.9.2.5 リリース

CapCapのV0.9.2.5をリリース 主な変更内容 段落検出機能を追加 字幕モードの名称を変更(Readability -> Text, Layout -> Item) 段落検出 テキストの行同士の距離をもとに段落を検出することが出来るようになりました。 段落の検出および段落間への空行挿入が行なえます。 これまではテキストをひと繋がりの文章として認識していましたが、段落ごとに分離されることで可読性の向上が見込めます。 文章に対して段落が多い場合や段落が2行からなる場合などには精度が落ちる傾向にあります。また実験的機能の側面があるため問題点等あればご報告いただけると助かります。 DLページ: Home