2011-07-21 4 views
3

この質問はちょっと混乱するかもしれません。私はFlexを使ってBisonにトークンを渡しています。フレックスを2番目に長い正規表現にマッチさせる方法は?

Flexは最も長い正規表現にマッチし、そのトークンを渡します(このように動作します)が、そのトークンが文法では機能しない場合は、2番目に長い正規表現に一致し、そのトークン。

私はこの動作を作成する方法を考えるのに苦労しています。どうすればこのことが起こるのですか?明確にするために

は、例えば、私は2つのルールを持っていると言う:

"//" return TOKEN_1; 
"///" return TOKEN_2; 

は、(それがない)私はそれが最初TOKEN_2に合格したい文字列"///"を、与えられました。 TOKEN_2がBisonで指定された文法に適合しない場合は、TOKEN_1(これも有効です)を渡します。

この動作はどのようにして作成できますか?

+0

私は大きなファイルを扱っていて、端末を備えたシステムを使用していないので、簡単な例を使ってチェックするのは難しいです。これはデフォルトの動作ではありませんか? –

+0

特定のルールセット、または一般的なすべてのルールに対してこれを実行しますか?後者の場合、flexを使ってこれを達成した場合、私は驚くでしょう。 特定のルールセットの場合は、ルールをリファクタリングする必要があります。 – Kizaru

+0

このトークン状況は、2つの異なるトークンに対してのみ発生します。基本的には、コメントを特定のタイプのコメントとして扱おうとしていますが、問題が発生した場合は、それを通常のコメントとして扱います。私のルールをこのようにリファクタリングするのは非常に難しく、このトークン・パッシング・メソッドを動作させることができれば、これははるかに簡単になると思います。 –

答えて

0

申し訳ありませんが、あなたはそれを行うことはできません。私は実際にバイソンとどのくらいフレックス交渉しているのかは分かりません。私は、REPL解析のためのモードがあることを知っているし、私はそれをすべて解析する別のモードがあることを知っている。

ルールをインライン化する必要があります。たとえば、//の代わりに/と/を受け入れるルールを書くと、///は//を意味する別の///を意味します。しかし、それは乱雑になり、私は自分のコードの特定の場合にのみそれをしました。 flex

3

、あなたが何かをしようとしますが、マクロREJECTを使用して、次善のルールを失敗したとしようとするルールを持つことができます。

はREJECT 「第二へ進むためにスキャナに指示入力と一致する「ベスト」ルール(または入力のプレフィックスは )です。このルールは、「入力がどのように一致するか」で前述した として選択され、 yytextおよびyylengが適切に設定されます。 は、最初に選択した のルールと同じくらい多くのテキストに一致しますが、後でフレックス の入力ファイルに含まれるものでも、少ないテキストにマッチしたものでもどちらでもかまいません。

(出典:The Flex Manual Page)。

2番目に長い式を得ることについての質問に答えるには、REJECTを使用してこれを行うことができます(同じ長さのものを同じ優先度で選ぶことができるので注意が必要です)。

flexは、いずれのポイントでも悪化するように余分なロジックを維持する必要があるため、REJECTが使用されていると遅くなります。私はあなたの問題を解決する他の方法がない場合にのみこれを使用することをお勧めします。

+0

ありがとうございます...これは参考になり、正しい軌道に乗っているようです。しかし、REJECTはトークンがBisonのルールでエラーを引き起こしたことをどのように知るでしょうか? –

0

私はちょうど2つのトークン///をスキャンして、それらが1つのトークンと見なされると思われる場合、または別々のものとして扱うようにします。私。 ///で始まる文法規則は、実際には///で始まるものにリファクタリングすることができます。つまり、TOKEN_2はまったく持っていません。LARL(1)パーサーはルックアヘッドのトークンを1つしか持たないので、同じような場合には、この種のことは難しいかもしれません。後に続く/に関係なく、//のみを参照することに基づいて、決定を下すか、または減らす必要があります。

私は、これを字句解析を含むハックなアプローチで解決しようと考えていましたが、うまくいかないことが判明しました。

アイデアの主な欠陥は、ユーザーから隠されているyaccでエラーリカバリを行う簡単な方法がないことです。構文エラーが発生した場合は、それが表示されます。 yyerror機能には、これを隠そうとするハックが含まれている可能性がありますが、コンテキスト情報はありません。

つまり、実際にYaccエラーアクションを使用して、別の解析のバックトラック検索を開始することはできません。

0

これは、バックトラックを行わないので、バイソン/ yaccが対処するのは難しいです。 btyaccのようなバックトラッキングパーサジェネレータを使用しても、それはレクサーを介してバックトラックしないと、実際には役に立ちません(これはおそらく統合レクサーを持つパーサジェネレータを必要とします)。

私の提案は、スラッシュはすぐに特別にスラッシュが続くと異なるトークンを返す:

\//\/  return SLASH; 
\/   return '/'; /* not needed if you have the catch-all rule: */ 
.   return *yytext; 

今、あなたは文法における非端末などのマルチスラッシュ「トークン」「を組み立てる」する必要があります。

single_slash: SLASH | '/' ; 
double_slash: SLASH SLASH | SLASH '/' ; 
triple_slash: SLASH SLASH SLASH | SLASH SLASH '/' ; 

ただし、1トークン先読みでは十分ではないため、文法に矛盾がある可能性があります。 btyaccまたはbisonの%glr-parserオプションを使用して解決できる場合があります。

関連する問題