2012-05-06 4 views
1

Можно ли легко получить позиции в качестве смещений (в качестве атрибутов от начала ввода) с помощью Parsec? Если да, то как? Внутренне Parsec сохраняет позицию как тип данных с именем источника, строкой и столбцом.Позиции Parsec как смещения

Я хотел бы, чтобы иметь возможность написать парсер как

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) в размере полного ввода, или мне не хватает чего-то, что делает этот запуск более эффективным? Я буду беспокоиться о том, чтобы называть это в парсере с любой регулярностью. Похоже, что это будет считать вкладки как некоторые обычно непредсказуемые значения между 1 (или 0?) И 8 из-за того, как updatePosChar работает :( – rcreswick

1

Нет, невозможно получить текущий индекс строки в Parsec, поскольку Parsec не отслеживает этот индекс. Вы можете использовать трансформатор монады над государственной монадой и вручную отслеживать проанализированный индекс.

+1

Насколько это было бы тяжело? Я полагаю, что некоторые примитивы должны быть пересмотрены, верно? – Romildo

+0

Было бы очень сложно; вы должны в принципе переопределить все примитивы и все, что зависит от этих примитивов. Там нет класса типа парсера, который имеет функцию, которую вы можете заменить. Я бы посоветовал вместо этого переопределить вашу логику, которая зависит от информации индекса строки. Какая вам информация в любом случае? – dflemstr

+0

Вы можете, например, создать функцию, которая преобразует '(Line, Column)' и входную строку в индекс. Если вы хотите, я могу показать вам, как построить эту функцию. – dflemstr

Смежные вопросы