2012-05-06 9 views
1

パーセックでオフセットの位置を(入力の開始点からのcharctersとして)簡単に取得できますか?もしそうなら、どうですか?内部的にParsecは、ソース名、行および列を持つデータ型として位置を保持します。オフセットとしてのパーセルの位置

私はパーサpを使って何かを解析し、オフセットとしての左右の位置だけでなく、その結果を返します

pWithPos p = do left <- getPosition  -- gets the current position as an offset 
       x <- p 
       right <- getPosition  -- gets the current position as an offset 
       return (x,(left,right)) 

のようなパーサを書くことができるようにしたいと思います。

alex(字句解析ジェネレータ)は、絶対文字オフセット、行番号、および列番号を保持するハンドルpositionsを処理します。私はparsecで絶対文字オフセットを逃しています。

+0

オフセットを何から? parsecはすでに0からの行オフセットと0からの列オフセットを示しています。ファイルの先頭から文字単位でオフセットされていますか? –

+0

@DonStewart入力の開始から文字のオフセットが必要です。 – Romildo

答えて

1

あなたは、入力文字列とSourcePos与えられ、オフセットを計算するために、この機能を使用することができます。

offset :: String -> SourcePos -> Maybe Location 
offset source pos = elemIndex pos positions 
    where positions = scanl updatePosChar firstPos source 
     firstPos = initialPos (sourceName pos) 
+0

これは実際には完全入力のサイズではO(n)ですか、これをより効率的に実行する何かがありませんか?私は規則的なパーサでこれを呼び出すことについて心配しています。また、これは、updatePosCharがどのように動作するかによって、1(または0?)と8の間のいくつかの一般的に予測不可能な値としてタブを数えるように見えます: – rcreswick

1

いいえ、Parsecはそのインデックスを追跡しないため、現在の文字列インデックスをParsecで取得することはできません。ステートモナドにモナドトランスを使用して、解析されたインデックスを手動で追跡することができます。

+1

それはどれくらい難しいでしょうか?私はいくつかのプリミティブを再定義する必要があると思います。 – Romildo

+0

これは非常に難しいでしょう。基本的にすべてのプリミティブとそのプリミティブに依存するすべてを再定義する必要があります。あなたが置き換えることができる関数を持つ "パーサ状態型クラス"はありません。代わりに、文字列のインデックス情報に依存するロジックを再定義することをお勧めします。とにかく何の情報が必要ですか? – dflemstr

+0

たとえば、 '(Line、Column)'と入力文字列をインデックスに変換する関数を作成できます。必要に応じて、私はその関数をどのように構築するかを示すことができます。 – dflemstr

関連する問題