Использование и архитектура Parsec Дмитрий Тимофеев Санкт-Петербургская группа пользователей Haskell 15 декабря 2007 г.

Презентация:



Advertisements
Похожие презентации
1 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Потоки. «Завязывание узлов» Часто обработку данных.
Advertisements

Теория языков программирования и методы трансляции Тема 3 Лексический анализ.
Разработка проблемно- ориентированного языка программирования Никита Дубровин группа С
ЛКШ. Зима.09. С + В. М. Гуровиц,
Санкт-Петербургский Государственный Университет Математико-Механический факультет Кафедра системного программирования Межъязыковое взаимодействие OCaml.
Семантический анализ КC-грамматики, с помощью которых описывают синтаксис языков программирования, не позволяют задавать контекстные условия (КУ), имеющиеся.
1 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Еще один пример функциональной программы
Челябинск 2006 г. 1 Разработка SQL компилятора для СУБД «ОМЕГА» Докладчик Губин Максим Владимирович Научный руководитель Соколинский Леонид Борисович.
Потоки Язык C++ не обеспечивает средств для ввода/вывода Ему это и не нужно; такие средства легко и элегантно можно создать с помощью самого языка Традиционно.
ПРАКТИКУМ по предмету: Информатика Алгоритмический язык Турбо-Паскаль.
1 Эффективность рекурсивных функций. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. -- Вычисление.
М.Ю. Харламов, ВНУ им. В.Даля, Семантический анализатор Семантический анализатор выполняет следующие основные действия: проверку соблюдения во входной.
Лекция 13. Введение в ООП. Часть 4 Красс Александр СПбГУ ИТМО, 2008.
Software engineering Дмитриев Андрей Владиславович ©
Язык высокого уровня компилятор Программа компиляторов Сделал:Студент группы:Ис-2о(очная)Воротов Валентин.
Введение в теорию компиляции Основные принципы построения трансляторов.
ЯЗЫКИ ПРОГРАММИРОВАНИЯ С РАСШИРЯЕМЫМ СИНТАКСИСОМ П.В. Егоров Екатеринбург, Июнь 2006.
Общее устройство компиляторов. Использование Lex и Yacc Сергей Нечаев, аспирант МО ВВС ИВМиМГ.
Лекция Неполная спецификация и недетерминизм. Let- и Case-выражения.
1 Кубенский А.А. Функциональное программирование. Глава 4. Основы лямбда-исчисления Рекурсия в лямбда-исчислении fac = λn.(if (= n 0) 1 (* n (fac.
Транксрипт:

Использование и архитектура Parsec Дмитрий Тимофеев Санкт-Петербургская группа пользователей Haskell 15 декабря 2007 г.

Синтаксический анализ Задачи: Проверка правильности исходных данных - соответствие текста грамматике Содержательная обработка исходных данных

Подходы Полностью ручная реализация Генераторы парсеров (YACC, Happy) Комбинаторные библиотеки List of successes Монадические Parsec

Монадические парсеры type Parser a return :: a -> Parser a (>>=) :: Parser a -> (a -> Parser b) -> Parser b satisfy :: (Char -> Bool) -> Parser Char ( ) :: Parser a -> Parser a -> Parser a

Parsec import Text.ParserCombinators.Parsec simple :: Parser Char simple = letter > parseTest simple a a Примитивные парсеры: letter, char, string, …

Последовательность парсеров bracketedLetter :: Parser Char bracketedLetter = do { char ( ; c

Последовательность парсеров > parseTest bracketedLetter (a) a > parseTest bracketedLetter (ab) parse error at (line 1, column 3): unexpected "b" expecting ")"

Альтернативы parens :: Parser () parens = do { char ( ; parens ; char ) ; parens } return ()

Предпросмотр test1 = string OCaml string Haskell test2 = string (lisp) string (scheme) > parseTest test1 Haskell Haskell > parseTest test2 (lisp) (lisp)

Предпросмотр test1 = string OCaml string Haskell test2 = string (lisp) string (scheme) > parseTest test2 (scheme) parse error at (line 1, column 1): unexpected "s" expecting "(lisp)"

Предпросмотр Причина: Parsec строит LL(1)-парсер Ограничение: решение принимается на основании анализа только первого символа строки Осознанный выбор: эффективность Есть возможность преодолеть ограничения LL(1)

Предпросмотр Вариант 1: test2 = do { char ( ; s string scheme ; char ) ; return ( ( ++ s ++ ) ) }

Предпросмотр Вариант 2: test2 = try (string (lisp)) string (scheme) Комбинатор try так изменяет наш парсер, что он в случае неудачи оставляет уже прочитанные символы в потоке

Архитектурные принципы Эффективность: отказ от затрат на поддержку неограниченного предпросмотра, LL(1) по умолчанию, можно увеличить количество просматриваемых символов, используя try Информативность сообщений об ошибках

Ограничение предпросмотра В конструкции p q парсер q в принципе не вызывается, если p обработал больше одного символа Каждый парсер отслеживает, сколько символов он обработал

Ограничение предпросмотра Упрощенная реализация: type Parser a = String -> Consumed a data Consumed a = Consumed (Reply a) | Empty (Reply a) data Reply a = Ok a String | Error

Базовые комбинаторы return x = \input -> Empty (Ok x input) satisfy :: (Char -> Bool) -> Parser Char satisfy test = \input -> case (input) of []-> Empty Error (c:cs) | test c-> Consumed (Ok c cs) | otherwise-> Empty Error

Базовые комбинаторы char c= satisfy (==c) letter = satisfy isAlpha digit= satisfy isDigit

Базовые комбинаторы (>>=) :: Parser a -> (a -> Parser b) -> Parser b p >>= f = \input -> case (p input) of Empty reply1 -> case (reply1) of Ok x rest -> ((f x) rest) Error-> Empty Error...

Базовые комбинаторы Consumed reply1 -> Consumed (case (reply1) of Ok x rest -> case ((f x) rest) of Consumed reply2 -> reply2 Empty reply2-> reply2 error -> error)

Базовые комбинаторы ( ) :: Parser a -> Parser a -> Parser a p q = \input -> case (p input) of Empty Error -> (q input) Empty ok-> case (q input) of Empty _ -> Empty ok consumed -> consumed

try try :: Parser a -> Parser a try p = \input -> case (p input) of Consumed Error-> Empty Error other-> other

Обработка ошибок К типу Parser добавляется состояние: type Parser a = State -> Consumed a data State= State String Pos К результатам разбора добавляется сообщение об ошибках, причем к удачному разбору – тоже data Message = Message Pos String [String] data Reply a = Ok a State Message | Error Message

Обработка ошибок Меняется реализация return, satisfy, ( ) – [Leijen, Meijer, 2001] В результате получаем возможность приписывать парсерам информативные обозначения – комбинатор

Семантика nesting :: Parser Int nesting = do { char ( ; n

Дополнительные возможности Лексический анализ: Лексический анализ объединяется с синтаксическим анализом Лексический анализ выполняется отдельными специализированными парсерами Реализованными в библиотеке Разработанными самостоятельно с помощью комбинаторов Использование отдельного сканера, параметризация по типу потока (не только Char) Возможность генерации парсера выражений по набору операций с учетом ассоциативности и приоритета

Источники информации Сайт Parsec: Daan Leijen. Parsec, a fast combinator parser, 2001 Daan Leijen, Erik Meijer. Parsec: Direct Style Monadic Parser Combinators For The Real World, 2001