2017-12-19 23 views
1

私はLexとYaccを使って小さなプロジェクトを開発しており、数学的表現を扱わなければなりません。私のファイルsyntax.yでプロダクションのタイプに基づくトークンのタイプを変更するにはどうすればよいですか?

、私はプロダクションルールのこれらの2つのタイプがあります。

%union { 
    char* lexeme;    
    double value; 
    } 

%token <lexeme> NUM 
%type <lexeme> expr 
%type <value> comp_expr 

expr : expr "+" expr { $$ = strcat($1,"+"); $$ = strcat($$,$3); } 
     | NUM 
     ; 

comp_expr: comp_expr "+" comp_expr { $$ = $1 + $3; } 
     | NUM 
     ; 

私は文字列として式を返すために、「式expr」を使用して、私がするために「comp_expr」を使用式を計算式、この場合は合計として返します。

syntax.yの他の部分をベースにしています(ここには含まれていないので、ここでは無関係です)。「expr」と「comp_expr」をいつ使うべきかを正しく認識するシステムがあります。

しかし、 "comp_expr"を使用するとエラーが発生します。なぜなら、トークンNUMは字句、つまり文字列として宣言されており、プロダクション "comp_expr"は値を持ち、したがってdouble型であるからです。

どのようにしてトークンNUMに語彙と値の両方を割り当てることができますか?または、私が使用している生産に基づいてNUMの価値をどのように変更できますか?注意を事前に

{NUM} { yylval.lexeme = strdup(yytext); return NUM; } 

ありがとう:

はまた、私はまた、私は、ファイルlexic.lにNUMを保存する方法を投稿してください。

答えて

1

明白なことを言う危険がありますが、私はあなたがダブルになる必要があるときにNUMをダブルに変換することをお勧めします。ユニットの制作は、このような変換のための完全であり、あなたは1つが手元に起こる:

comp_expr: NUM { $$ = strtod($1, NULL); } 

あなたはstrtodに電話で確認し、より慎重なエラーを行うことができますが、語彙素がすでにによって検証されていることを前提とするのが妥当かもしれ語彙スキャナー。ところで


は、巨大な問題があります:

expr : expr "+" expr { $$ = strcat($1,"+"); $$ = strcat($$,$3); } 

$1は、おそらく、字句スキャナでstrdupへの呼び出しの戻り値です。その場合、それは正確に語彙を保持するのに十分な長さであり、であり、もはやではありません。最後に多くのものを連結すると、バッファのオーバーフローが発生します。あなたはあなたのものではないメモリを上書きします。それは非常に迅速に問題にあなたを取得します。

exprの正しい長さの新しい文字列を割り当てる必要があります。 asprintfは、この目的のために非常に便利で、一連のstrcatよりも読みやすくなっています。

strdupエフェクツを連結した後に、freeが出てこないことに起因するメモリリークについて考えるべきでしょう。

+0

ありがとうございます。最初のソリューションはうまく動作し、2番目のヒントは非常に有用で便利です。 –

関連する問題