2017-06-13 10 views
2

ElixirのLeex/Yeccで特定のログファイルを解析しようとしています。数時間後、私は最も簡単なシナリオを手に入れました。しかし、私は次のステップに進んでいきたいと思いますが、どうやってそれを行うのか分かりません。Elixir/ErlangのYeccパーサーでマップする項目を追加する

まず、ここでのログ形式の例です:

[!] plugin error detected 
| check the version of the plugin 

私の簡単な試みは、最初の行のみとあったが、それらの複数のエントリ、など:

[!] plugin error detected 
[!] plugin error 2 detected 
[!] plugin error 3 detected 

働いたことテキストとログラインタイプ(警告)を含むすばらしい地図を私にくれました:

iex(20)> LogParser.parse("[!] a big warning\n[!] another warning") 
[%{text: "a big warning", type: :warning}, 
%{text: "another warning", type: :warning}] 

これは完璧です。しかし、上記のように、ログ行は次の行に続き、パイプ文字は|と表示されます。私のレクサーはパイプ文字を持っていて、パーサはそれを理解することができますが、私のマップのtext値に次の行を追加します。今のところ、マップ内の文字列として追加されます。だから、代わりに:

[%{text: "a big warning ", type: :warning}, " continues on next line"] 

私が必要:

[%{text: "a big warning continues on next line", type: :warning}] 

私は、ネット上の例を見て、それらのほとんどは、このような終了タグや閉じ括弧など本当に明確な「終了」トークンを、持っています、そしてそれでも、最終的なASTが正しいようにプロパティを追加する方法は私には分かりません。完全のために

は、ここに私のレクサーです:

Definitions. 

Char   = [a-zA-Z0-9\.\s\,\[\]] 
Word   = [^\t\s\.#"=]+ 
Space   = [\s\t] 
New_Line  = [\n] 
%New_Line  = \n|\r\n|\r 
Type_Regular = \[\s\]\s 
Type_Warning = \[!\]\s 
Pipe   = \| 

Rules. 

{Type_Regular} : {token, {type_regular, TokenLine}}. 
{Type_Warning} : {token, {type_warning, TokenLine}}. 
{Char}   : {token, {char, TokenLine, TokenChars}}. 
{Space}   : skip_token. 
{Pipe}   : {token, {pipe, TokenLine}}. 
{New_Line}  : skip_token. 

Erlang code. 

そして、私のパーサー:

Nonterminals lines line line_content chars. 
Terminals type_regular type_warning char pipe. 
Rootsymbol lines. 

lines -> line lines : ['$1'|['$2']]. 
lines -> line : '$1'. 

line -> pipe line_content : '$2'. 
line -> type_regular line_content : #{type => regular, text => '$2'}. 
line -> type_warning line_content : #{type => warning, text => '$2'}. 

line_content -> chars : '$1'. 
line_content -> pipe chars : '$1'. 

chars -> char chars : unicode:characters_to_binary([get_value('$1')] ++ '$2'). 
chars -> char : unicode:characters_to_binary([get_value('$1')]). 

Erlang code. 

get_value({_, _, Value}) -> Value. 

あなたも、ここまでなった場合は、すでにありがとうございました!もし誰かが助けてくれたら、もっと大きな感謝を!

+0

を私は今、この権利をテストすることはできませんが、私はあなたを考えます'line - > pipe line_content: '$ 2'.'を削除し、' line_content'を複数の行にするべきです。 PEGのような記法では、 'line_content = chars(pipe chars)*'、つまりcharsの後に0以上の '(pipe chars)'が続きます。 – Dogbert

+0

@Dogbert aha okありがとう、私は複数の行の解析で検索しようとしましたが、良い例を得ることができません。私はあなたの提案をさらに検索します、おかげですでに束! –

+0

私はこの時点で詳細を見る時間はありませんが、数ヶ月前にSFのErlang/Elixir Confでleex/yecc(Erlangで)を使っている小さなプロジェクトで雷の話をしました。スライドへのリンクはここにあります。リンクの最後に参考文献のリンクがあります。例:https://github.com/derek121/mrwhite –

答えて

2

パイプで区切られた複数の行を処理し、規則line -> pipe line_content : '$2'.を削除するために、line_contentルールを追加することをお勧めします。

はまた lines句で '$2'周りの不要な []があり、シングルライン句は、前の句の戻り値と一致するようにリストを返す必要がありますので、あなたが不適切なリストで終わるません。これら四つの変更、

-lines -> line lines : ['$1'|['$2']]. 
+lines -> line lines : ['$1'|'$2']. 
-lines -> line : '$1'. 
+lines -> line : ['$1']. 

-line -> pipe line_content : '$2'. 
line -> type_regular line_content : #{type => regular, text => '$2'}. 
line -> type_warning line_content : #{type => warning, text => '$2'}. 

line_content -> chars : '$1'. 
-line_content -> pipe chars : '$1'. 
+line_content -> line_content pipe chars : <<'$1'/binary, '$3'/binary>>. 

私はちょうど罰金複数行のテキストを解析することができます

Belino.parse("[!] Look at the error") 
Belino.parse("[!] plugin error detected 
| check the version of the plugin") 
Belino.parse("[!] a 
| warning 
[ ] a 
| regular 
[ ] another 
| regular 
[!] and another 
| warning") 

出力:

[%{text: "Look at the error", type: :warning}] 
[%{text: "plugin error detected check the version of the plugin", 
    type: :warning}] 
[%{text: "a warning ", type: :warning}, %{text: "a regular ", type: :regular}, 
%{text: "another regular ", type: :regular}, 
%{text: "and another warning", type: :warning}] 
+0

感謝の男!余分な '[]'に関しては、最後の項目に '|'が付いているので( 'iex'の出力で)、出力に表示されるので、リストに何か問題があります。 'Enum'でループしている間、私はエラーになります。だから私は '[1,2]'や '[1 | [2] 'でマップを構築するErlangのコードでなければならないので、括弧を追加して括弧を追加するのはなぜですか?あなたの編集でもう一度試してみます。実際の新しい行の代わりに '\ n'を使用しましたが、それは問題ではありません。再度、ありがとうございました! –

+0

ああ。 'lines'の2番目の節からリストを返すべきです。私は私の答えを編集しました。 – Dogbert

+0

それは働いた!驚くばかり。私は本当に何が起こっているのか把握しようとしていますが、私はそれを得ると思います。次のステップでは、ライン自体を一種のマップに解析することができるため、各ラインの内容をさらにネストされたノードに解析します(ログにはdate:today、重要度:緊急など)。 !多分私は後で新しい質問を投稿するでしょう。小さな質問として –

関連する問題