• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:flex+bisonで簡単なパーサ)

flex+bisonで簡単なパーサの作成方法とは?

このQ&Aのポイント
  • flexとbisonを使用して簡単な設定ファイルパーサを作成する方法について教えてください。
  • bisonで$1, $2などの値が正しく出力されない問題について、どこが原因か教えてください。
  • 作成したパーサを実行した際に、期待した出力と異なる結果が出力される問題について、対処方法を教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

最終的にどういうパーサーを作りたいのかわからないのでちと外しているかもしれませんが > レクサがトークンをstrcatせず(終端文字を残したまま)連結したものを > 使うことはできないんでしょうかねえ。。。と無駄なことを考えてしまいま した。 メモリの消費を抑えたいというのであれば、aaaのような名前は 記号表に登録してその結果を返すようにし、= のような記号は yylval.str_value = "=" のように固定の文字列のアドレスを入れちゃえばどうでしょう? 1234のような定数は yylvalに数値定数を保持するメンバーを増やして それに格納するようにするとか。 yaccをつかったインタプリタはソースが結構見つかると思うので 参考にしてみてはどうでしょう?

bobviv
質問者

お礼

たびたびご回答いただき恐縮です。私が思ったのは、lex.yy.cでマッチしたトークンを次々とバッファに突っ込んでいるループで(ソースを見たところ、一時的に終端文字を入れたあと、ループ冒頭で終端文字を上書きして消してしまっています)終端文字を消さないように残したままにすれば、のちにパーサのアクションコードから'$1'などでトークンを文字列として参照したときに、うまくいくのではないかということです。で、そのようにいじってみましたら、やっぱり二番めのトークンを正しく認識できずエラーになってしまいました。いまはどうして二番め以降がエラーになるのかを知りたいと思っていますが、どうもまだ全体の仕組みすらよく分かっていない状態ですんで、たぶん高い確率で挫折すると思います^^。  要するに、生意気にもflexとbisonの動作を変更しようと思っていたわけですがそんなに簡単じゃないですね当然。ご紹介の方法も含めてユーザとしての工夫を考えるのが第一でした。  どうもありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

flexではなくlexを使うと明確にわかるのですが、yytextはトークンごとに 別の領域を確保するということはしません(extern char yytext[]と宣言される)。 assign: noeq_exp EQ exp_l { printf("<assign>%s|%s|%s\n", $1, $2, $3); printf("address: $1=%p, $2=%p, $3=%p\n", $1, $2, $3); } のようにしてアドレスをチェックするとよくわかると思います。 私の環境では address: $1=0x661f88, $2=0x661f8b, $3=0x661f8c のようになりました。 ということで、お手軽に済ませるには %% [=:] yylval.str_value=strdup(yytext); return EQ; [^=:\t\n]+ yylval.str_value=strdup(yytext); return TOKEN; [ \t]+ yylval.str_value=strdup(yytext); return WS; \n yylval.str_value=strdup(yytext); return CR; %% トークンごとに別の領域を確保してそこにコピーしましょう。

bobviv
質問者

お礼

 なるほど。パーサの方はトークンとしてそれぞれヌル終端された文字列を期待しているのに、上のようなレクサのコードでは一連のトークンをstrcat済みの単一バッファ上のトークンごと先頭ポインタが渡されているだけってことですか。。。しかし、トークン毎にいちいちメモリ領域を確保するのは無駄なことですねえ。レクサがトークンをstrcatせず(終端文字を残したまま)連結したものを使うことはできないんでしょうかねえ。。。と無駄なことを考えてしまいました。意外とうまくいきそうな気がするんですが、たぶん気のせいでしょう^^。  とても勉強になりました。有難うございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • bison&flex

    Linux上で、以下の記述を行い、一番最後に参照のFLEXのマニュアルにしたがって、コンパイルしてみたところ、alloca.cなどと言うファイルは存在しないとのエラーが出ました。bison単独では、コンパイルと実行とが可能なのですが、flexとの連携方法が分かりません。他のWeb上の例では、alloca.cなどを使ったコンパイル例も無いわけで、実際のところ、どのように変更すれば、コンパイル出来るようになるのか、追加のインクルードファイルなども含めて、教えてください。 bison -d parse.y flex -I parse.l gcc -o parse alloca.c parse.tab.c lex.yy.c Bisonの記述 %{ #define YYSTYPE double #include <stdio.h> /*#include "lex.yy.c"*/ %} %token NUM %% input: /* empty */ | input line ; line: '\n' | exp '\n' { printf("\t%.10g\n",$1);} ; exp: NUM {$$ = $1; } | exp exp '+' {$$ = $1 + $2; } | exp exp '-' {$$ = $1 - $2; } | exp exp '*' {$$ = $1 * $2; } | exp exp '/' {$$ = $1 / $2; } ; %% #include <ctype.h> /*yylex () { int c; while((c = getchar ()) == ' ' || c == '\t') ; if (c== '.' || isdigit(c)) { ungetc(c,stdin); scanf("%lf",&yylval); return NUM; } if(c == EOF) return 0; return c; } */ main() { yyparse(); } yyerror(s) char *s; { printf("%s\n",s); } FLEXの記述 %{ #include <stdio.h> #include "parse.tab.h" %} extern int yylval; %% [0-9]+ {yylval = atoi(yytext);return NUMBER; } [ \t] ; /*eat whitespace*/ \n return (0); /*logical EOF*/ . return (yytext[0]); %%

  • formタグのvalue="" に代入される文字列をsubmitボタン

    formタグのvalue="" に代入される文字列をsubmitボタンが押されたときに Javascriptでlocation.hrefで現在のURLを判定して 条件分岐してformタグのvalue="" に "A" や "B" といった 文字列を代入したいと考えてます。 現在下記のタグを書いているのですが、submitボタンが押されたときに パラメータにvalueの値が代入されず、困ってます。。。 タグの記述に間違いがあると思うのですが、ご指摘いただけないでしょうか? ■現在のタグ 1.Javascript側 <script> <!-- function check() { if(location.href.startsWith('http://www.AAA.com/AAA/')){ document.exp.categoryII.value = "A"; }else if(location.href.startsWith('http://www.AAA.com/BBB/')){ document.exp.categoryII.value = "B"; } return true; } // --> </script> 2.formタグ側 <form onsubmit="return check()" name="exp" action=""> <input name="gen" value="6" type="hidden" /> <input name="categoryII" value="" type="hidden" /> <input name="button" value="検索" type="submit" /> </form> よろしくお願い致します。

  • 文字列 数 変換

    数字列を数に変換できなかった男です。 以下はコンパイルエラー patn.c: In function 'input': patn.c:9:3: warning: function returns address of local variable [-Wreturn-local- addr] return (str); ^ 以下は実行後、 数を入力してください。 123.456 ・・,( 0.000000 0 0 以下は書いたプログラムです。 #include<stdio.h> #include<stdlib.h> char *input(void){ char str[100]; printf("数を入力してください。\n"); scanf("%s",str); return (str); } int main(void){ char *a; double d; int i; long l; a=input(); printf("%s\n",a); d=atof(a); i=atoi(a); l=atol(a); printf("%f %d %ld",d,i,l); return(0); } 関数input()にchar *str2; str2=str; return(str2);としても、実行後の表示はおかしいです。 123.456 123 123.456と表示したいです。御指摘お願いします。

  • StrutsでJSPからListを受け取りたい

    JSPに複数のhidden(動的に数が変化)があり、これらの値をformのlist(配列)に詰めたいです。 尚、nameの値は別の処理でjavascriptを使いvalueを変化させるため連番であれば構わないです。です。 ~~~JSP~~~ <input type="hidden" name="str1" value="a"/> <input type="hidden" name="str2" value="b"/> <input type="hidden" name="str3" value="c"/> ~~~~~~~~ 上のJSPから下記のFORMに詰めたい ~~~form~~~ private List strList; public List getStrList(){ return strList; } ~~~~~~~~ 又、こちらで調べたところ下記のようにすればいけるようですが欲しい値は一つのためBeanを使用しなくても実現可能ではないかと思い、質問させていただきました。 よろしくお願い致します。 ~~~JSP~~~ <input type="hidden" name="testArray[0].str" value="a"/> <input type="hidden" name="testArray[1].str" value="b"/> <input type="hidden" name="testArray[2].str" value="c"/> ~~~~~~~ ~~~FORM~~~ private List list; public TestBean getTestA(int iIndex) { while (this.list.size() <= iIndex) { this.list.add(new TestBean ()); } return ( TestBean ) this.list.get(iIndex); } public Object[] getTestArray() { return list.toArray(); } public static class TestBean { private String str = ""; public String getStr() { return str; } public void setStr(String str) { this.str = str; } }

    • ベストアンサー
    • Java
  • 次のソースの使い方(strtok()関数)

     次のソースプログラムについてです。 (“□”は、タブを表します) ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ #include <stdio.h> #include <stdlib.h> /* EXIT_SUCCESS */ #include <string.h> /* strtok() */ int main(void) { □int i, n; □char str[10], *token1, *token2; □scanf("%d", &n); □for (i=0; i<n; i++) { □□scanf("%s", str); □□token1 = strtok(str, ","); □□token2 = strtok(NULL, ","); □□printf("hello = %s , world = %s\n" ,token1 ,token2); □} □return EXIT_SUCCESS; } ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆  これを実行すると、入力待ち画面になって、何を入力すれば何が得られるのか、てんで分からないのですが、どなたか、このプログラムの使い方と意味について、解説をお願いします。  ちなみに、“1”を入力した後、[Ctrl]+[c]で抜けると、結果は、 ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ hello = ヒヒz@俳・, world = (null)◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ となりました。

  • BISON&FLEX

    手元のRedHat7.1には、初期インストール時から、BISONやFLEX用のパッケージが保存されているようなのですが、その起動方法が分かりません。 Lex&YaccのGNU版とされるツールですが、その使用には、何らかの設定が必要なのでしょうか?どうすれば、起動できますか?

  • POV-Rayのエラー

    POV-Rayをインストールしました。 が、 Scene file parser initialization error. Cannot open input file. Returned from rederer[non-zero return value] と表示され、画像が出てきません。 一体何のことやら?? です。 よろしくお願いします。

  • ファイル読み込みとmap処理

    Visual C++ 2008 Express Edition 環境です。 入力テキストファイルを読み込み、空白で単語を区切り、単語すべてをmapにいれるという処理のプログラムを書こうとしています。 perlでいうところのsplit, 配列へのpushをC++でstrtokとmapでならかけると思いました。 入力ファイルは input1.txt--------------- cat dog mice human mosquito beetle spider ------------------------- プログラムは #include <stdio.h> #include<iostream> #include <map> #include <vector> int main( ) { FILE *input_file1; input_file1 = fopen("input1.txt", "r"); char str[256]; char *token; std::vector<char *> my_vector; // while (fgets(str, 256, input_file1) != NULL) { token = strtok( str , " " ); while( token != NULL ){ my_vector.push_back(token) ; printf("%s\n",token); token = strtok( NULL , " " ); } } printf("starting vector loop\n"); std::vector<char *>::iterator it = my_vector.begin(); // while( it != my_vector.end() ) // { printf("%s\n",*it); ++it; // } fclose(input_file1); return 0; } というふうにしました。 cat dog mice human mosquito beetle spider というような出力がなされるものと思ったのですが、実行してみると mapを使ったループ(全要素)出力は mosquito uito le mosquito beetle spider というふうに出力されてしまいます。 strtokで単語を分ける部分は問題なく出力で確認できるので、問題はmapの作り方やポインタだと思うのですが原因がわかりません。 問題点、解決策がお分かりになる方、よろしくお願いします。

  • プログラミング ポインタを使った文字列比較

    プログラミング ポインタを使った文字列比較 2つの文字列str1, str2を入力し,それらが等しければ0,等しくなければ1を返す関数str_compareを作り、返り値によって以下のように表示するプログラムを作れ。ただし,関数strcmpを使ってはならない。 文字列の入出力はmain関数で行い,関数str_compareの仮引数にはポインタ変数を宣言し,ポインタと間接演算子*を用いた処理を行うこと。 % ./a.out input str1 = Worldcup input str2 = Worldcup same strings % ./a.out input str1 = World input str2 = cup different strings この問題に私は次のようにプログラミングしました。 #include <stdio.h> #define MAX 100 int str_compare(char *, char *); main() { char str1[MAX], str2[MAX]; printf("input str1 = %s", str1); scanf("%s", str1); printf("input str2 = %s", str2); scanf("%s", str2); str_compare(str1, str2); if (str_compare(str1, str2) == 0) printf("same strings\n"); else if (str_compare(str1, str2) == 1) printf("different strings\n"); } int str_compare(char *s1, char *s2) { int i; for (i = 0; s1[i] != '\0'; i++) { if (s1[i] != s2[i]) { break; } } if (s1[i] == s2[i]) { return 0; } else { return 1; } } これで実行したところ、「input str1 =」の右のスペースが文字化け?してしまいます。(半角カタカナや記号が出る)ただ、その後に文字列を入力すると、正しく機能します。 これは何が悪いなのでしょうか、どなたか教えてください。

  • javascript 要素取得

    htmlでチェックボックスを作り、その値をjavascriptで取得したいと思い、 下記のようなプログラムを書きました。 セレクトボックスから複数選択できるようにしたいのですが、 表示されるのは複数選んだ際に一番初めに選択したものだけです。  例) 「あああ」と「いいい」を選ぶと「あああ」のみ表示される。 しかし、これを「あああ.いいい」としたいのです。 できれば、 「あああ  いいい」 と改行できるといいです。 formの中にたくさんの項目があるため、 forのところがうまくいっていないのでしょうか? どなたかよろしくお願いします。 javascript側 function checkbox(){  var str="";  for(i=0;i<document.form1.elements.length;i++){   if(document.form1.elements[i].checked){     if(str != "") str = str + ".";     str = str + document.form1.document[i].value;   }  }  if(str == ""){   alert("入力してください");   return false;  }else{   document.form1.submit();  } } HTML側 <form action="<%=遷移先ページ%>" method="post" name="form1"> <select 複数> <input 複数> <input type="checkbox" name="document" value="・あああ"/>あああ <input type="checkbox" name="document" value="・いいい"/>いいい <input type="checkbox" name="document" value="・ううう"/>ううう <input type="submit" value="Submit" onclick="return checkbox();">

このQ&Aのポイント
  • ミシンが古い場合でも、刺繍Pro10のソフトウェアは使用できるのか気になります。
  • ミシンの種類によっては、刺繍Pro10のソフトウェアの互換性があるか確認したいです。
  • 古いミシンでも刺繍Pro10のソフトウェアを利用したい場合、どのような対策が必要なのでしょうか。
回答を見る