2016-09-21 9 views
0

私が一致するように、単純なパターン持っている:ヘッド+コンテンツ+テールを、私は以下のようなlexのファイル持っている:私のlexパターンが入力ファイルと一致するようには機能しません。どのように修正するのですか?

$ cat b.l 
%{ 
#include<stdio.h> 
%} 
%% 
"12" {printf("head\n");} 
"34" {printf("tail\n");} 
.* {printf("content\n");} 
%% 

を私がする場合、「12」を満たしたときに、それは「頭」を印刷することを願っています"34"を満たすと、 "tail"、他の連続した文字列が印刷され、 "content"が印刷されます。

だから私はコンパイルして実行します。私の期待がある

lex b.l && gcc lex.yy.c -ll 
$ echo '12sdaesre34'|a.out 
content 

、それは

head 
content 
tail 

が印刷されますが、実際にそれが唯一の「コンテンツ」の行を出力します。私は間違ったこと、それを修正する方法を得ましたか?

ありがとうございます!

答えて

1

(F)lexは、可能な限り最長のトークンと常に一致します。 .*は、改行文字が含まれていないシーケンスと一致するので、うれしく12sdaesre34と一致します。 (lexでは、.は改行以外の文字と一致します)。したがって34はマッチすることができなくなりました。

修正するには、contentと一致するものを明確にする必要があります。たとえば、次のように数字が含まれていないものにマッチします:

[^[:digit:]]+ { printf("content\n"); } 

あなたが一致しないために文字のリストに改行を追加したい場合があります:

[^\n[:digit:]]+ { printf("content\n"); } 

それとも、あなたがしたいです34を含まない最長配列と一致する。それはトリッキーだが、それを行うことができます。

([^3]|3+[^34])+ { printf("content\n"); } 

、問題を解決するには十分ではありませんので、しかし、それはまだ、初期12と一致します。

入力が常に12...34の文字列で構成されていて、他のコンテンツが散在している場合は、12...34シーケンス全体を一致させて3つのトークンに分割できます。最初と最後のマーカーは既知の長さであるため、間違いなく最も簡単な解決策です。次のパターンの最初は、12を開始しない文字列と、最初のインスタンス12の直前で終わる文字列に一致し、2番目の文字は12で始まり、最初のインスタンス34(一致する)で終わる文字列と一致します。いずれのパターンも、一致しない12を含む入力と一致しません。その場合に合致するように第3のルールが追加されます。 2番目のルールのように見えますが、末尾に34の一致は含まれません。 (f)lexは常に最長のトークンと一致するため、3番目のルールは2番目のルールが失敗した場合にのみ成功します。

([^1]|1+[^12])*   { puts("content"); } 
12([^3]|3+[^34])*34  { puts("head content tail"); } 
12([^3]|3+[^34])*  { puts("error"); } 

通常、あなたが実際に呼び出し元のプログラムに渡すためにcontentの値をキャプチャしたいと思います。最初のルールでは、それはちょうどyytextですが、2番目のルールでは、コンテンツはyytext+2で始まるyyleng-4文字からなります(先頭と末尾の区切り文字を削除するため)。

yytextがレキシカルスキャナで使用されている内部データ構造を指し、ポインタが次のパターンマッチで無効になるため、ほとんどの場合、一致したトークンを保持する必要がある場合はコピーする必要があります。最初のルールの場合は、あなたはstrcpyを使用して文字列のコピーを作成することもできますが、2番目のルールのため、あなたはコピーを自分で作りたいと思います:

([^1]|1+[^12])*   { yylval = strcpy(yytext); ... } 
12([^3]|3+[^34])*34  { yylval = malloc(yyleng-3); 
          memcpy(yylval, yytext, yyleng-4); 
          yylval[yyleng-4] = '\0'; 
          ... 
         } 

者はyylvalがグローバル変数であると仮定しますタイプchar*であり、コード内のどこかにある規則free()の文字列です。彼らはまた、省略コード(...)でyylvalを使って何かをやっているとか、頭と尾が遭遇したかどうかの表示で呼び出し元に戻ったと仮定します。

+0

ありがとうございますが、答えはそれほど正確ではありません。 ([^ 3] | 3 + [^ 34])+ {printf( "content \ n"); } は今、結果はまだないが、私はwated: \t $が12dsfadsf34をエコー| \tコンテンツ \t尾 \tコンテンツ –

+0

@HindForsum a.out形式:はい、あなたは全く正しいです。どのように進めるかについていくつかの提案を加えましたが、実際にはあなたの要件を知らないので、明らかに概要に過ぎません。私は一般的にあなたがCで文字列処理に精通していると仮定しています。 – rici

関連する問題