2

トークンを別のものに置き換えた後、bison や flex に強制的にスキャンを再開させる方法はありますか?

私の特定の例は、特定の単語/文字列の置換です。helloの単語をに置き換えたい場合echo hello、flex または bison を置き換えてから再度解析を開始するにはどうすればよいですかhello(1 つではなく 2 つの単語を取得するため)。したがって、次のようになります。

  • トークン WORD (文字列型) を取得します。
  • の場合hello、トークン値をecho hello
  • 入力全体の解析を再開します (現在はecho hello)
  • トークン取得 WORD ( echo)
  • トークン取得 WORD ( hello)

のような非常に魅力的な関数を見てきましyyrestart()たが、特にその関数が実際に何を達成するのかはよくわかりません。どんな助けでも大歓迎です、ありがとう!

2010 年 4 月 23 日更新

私が最終的に使用したハックアンドスラッシュ ソリューションの 1 つは、word通過するそれぞれについて、「エイリアス」配列をチェックすることです。にエイリアスがある場合wordは、単語の値を (たとえば を使用して) 置き換え、フラグstrcopy($1,aliasval)をマークします。aliasfound

入力の行全体が 1 回解析されると、aliasfoundフラグが true の場合yy_scan_string()、バッファの状態を展開されたエイリアスを持つ入力に切り替え、YYACCEPT.

そのため、メイン関数に飛び出しyyparse()、バッファがまだ文字列を指している状態で再度呼び出します。これは、エイリアスが見つからなくなるまで続きます。すべての文法アクションが完了したら、呼び出しyyrestart(stdin)て「通常」モードに戻ります。

エイリアス値を使用して単語を効果的に展開し、stdin(または他の方法に) 挿入し、基本的にすべてのエイリアス (ネストされていても) を展開する方法を誰かが知っていれば、それは素晴らしいことです。yypush_buffer_state()私はとyypop_buffer_state()、 と一緒にいじっていましyy_switch_to_buffer()たが、継続的な解析作業で「インライン」置換を得ることができませんでした...

4

2 に答える 2

1

It seems to me that the place to fix this is the lexer. I would suggest using flex, which supports a state machine (called "Start Conditions" in the flex documentation). You change states using BEGIN, and the states need to be defined in the definitions section.

So, for example, you could have a rule like

<INITIAL>hello    BEGIN(in_echo); yyless(0); return (WORD_ECHO);
<in_echo>hello    BEGIN(0); return (WORD_HELLO);

yyless() truncates the yytext to the given value, so this puts the entire input back into the stream.

I haven't tried this out myself, but I think this is the structure of the solution you want.

于 2010-04-25T13:04:33.513 に答える
0

私がやったことに基づいて「答え」を追加します。この質問を回答済みとしてマークします。

2010 年 4 月 23 日更新

私が最終的に使用したハックアンドスラッシュ ソリューションの 1 つは、通過する単語ごとに「エイリアス」配列をチェックすることです。単語にエイリアスがある場合は、単語の値を (たとえば、strcopy($1,aliasval) を使用して) 置き換え、aliasfound フラグをマークします。

入力の行全体が 1 回解析されたら、aliasfound フラグが true の場合、yy_scan_string() を使用してバッファーの状態を展開されたエイリアスを持つ入力に切り替え、YYACCEPT を呼び出します。

次に、メイン関数に飛び出し、yyparse() を再度呼び出します。バッファーはまだ文字列を指しています。これは、エイリアスが見つからなくなるまで続きます。すべての文法アクションが完了したら、yyrestart(stdin) を呼び出して「通常」モードに戻ります。

エイリアス値を使用して単語を効果的に展開し、stdin (または他の方法) に挿入し、基本的にすべてのエイリアス (ネストされていても) を展開する方法を誰かが知っていれば、それは素晴らしいことです。yypush_buffer_state() と yypop_buffer_state() を yy_switch_to_buffer() と一緒にいじっていましたが、解析を続けながら「インライン」置換を行うことができませんでした...

于 2012-01-07T16:00:41.100 に答える