Каким должен быть язык программирования? Анализ и критика Описание языка Компилятор
Отечественные разработки Cтатьи на компьютерные темы Компьютерный юмор Прочее

Помеченные комментарии

Напомню, что в одной из предыдущих статей отмечалась невозможность обеспечить вложенность длинных (скобочных) комментариев «/* ... */». Собственно говоря, нас заботила не вложенность как таковая, а возможность закомментировать любой код, не обращая внимания на его содержимое. А длинные комментарии «спотыкаются» о строки типа char x[] = "*/".

            Для решения этой проблемы были предложены комментарии нового вида: «нерабочий код». Однако такое решение, как теперь видится, является слишком дорогим для такой дешёвой проблемы. Этот способ предполагает разбор лексем и вводит новую их категорию: недействующие лексемы. Это чревато неоправданным усложнением компилятора.

            Есть мысль сделать другой вид комментариев — помеченные комментарии. Каждый комментарий такого вида содержит уникальную метку в своём начале и такую же метку в конце. Внутри таких комментариев могут содержатся любые другие комментарии: хоть такие же помеченные (но с другой меткой), хоть длинные, короткие.

            Со стилем мы уже определились, длинные комментарии будут иметь вид «(* ... *)». Предлагаемый вид комментариев тоже будет начинаться и заканчиваться скобками. Где и как располагать метку? Наверное, лучше всего так:

(:метка
. . .
метка:)
Метка — это ряд символов, которые соответствуют лексеме «идентификатор». Двоеточие отсылает нас традиционным меткам в языках, в которых есть «goto»:
label_01: // какой-то код
. . .
goto  label_01:;
Помеченные комментарии
Обоснование выбора.
  • Почему не «(*метка ... метка*)»? Потому что нет возможности отличить его от длинного комментария «(* ... *)».
  • Почему не «(метка* ... *метка)»? Потому метка — это идентификатор и «(идентификатор*» выглядит как левая часть умножения.
  • Почему не «(метка: ... :метка)»? Потому метка — это идентификатор и «(идентификатор:» выглядит как левая часть операции «:». Этот символ пока нами не задействован для какой-либо операции. Но не стоит это трогать — вдруг пригодится.
Есть ли у этой идеи подводные камни? Да, они могут иметь место, например:
(:метка777
  char  x = "метка777:)";
  метка777:)
В таком случае легко избежать коллизии:
(:метка333
  char  x = "метка777:)";
  метка333:)
Т.е. меняется метка комментария, но не код, оказавшийся внутри него. С длинным комментарием такой номер не пройдёт, придётся менять сам текст. Проблемный код:
(* char  x = "*/"; *)
Вариант решения проблемы — изменение кода внутри:
(* char  x = "\x2A\x2F"; *)
            И так, наверное наилучший способ обозначения помеченных комментариев — это смайлики улыбки (если кто-то ещё не обратил на получившиеся графические очертания). Но есть вполне резонный вопрос: а есть ли смысл закладывать в язык отдельную конструкцию для борьбы с одним-единственным случаем, когда конец комментария внутри текста?

Последняя правка: 2018-11-07    10:07

ОценитеОценки посетителей
   ██████████████████████████████████████████ 3 (100%)
   ▌ 0
   ▌ 0
   ▌ 0

Отзывы

     2018/11/11 14:27, Александр Коновалов aka Маздайщик

Похожая проблема в языках программирования возникает со строками — изобразить строку, которая сама содержит кавычки. Традиционное решение — escape-символы вроде ". Но некоторые языки программирования предлагают более хитрые способы.

Например, в Python можно строку ограничивать тремя кавычками: """...""" — весь текст между ними (включая переводы строк) становится содержимым строки. Таким образом в Python иногда записывают многострочные комментарии. Запись строкового литерала в строке считается выражением, а значит, оператором. Никакого побочного эффекта, кроме потери времени на интерпретацию, это не даёт. Недостаток — нельзя внутри использовать три кавычки подряд, но с этим питонисты мирятся.

Интересен подход Rust (https://doc.rust-lang.org/reference/tokens.html#raw-string-literals) — строка, которая начинается с r#...#", должна заканчиваться на "#...#, причём число решёток в начале и конце должно совпадать. Т.е., строки могут иметь вид r"...", r#"..."#, r##"..."##. Соответственно, если строка содержит "#### (кавычка и четыре решётки), то её можно погрузить в r#####"..."##### — (пять решёток).

Языки Bash и Perl для многострочных строк предоставляют т.н. heredoc-синтаксис (https://ru.wikipedia.org/wiki/Heredoc-синтаксис) (не знаю, как его лучше переводить на русский):
somecommand <<ENDOFTEXT
...
...
ENDOFTEXT
Семантика следующая: запускается команда somecommand, на стандартный ввод которой падают строчки между строкой запуска команды и строкой ENDOFTEXT. Строку вместо ENDOFTEXT можно записать любую:
somecommand <<ABCD
...
...
ABCD
Пример в Perl (псевдокод):
sql_call("SELECT * FROM table WHERE тут длиннющая длиннющая строка JOIN table2 ON key GROUP BY
и ещё много букв на SQL, я не знаю SQL пишу от балды всякую чушь ODRER DESCENT", param1, param2);
С heredoc’ами:
sql_call(<<SQLEND, param1, param2)
SELECT * FROM table
WHERE тут длиннющая длиннющая строка
JOIN table2 ON key
GROUP BY и ещё много букв на SQL,
я не знаю SQL пишу от балды всякую чушь
ORDER DESCENT
SQLEND
К чему я всё это написал. К тому, что комментарии и строки родственны тем, что внутри них может быть произвольный текст, и проблему символов-разделителей внутри приходится как-то решать. Для строк некоторые решения известны, подход для комментариев — новый.

Вариант, предложенный Автором сайта, немного напоминает подход Rust’а для строк и heredoc’и, но применён к комментариям, что, несомненно, является новшеством.

     2018/11/15 09:37, kt

Древний подход к символу кавычки внутри строки в кавычках — удвоение кавычки. Например, текст строки I’m back, будет выглядеть так: ’I’’m back’
Логических сложностей при лексическом разборе не возникает — вторую кавычку подряд надо просто игнорировать. Строка даже может состоять из одних кавычек — просто все их надо удвоить. При этом самая первая кавычка — признак самой строки и поэтому в удвоении не учитывается. Еще одна удобная мелкая доработка — знак «крышка» ^ этот символ внутри строки гасит старшие три разряда в следующем байте. При этом в строке удобно пишутся управляющие символы, которые все становятся печатными, например строка ’^G^M^J’ бибикнет и переведет строку. Ну а сама "крышка" записывается, естественно, как две "крышки" подряд ))

     2018/11/15 17:59, Автор сайта

Разница между строками и комментариями всё-таки есть. Строки заключаются между одинаковых символов:
"строка"
. Чтобы внутри поместить этот символ, его надо просто задвоить:
"строка с "" кавычкой"
. Или строку поместить внутри одинарных кавычек, как в PHP:
'строка с " кавычкой'
Комментарии же заключаются между разных символов (допустим, между «/*» и «*/»):
/* комментарий */
Как мы можем задвоить эти символы? Так
/* длинный */*/ комментарий */
или так
/* длинный *//* комментарий */
?

     2018/11/15 23:30, kt

Замечу, что в нашем трансляторе PL/1 эта проблема, увы, также не решена. Т.е. у нас есть «объемлющий» комментарий /*[ .... ]*/, который ищет квадратную скобку вплотную к знаку комментария и, таким образом, пропускает почти любой текст внутри, поскольку [] вообще не входят в алфавит PL/1 (кстати, теперь входят и поэтому скобки физических типов нельзя писать вплотную к границам комментария).
Но так можно закомментировать кусок программы с «обычными» /* */ только один раз ((

     2018/11/16 12:53, Автор сайта

Что тогда остаётся? Либо предупреждать, что внутри строк "*/" надо менять на "\x2A\x2F", либо вот такие помеченные комментарии. Но оба варианта не вписываются в стандарт PL/1.

Написать отзыв

Написать автору можно на электронную почту mail(аt)compiler.su

Авторизация

Регистрация

Выслать пароль

Карта сайта


Каким должен быть язык программирования?

Анализ и критика

Устарел ли текст как форма представления программы

Русский язык и программирование

Многоязыковое программирование

Синтаксис языков программирования

Синтаксический сахар

Некоторые «вкусности» Алгол-68

«Двухмерный» синтаксис Python

Почему языки с синтаксисом Си популярнее языков с синтаксисом Паскаля?

Должна ли программа быть удобочитаемой?

Стиль языка программирования

Тексто-графическое представление программы

●  Разделители

●  Строки программы

●  Слева направо или справа налево?

Комментарии

●  Длинные комментарии

●  Короткие комментарии

●  Комментарии автоматической генерации документации

●  Нерабочий код

●  Помеченные комментарии

Нужны ли беззнаковые целые?

Шестнадцатиричные и двоичные константы

Условные операторы

Переключатель

Циклы

●  Продолжение цикла и выход из него

Некошерный «goto»

Операции присвоения и проверки на равенство. Возможно ли однаковое обозначение?

Так ли нужны операции «&&», «||» и «^^»?

Постфиксные инкремент и декремент

Почему в PHP для конкатенации строк используется «.»?

Указатели и ссылки в C++

Использование памяти

Почему динамическое распределение памяти — это плохо

Как обеспечить возврат функциями объектов переменной длины?

●  Типы переменного размера (dynamically sized types, DST) в языке Rust

●  Массивы переменной длины в C/C++

●  Размещение объектов в стеке, традиционный подход

●  Размещение объектов переменной длины с использованием множества стеков

●  Размещение объектов переменной длины с использованием двух стеков

●  Реализация двухстековой модели размещения данных

●  Двухстековая модель: тесты на скорость

●  Изменение длины объекта в стеке во время исполнения

●  Размещение объектов переменной длины с использованием одного стека

Можно ли забыть о «куче», если объекты переменной длины хранить в стеке

Безопасность и размещение объектов переменной длины в стеке

Массивы, структуры, типы, классы переменной длины

О хранении данных в стеке, вместо заключения

Описание языка

Компилятор

Отечественные разработки

Cтатьи на компьютерные темы

Компьютерный юмор

Прочее

Последние комментарии

2018/11/20 20:13 ••• ivan.ee
✎ Программирование без программистов — это медицина без врачей

2018/11/18 17:14 ••• kt
✎ Экстракоды при синтезе программ

2018/11/18 15:26 ••• Freeman
✎ Так ли нужны операции «&&», «||» и «^^»?

2018/11/18 15:21 ••• Freeman
✎ Устарел ли текст как форма представления программы

2018/11/17 03:28 ••• Comdiv
✎ Изменение длины объекта в стеке во время исполнения

2018/11/16 12:53 ••• Автор сайта
✎ Помеченные комментарии

2018/11/11 14:01 ••• Александр Коновалов aka Маздайщик
✎ Нерабочий код

2018/11/11 13:39 ••• Александр Коновалов aka Маздайщик
✎ О русском языке в программировании

2018/11/11 12:57 ••• Александр Коновалов aka Маздайщик
✎ Об одной реализации специализированных операторов ввода-вывода

2018/11/03 22:43 ••• rst256
✎ Непрерывное компилирование

2018/11/02 23:23 ••• Неслучайный читатель
✎ Сколько проходов должно быть у транслятора?

2018/11/01 19:10 ••• Автор сайта
✎ Об исключенных командах или за что «списали» инструкцию INTO?