22

最近、複雑なコマンド ライン引数から出力ファイルを生成する既存のツールに、ソース ファイルの解析機能を追加しました。

コマンド ライン引数が非常に複雑になったため、非常に大きなコマンド ラインであるかのように解析されるファイルとして提供できるようになりましたが、構文は依然として扱いにくいものでした。そこで、より合理的な構文を使用してソース ファイルを解析する機能を追加しました。

Windows 用の flex 2.5.4 を使用して、このカスタム ソース ファイル形式のトークナイザーを生成しましたが、うまくいきました。しかし、私はコードが嫌いでした。グローバル変数、変な命名規則、そしてそれが生成する C++ コードはひどいものでした。既存のコード生成バックエンドは flex の出力にくっついていました - 私は yacc も bison も使いません。

私はそのコードに飛び込もうとしていますが、より優れた/より最新のツールを使用したいと考えています。誰かがそれを知っていますか。

  • Windows コマンド プロンプトで実行します (Visual Studio との統合は問題ありませんが、ビルドには make ファイルを使用します)
  • カプセル化された適切な C++ トークナイザーを生成します。(グローバル変数なし)
  • トークン化ルールを記述するために正規表現を使用します (lex 構文と互換性があります)。
  • ファイルの読み取りに c-runtime を使用する (または偽造する) ことを強制しません。(メモリから解析)
  • ルールによってトークナイザーがバックトラックする (または自動的に修正する) 場合に警告します
  • 変数名とメソッド名を完全に制御できます (既存の命名規則に従うことができます)
  • 名前の競合なしに、複数のパーサーを単一の .exe にリンクできます
  • 必要に応じて UNICODE (16 ビット UCS-2) パーサーを生成できます
  • 統合されたトークナイザー + パーサージェネレーターではありません (lex + yacc の置き換えではなく、lex の置き換えが必要です)

トークン化テーブルのみが利用可能であれば、おそらくトークン化テーブルを生成するだけのツールで生活できるでしょう。

4

5 に答える 5

11

Ragel: http://www.complang.org/ragel/ほとんどの要件に適合します。

  • Windowsで動作します
  • 変数を宣言しないので、好きなようにクラス内または関数内に配置できます。
  • 正規表現を分析して、いつバックトラックするかを確認するための優れたツールがあります。(バックトラッキング パーサーを作成する構文を Ragel で使用したことがないため、これについてはよくわかりません。)
  • 変数名は変更できません。
  • テーブル名にはマシン名のプレフィックスが付けられ、「const static」と宣言されているため、同じファイルに複数を入れて、単一のプログラムに同じ名前のテーブルを複数持つことができます (それらが別のファイルで)。
  • 変数は、UChar (または任意の UTF-16 型) を含む任意の整数型として宣言できます。ただし、サロゲート ペアは自動的には処理されません。Unicode 用の特殊な文字クラスもありません (と思います)。
  • 正規表現のみを行います... bison/yacc 機能はありません。

それが生成するコードは、プログラムにほとんど干渉しません。コードも信じられないほど高速で、Ragel 構文はこれまでにないほど柔軟で読みやすいものです。堅実なソフトウェアです。テーブル駆動パーサーまたは goto 駆動パーサーを生成できます。

于 2010-01-30T23:25:35.157 に答える
7

Boost.Spirit.Qi(パーサー-トークン化)またはBoost.Spirit.Lex(トークン化のみ)。私は気が大好きで、Lexも悪くはありませんが、構文解析のニーズに気を使う傾向があります...

Qiの唯一の本当の欠点は、コンパイル時間の増加である傾向があり、手書きの解析コードよりも実行速度がわずかに遅くなります。ただし、一般的には正規表現を使用した解析よりもはるかに高速です。

http://www.boost.org/doc/libs/1_41_0/libs/spirit/doc/html/index.html

于 2010-01-30T23:19:52.013 に答える
6

FlexにはC++出力オプションもあります。
結果は、その解析を行うクラスのセットです。

lexファイルの先頭に以下を追加するだけです。

%option C++
%option yyclass="Lexer"

次に、ソースでは次のようになります。

std::fstream  file("config");
Lexer         lexer(&file)
while(int token = lexer.yylex())
{
}
于 2010-01-30T23:18:35.917 に答える
5

AntlrとGoldParserの 2 つのツールが思い浮かびますが、どちらが適しているかは自分で調べる必要があります。両方のツールで使用できる言語バインディングがあり、C++ ランタイム環境にプラグインできます。

于 2010-01-30T23:08:35.450 に答える
2

boost.spiritYard パーサーが思い浮かびます。lexer ジェネレーターを使用するアプローチは、トークンを指定するために C++ 内部 DSL (ドメイン固有言語) に多少置き換えられていることに注意してください。外部ユーティリティを使用せずにコードの一部であるため、一連の規則に従って文法を指定するだけです。

于 2010-01-30T23:22:39.483 に答える