А вот тесты как раз ничего не доказывают. Даже в равномерном распределении возможны сколь угодно большие отклонения, если тестов достаточно много. Тут думать надо!
Чтобы третья дверь не учитывалась вообще, ведущему придется с равной вероятностью открывать оставшиеся двери. Но по условию дверь с призом от открыть не может.
Википедия с Вами не согласна: Кондиционер. И я с ней солидарен. Главное — не принцип действия, а результат. А внутри пусть хоть неонка будет :)
Кондиционе́р — это устройство для поддержания оптимальных климатических условий в квартирах, домах, офисах, автомобилях, а также для очистки воздуха в помещении от нежелательных частиц. Предназначен для снижения температуры воздуха в помещении при жаре, или (реже) — повышении температуры воздуха в холодное время года в помещении.
Да, Viliv S5 бьет его по всем статьям. И разница в цене вполне адекватная с учетом функциональности. Поэтому я свой после года использования продавать не собираюсь :)
Для экспериментального проекта важнее всего низкие трудозатраты на эксперимент. Эксперимент — это результат любым способом, в том числе и правкой сгенерированного кода. А удобство сопровождения — это, в числе прочего, низкие трудозатраты на внесение изменений правильным способом, который не ломает технологию и не снижает качество кода. Так что да, твикабельность ценее. Но эксперименты реализуются не правкой сгенерированного кода, а правкой исходного.
одно из самых естественных применений для новых компиляторов — поддержка всяких компактных платформ, где сэкономленная память имеет значение
Не могу согласиться. Обычно используется кросс-компиляция.
Логично в качестве позиции ошибки показывать самую правую, до которой сумела добраться хотя бы одна развёртка
На первый взгляд да, на практике бывают ситуации, когда ошибочный текст действительно оказывается [почти] правильной, но совсем не той конструкцией.
Я бы несколько вариантов ошибки попробовал показать. Типа, если вы хотели написать объявление функции, то вот тут ошибка, а если объявление массива — то тут.
Иногда делают так: собирают информацию о типичных ошибках. Расширяют язык так, чтобы типично ошибочные конструкции вошли в язык. Сообщение об ошибке становится действием, которое долно выполняться при распознавании этих конструкций. Эвристика, но качество может приподнять.
Рассказывали байку, кажется про DECовский С++ компилятор, который умел компенсировать пропущенные (или лишние?) разделители. Первое сообщение — тут у вас точки с запятой не хватает, не волнуйтесь, я ее сама вставлю. Второе — а чего это у вас тут точка с запятой лишняя? Позиция та же. :)
Кстати, вот что я всё хочу добавить, но забываю. Классические компиляторы уже не обеспечивают достаточное количество возможностей. При проектировании «инструмента обработки формального текста» надо учитывать потребности IDE. Иначе придется отдельно реализовывать автопродолжение, outline и прочие стандартные средства. А для IDE надо уметь частично разбирать некорректные программы, извлекая из них максимум возможной информации. К примеру, компилятор, закончив синтаксический разбор, уже не имеет права останавливаться, если были ошибки — всё равно надо пытаться выделить декларации верхнего уровня и т.п.
Значит, приемлемый уровень в данном случае высок. Но с какого-то момента скорость разбора перестанет играть существенную роль, узкие места будут в другом. Из технологий, которые обеспечат такую скорость разбора, надо выбирать такую, которая минимизирует затраты на разработку (надо рассматривать весь жизненный цикл).
OP: '{' OPS '}' // блок
| EXPR ';' // выражение
| 'if' '(' EXPR ')' OP ( 'else' OP )?
| 'while' '(' EXPR ')' OP
| 'exit' ';' ;
но можно и так:
OP: '{' OPS '}' // блок
| EXPR ';' // выражение
// вроде, можно не дублировать, но не помню синтаксис
| ( 'if' '(' EXPR ')' OP 'else' OP )=> 'if' '(' EXPR ')' OP 'else' OP
| 'if' '(' EXPR ')' OP
| 'while' '(' EXPR ')' OP
| 'exit' ';' ;
так что заглядывание вперед всё же поможет, как раз потому, что может быть произвольной длины.
Зачем нам куча дополнительных нетерминалов, когда есть extended bnf?
EXPR: NUM ( OP NUM )*;
невозможность написания «заплаток» на сгенерированный код, потому что он меняется при изменении грамматики, да ещё и размножается по десяткам функций.
Это одно из самых страшных зол, которые только бывают. Сгенерированный код не должен залатываться! Вместо этого DSL должен допускать вставку кода, которая попадет в нужное место сгенерированного кода.
В качестве преимуществ ANTLR в том споре приводят всё что угодно, кроме качеств собственно парсинга
Основным критерием является производительность труда программиста. «Качество собственно парсинга», если имеется ввиду производительность, при этом должно быть на приемлемом уровне, не более того.
Техническая сложность в том, что каждый новый символ, от которого зависит выполнение развёртки, увеличивает размерность таблиц перехода
В ANTLR есть возможность изменять глубину заглядывания вперед локально. То есть, для «почти» LL(1) грамматики можно построить парсер, который будет вести себя как LL(1), а в особо сложном месте заглянет вперед на нужное количество лексем (возможно, бесконечное). Это называется guessing mode: парсеру говорят, если вход от текущего места разберется как вот эта конструкция, то выбирай эту альтернативу, иначе — другую.
И нет там никаких глобальных таблиц перехода.
Но всегда правильнее преобразовать грамматику, а к lookahead прибегать только в особо запущенных случаях.
OP: '{' OPS '}' // блок
| EXPR ';' // выражение
| 'if' '(' EXPR ')' OP
| 'if' '(' EXPR ')' OP 'else' OP
| 'while' '(' EXPR ')' OP
| 'exit' ';' ;
Когда-то мы использовали Maven первой версии. В проектах кроме Java использовались DSL, так что писали даже свои плагины. Как-то жили, но самой большой проблемой было создание нового рабочего места разработчика. Разные версии Maven, разные версии плагинов — всё это приводило к тому, что некоторые проекты напрочь отказывались собираться свежеустановленным Maven'ом, а у старых разработчиков проблем не было. Выхода второго Maven я не дождался — перевел все проекты на Ant + Ivy. Ant для сборки (прост и стабилен), Ivy для управления зависимостями (гораздо гибче, чем первый Maven).
А чтобы не писать build.xml для каждого нового проекта, написал библиотечный build.xml, который делает 99% работы в простых проектах и 90% в сложных. Оставшиеся 10% дописываю в build.xml проекта. Трансляция DSL (JavaCC, Antlr, TreeDL), компиляция Java, создание JavaDoc, тесты, упаковка дистрибутива — из коробки.
В качестве бонуса — можно создавать билдеры для трансляции DSL из Eclipse: при изменении исходных файлов запускаются те же Ant'овские цели, что и из консоли.
Для сборки любого проекта достаточно установить Ant и достать исходники проекта из svn!
Делал для себя, документация минимальна, проект не пиарю, хотя исходники открыты. Но для любопытствующих ссылку дам: BuildBase. И на вопросы отвечу.
Кондиционе́р — это устройство для поддержания оптимальных климатических условий в квартирах, домах, офисах, автомобилях, а также для очистки воздуха в помещении от нежелательных частиц. Предназначен для снижения температуры воздуха в помещении при жаре, или (реже) — повышении температуры воздуха в холодное время года в помещении.
К слову, из WYSIWYG когда-то пользовался XMLmind XML Editor. Есть бесплатная версия. Скорее, нравился.
Не могу согласиться. Обычно используется кросс-компиляция.
На первый взгляд да, на практике бывают ситуации, когда ошибочный текст действительно оказывается [почти] правильной, но совсем не той конструкцией.
Я бы несколько вариантов ошибки попробовал показать. Типа, если вы хотели написать объявление функции, то вот тут ошибка, а если объявление массива — то тут.
Иногда делают так: собирают информацию о типичных ошибках. Расширяют язык так, чтобы типично ошибочные конструкции вошли в язык. Сообщение об ошибке становится действием, которое долно выполняться при распознавании этих конструкций. Эвристика, но качество может приподнять.
Рассказывали байку, кажется про DECовский С++ компилятор, который умел компенсировать пропущенные (или лишние?) разделители. Первое сообщение — тут у вас точки с запятой не хватает, не волнуйтесь, я ее сама вставлю. Второе — а чего это у вас тут точка с запятой лишняя? Позиция та же. :)
Кстати, вот что я всё хочу добавить, но забываю. Классические компиляторы уже не обеспечивают достаточное количество возможностей. При проектировании «инструмента обработки формального текста» надо учитывать потребности IDE. Иначе придется отдельно реализовывать автопродолжение, outline и прочие стандартные средства. А для IDE надо уметь частично разбирать некорректные программы, извлекая из них максимум возможной информации. К примеру, компилятор, закончив синтаксический разбор, уже не имеет права останавливаться, если были ошибки — всё равно надо пытаться выделить декларации верхнего уровня и т.п.
Свой первый транслятор я писал, чтобы уйти от регулярного исправления сгенерированного кода в больших объемах :)
От левой рекурсии в большинстве случаев довольно легко избавиться.
но можно и так:
так что заглядывание вперед всё же поможет, как раз потому, что может быть произвольной длины.
Зачем нам куча дополнительных нетерминалов, когда есть extended bnf?
EXPR: NUM ( OP NUM )*;
Это одно из самых страшных зол, которые только бывают. Сгенерированный код не должен залатываться! Вместо этого DSL должен допускать вставку кода, которая попадет в нужное место сгенерированного кода.
Основным критерием является производительность труда программиста. «Качество собственно парсинга», если имеется ввиду производительность, при этом должно быть на приемлемом уровне, не более того.
В ANTLR есть возможность изменять глубину заглядывания вперед локально. То есть, для «почти» LL(1) грамматики можно построить парсер, который будет вести себя как LL(1), а в особо сложном месте заглянет вперед на нужное количество лексем (возможно, бесконечное). Это называется guessing mode: парсеру говорят, если вход от текущего места разберется как вот эта конструкция, то выбирай эту альтернативу, иначе — другую.
И нет там никаких глобальных таблиц перехода.
Но всегда правильнее преобразовать грамматику, а к lookahead прибегать только в особо запущенных случаях.
А чтобы не писать build.xml для каждого нового проекта, написал библиотечный build.xml, который делает 99% работы в простых проектах и 90% в сложных. Оставшиеся 10% дописываю в build.xml проекта. Трансляция DSL (JavaCC, Antlr, TreeDL), компиляция Java, создание JavaDoc, тесты, упаковка дистрибутива — из коробки.
В качестве бонуса — можно создавать билдеры для трансляции DSL из Eclipse: при изменении исходных файлов запускаются те же Ant'овские цели, что и из консоли.
Для сборки любого проекта достаточно установить Ant и достать исходники проекта из svn!
Делал для себя, документация минимальна, проект не пиарю, хотя исходники открыты. Но для любопытствующих ссылку дам: BuildBase. И на вопросы отвечу.