Pull to refresh

Comments 14

14 голосов, 23 человека добавили в избранное и ни одного комментария. Думаю пора создавать отдельный блок, с названием Yet Another Compiler.
Или хотя бы перенести этот пост в «Компиляторы».
> Оператор case подобен оператору if, примененному несколько раз.В Cool это
Сорри, рано отправилось. В Cool case не так работает. Это скорее похоже на «as» в C#. case проверяет можно ли привести объект (результат выражения) к типу и если да, то выполняет выражение после стрелки.
Я не до конца разъяснил: результат в операторе Case получается как если бы мы несколько раз применили поиск «наиболее общего близкого предка» поочередно к выражениям expr1,…, exprn, которые справа.
А про «as» у вас верно написано.
Либо я не так понял, либо нет.
case expr of x1: T1 => expr1; x2: T2 => expr2;… esac
работает так: вычисляем expr (запоминаем результат), запоминаем его динамический тип, скажем T. Если T1 предок T (или равен T), то биндим результат expr в x1 и вычисляем expr1, иначе повторяем это T2/expr2/x2,… и т.д.
Это что-то вроде:
var x = expr;
if(x is T1) { x1 = x; expr1; }
else if (x is T2) { x2 = x; expr2; }
Смотрите: оператор case всегда должен возвращать статический тип, как и остальные операторы. Этот тип определяется на этапе компиляции по выражениям expr1...exprn.

А у вас тоже почти все верно написано: в Case вводятся как бы локальные переменные x1,…, xn с соответствующими типами, которые затем могут использоваться в выражениях expr1,…, exprn.
Так, я понял в чем наша проблема :) Мы говорим о разных вещах.
Я просто по той (в первом моем коменте) подумал что речь о case как if не с точки зрения типизации, а в смысле рантайма. Просто до этого вы нигде не описали как case работает (ведь работает он не так как в других языках case/switch) и я подумал что речь именно про это. Вы же писали про типизацию.
Тогда да, все верно.
Кстати, ваше замечание про оператор Case было прямо в точку.
Именно этот оператор не реализован у меня в генерации кода, поскольку это оказалось слишком ресурсозатратно для меня ;) (Этот проект вообще идет в качестве 4 лабораторных по курсу «Конструирование компиляторов»).

Теперь я подумаю, стоит ли для него сделать генерацию или нет.
case проверяет можно ли привести объект (результат выражения) к типу и если да, то выполняет выражение после стрелки.

Как в Scala чтоли?
Советую посмотреть на Nemerle.Peg — не видел лучшего средства для создания парсеров под .net. У самого проект, который могу поддерживать только из-за того, что в свое время выбрал peg в качестве инструмента для создания парсера.

Из особенностой можно отметить отсутствие деления на лексер и парсер, а так же то, что писать парсер приходиться на Nemerle.
Думаю вам будет интересно посмотреть на Peggy пакет в Haskell, так как он на Template Haskell.

Как-то для решения простенькой задачки из ЖЖ Darkus'а воспользовался:
{-# Language TemplateHaskell, QuasiQuotes, FlexibleContexts #-}

module PeggyTest (
    test
    ) where

import Text.Peggy

import Data.Word

[peggy|

file :: [(Word32, Word32)] = ranges !.

ranges :: [(Word32, Word32)]
    = ips* { $1 }

ips :: (Word32, Word32)
    = ip ',' ip { ($1, $2) }

ip :: Word32
    = byte "." byte "." byte "." byte { $1 * 256 * 256 * 256 + $2 * 256 * 256 + $3 * 256 + $4 }

byte ::: Word32
    = [0] { 0 }
    / [1-9] [0-9]* { read ($1 : $2) }

|]

test :: IO ()
test = print $ parseString file "test" "0.0.0.0,255.255.255.255 192.168.0.3,192.168.1.13"

Ну и какие есть аргументы, кроме того, что он вам больше всего нравится?

>> Из особенностой можно отметить отсутствие деления на лексер и парсер, а так же то, что писать парсер приходиться на Nemerle.

Вы наверное хотели сказать, код, который использует парсер, нужно писать на Nemerle? Потому что парсер писать вообще не надо — для этого и используются генераторы.

Судя по этому и этому сравнениям, единственным адекватным конкурентом для ANTLR является Gold Parser. Он основан на LALR синтезе.

Если сравнивать его с ANTLR, то основными преимуществами являются:
  • 1. Скорость работы.
  • 2. Допустимость левой рекурсии.
  • 3. Поддержка большего количества языков.
  • 4. Более красивый интерфейс (нет мелких шрифтов, как в ANTLR под Windows).

А недостатки следующие:
  • 1. Сложновоспринимаемый человеком код лексера и парсера.
  • 2. Необходимость приведения грамматики к форме Бэкуса-Наура.
3. Работает только под Windows (ANTLR на Java, а значит кроссплатформенная).

Я Nemerle.PEG пользовался не очень много, но могу прокомментировать.

Код, который использует парсер можно писать на любом .NET совместимом языке. Так, как Nemerle.PEG — это макрос, то он во время компиляции раскрывается в парсер, который можно использовать из другой сборки.

Из преимуществ могу отметить то, что во время написания грамматики компилятор сразу подчёркивает некорректные места и выдаёт ошибку. Причём эта ошибка не в сгенерированном коде, а именно в грамматике, поэтому понять где ошибся очень легко.

Сгенерированный парсер реально быстр: «Производительность парсера C# с построением AST колеблется между 3 и 4 МБ/c. Для YAML это число видимо будет выше в несколько раз.» © Hardcase
Можно поискать на rsdn ветки по производительности, там народ вроде бы мерил.

Я думаю, shai_xylyd сможет более подробно описать остальные преимущества. Я на PegParsere только один проект написал. Конвертер из CSS в SASS cо свёрткой и прочим. bit.ly/xSVDGE
Sign up to leave a comment.

Articles