Comments 14
14 голосов, 23 человека добавили в избранное и ни одного комментария. Думаю пора создавать отдельный блок, с названием Yet Another Compiler.
> Оператор case подобен оператору if, примененному несколько раз.В Cool это
Сорри, рано отправилось. В Cool case не так работает. Это скорее похоже на «as» в C#. case проверяет можно ли привести объект (результат выражения) к типу и если да, то выполняет выражение после стрелки.
Я не до конца разъяснил: результат в операторе Case получается как если бы мы несколько раз применили поиск «наиболее общего близкого предка» поочередно к выражениям expr1,…, exprn, которые справа.
А про «as» у вас верно написано.
А про «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 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 вводятся как бы локальные переменные x1,…, xn с соответствующими типами, которые затем могут использоваться в выражениях expr1,…, exprn.
Так, я понял в чем наша проблема :) Мы говорим о разных вещах.
Я просто по той (в первом моем коменте) подумал что речь о case как if не с точки зрения типизации, а в смысле рантайма. Просто до этого вы нигде не описали как case работает (ведь работает он не так как в других языках case/switch) и я подумал что речь именно про это. Вы же писали про типизацию.
Тогда да, все верно.
Я просто по той (в первом моем коменте) подумал что речь о case как if не с точки зрения типизации, а в смысле рантайма. Просто до этого вы нигде не описали как case работает (ведь работает он не так как в других языках case/switch) и я подумал что речь именно про это. Вы же писали про типизацию.
Тогда да, все верно.
Кстати, ваше замечание про оператор Case было прямо в точку.
Именно этот оператор не реализован у меня в генерации кода, поскольку это оказалось слишком ресурсозатратно для меня ;) (Этот проект вообще идет в качестве 4 лабораторных по курсу «Конструирование компиляторов»).
Теперь я подумаю, стоит ли для него сделать генерацию или нет.
Именно этот оператор не реализован у меня в генерации кода, поскольку это оказалось слишком ресурсозатратно для меня ;) (Этот проект вообще идет в качестве 4 лабораторных по курсу «Конструирование компиляторов»).
Теперь я подумаю, стоит ли для него сделать генерацию или нет.
case проверяет можно ли привести объект (результат выражения) к типу и если да, то выполняет выражение после стрелки.
Как в Scala чтоли?
Советую посмотреть на Nemerle.Peg — не видел лучшего средства для создания парсеров под .net. У самого проект, который могу поддерживать только из-за того, что в свое время выбрал peg в качестве инструмента для создания парсера.
Из особенностой можно отметить отсутствие деления на лексер и парсер, а так же то, что писать парсер приходиться на Nemerle.
Из особенностой можно отметить отсутствие деления на лексер и парсер, а так же то, что писать парсер приходиться на Nemerle.
Думаю вам будет интересно посмотреть на Peggy пакет в Haskell, так как он на Template Haskell.
Как-то для решения простенькой задачки из ЖЖ Darkus'а воспользовался:
Как-то для решения простенькой задачки из ЖЖ 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, то основными преимуществами являются:
А недостатки следующие:
>> Из особенностой можно отметить отсутствие деления на лексер и парсер, а так же то, что писать парсер приходиться на Nemerle.
Вы наверное хотели сказать, код, который использует парсер, нужно писать на Nemerle? Потому что парсер писать вообще не надо — для этого и используются генераторы.
Судя по этому и этому сравнениям, единственным адекватным конкурентом для ANTLR является Gold Parser. Он основан на LALR синтезе.
Если сравнивать его с ANTLR, то основными преимуществами являются:
- 1. Скорость работы.
- 2. Допустимость левой рекурсии.
- 3. Поддержка большего количества языков.
- 4. Более красивый интерфейс (нет мелких шрифтов, как в ANTLR под Windows).
А недостатки следующие:
- 1. Сложновоспринимаемый человеком код лексера и парсера.
- 2. Необходимость приведения грамматики к форме Бэкуса-Наура.
Я Nemerle.PEG пользовался не очень много, но могу прокомментировать.
Код, который использует парсер можно писать на любом .NET совместимом языке. Так, как Nemerle.PEG — это макрос, то он во время компиляции раскрывается в парсер, который можно использовать из другой сборки.
Из преимуществ могу отметить то, что во время написания грамматики компилятор сразу подчёркивает некорректные места и выдаёт ошибку. Причём эта ошибка не в сгенерированном коде, а именно в грамматике, поэтому понять где ошибся очень легко.
Сгенерированный парсер реально быстр: «Производительность парсера C# с построением AST колеблется между 3 и 4 МБ/c. Для YAML это число видимо будет выше в несколько раз.» © Hardcase
Можно поискать на rsdn ветки по производительности, там народ вроде бы мерил.
Я думаю, shai_xylyd сможет более подробно описать остальные преимущества. Я на PegParsere только один проект написал. Конвертер из CSS в SASS cо свёрткой и прочим. bit.ly/xSVDGE
Код, который использует парсер можно писать на любом .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.
Разрабатываем компилятор для учебного языка Cool на языке C# под .NET (Часть 1)