Lex と Yacc プログラムでコマンド ライン引数を次のように解析するとします。
./a.out show memory
lex に文字列 "show memory" を解析させたい。どうすればこれを達成できますか?
Lex と Yacc プログラムでコマンド ライン引数を次のように解析するとします。
./a.out show memory
lex に文字列 "show memory" を解析させたい。どうすればこれを達成できますか?
int main(int argc, char **argv) {
if(argc > 1) {
if(argv[1])
yy_scan_string(argv[1]);
}
yyparse();
return 0;
}
引数の間に空白を挿入して、すべての引数を大きな文字列に連結する必要があります。YY_INPUT
次に、テキスト バッファから入力を読み取るようにマクロを再定義して、残りのテキスト バッファを Lex/Yacc にフィードします。
開始は次のようになります。
#include <stdio.h>
#include <string.h>
char *argbuf;
size_t arglen;
int main(int argc, char *argv[])
{
int i;
// Compute total length of all arguments, with a single space between.
arglen = 0;
for(i = 1; argv[i] != NULL; i++)
arglen += 1 + strlen(argv[i]);
// Allocate buffer space.
argbuf = malloc(arglen);
if(argbuf == NULL)
{
fprintf(stderr, "No memory for argument buffer, aborting");
exit(1);
}
// Concatenate all arguments. This is inefficient, but simple.
argbuf[0] = 0;
for(i = 1; argv[i] != NULL; i++)
{
if(i > 1)
strcat(argbuf, " ");
strcat(argbuf, argv);
}
// Here we should be ready to call yyparse(), if we had implemented YY_INPUT().
return 0;
}
昔ながらの方法でそれを行うことの何が問題になっていますか?:
if(argc > 1 && !strcmp(argv[1],"show"))
{
if(argc > 2)
{
if(!strcmp(argv[2],"memory"))
...
else if(!strcmp(argv[2],"cpu"))
...
else ...
}
}
その上、getopt()
そして友達がより適切です。
私のブログ記事Parsing command line parameters with Yacc & Flexでは、実際の例でこれについて説明しています。引数文字列を連結する必要はありません。理由は記事に書いてあります。
宣伝文句は次のとおりです。
ときどき誰かがやってきて、Yacc と Flex でコマンド ライン パラメータを解析する方法を尋ねてきます。これはかなり簡単ですが、生成されたコードを正しく理解するにはある程度の知識が必要です。
ここでは、これを行うソース テンプレートを示します。ユーザーは、文法とスキャン ルールを編集するだけで済みます。C、Yacc、および Flex に関するある程度の知識があることを前提としています。
コードは WTFPL ライセンスです
このテンプレートは、Berkeley Yacc および Flex の reflex バリアント用に作成されています。おそらくいくつかの変更を加えて、GNU Bison および SourceForge Flex で動作するようにすることができます。
得られるのは、字句と文法の仕様を挿入するだけのテンプレートです。
テンプレート自体の使用およびブログ コメントへの適応について質問してください。