Как обычно обрабатываются комментарии в языках программирования и разметке? Я пишу парсер для некоторого пользовательского языка разметки и хочу следовать принципу наименьшего удивления , поэтому я пытаюсь определить общее соглашение.
Например, должен ли комментарий, встроенный в токен, «мешать» токену или нет? Как правило, это что-то вроде:
Sys/* comment */tem.out.println()
действует?
Кроме того, если язык чувствителен к новым строкам, а комментарий охватывает новую строку, должна ли учитываться новая строка или нет?
stuff stuff /* this is comment
this is still comment */more stuff
рассматриваться как
stuff stuff more stuff
или
stuff stuff
more stuff
?
Я знаю, что делают несколько конкретных языков, и я не ищу мнений, но ищу, действительно ли существует общий консенсус относительно ожидаемой наценки в отношении токенов и новых строк?
Мой конкретный контекст - это вики-разметка.
Ответы:
Обычно комментарии сканируются (и удаляются) как часть процесса токенизации, но перед анализом. Комментарий работает как разделитель токенов даже при отсутствии пробелов вокруг него.
Как вы указали, в спецификации C явно указано, что комментарии заменяются одним пробелом. Это просто язык спецификации, поскольку реальный анализатор на самом деле ничего не заменит, а просто отсканирует и отбросит комментарий так же, как он сканирует и отбрасывает пробельные символы. Но это объясняет простым способом, что комментарий разделяет токены так же, как пробел.
Содержание комментариев игнорируется, поэтому разрывы строк внутри многострочных комментариев не действуют. Языки, чувствительные к разрывам строк (Python и Visual Basic), обычно не имеют многострочных комментариев, но JavaScript является одним исключением. Например:
Эквивалентно
не
Однострочные комментарии сохраняют разрыв строки, т.е.
эквивалентно
не
Поскольку комментарии сканируются, но не анализируются, они, как правило, не вкладываются. Так
это синтаксическая ошибка, так как комментарий открывается первым
/*
и закрывается первым*/
источник
/* like this */
) считаются равными одному пробелу, а завершенные EOL комментарии (// like this
) - пустой строке.(define x #| this is #| a sub-comment |# the main comment |# 3) x
выходы3
.Чтобы ответить на вопрос:
Я бы сказал, что никто не ожидает, что комментарий, встроенный в токен, будет законным.
Как правило, комментарии должны обрабатываться так же, как и пробелы. Любое место, которое могло бы иметь посторонние пробелы, также должно иметь встроенный комментарий. Единственным исключением будут строки:
Было бы странно поддерживать комментарии внутри строк, и было бы утомительно избегать их!
источник
Hello /* world*/!
а не подавит разделители комментариев. Также добро пожаловать в Программисты!В нечувствительных к пробелам языках игнорируемые символы (то есть пробелы или те, которые являются частью комментария) разделяют токены.
Так, например
Sys tem
, два токена, аSystem
один. Полезность этого может быть более очевидной, если вы сравните,new Foo()
иnewFoo()
один из них создаст экземпляр,Foo
а другой вызоветnewFoo
.Комментарии могут играть ту же роль, что и пробелы, например,
new/**/Foo()
работают так же, какnew Foo()
. Конечно, это может быть более сложным, например,new /**/ /**/ Foo()
или еще много чего.Технически, должно быть возможно разрешить комментарии в идентификаторах, но я сомневаюсь, что это особенно практично.
Теперь, что из языков, чувствительных к пробелам?
Python приходит на ум, и у него очень простой ответ: без блочных комментариев. Вы начинаете комментарий с
#
а затем анализатор работает точно так, как если бы остальная часть строки не существовала, а была просто новой строкой.В отличие от этого, Jade допускает комментарии блока , где блок заканчивается, когда вы возвращаетесь к тому же уровню отступа. Пример:
Так что в этом мире я бы не сказал, что вы могли бы сказать, как все обычно происходит . То, что кажется общностью, состоит в том, что комментарий всегда заканчивается концом строки, что означает, что все комментарии действуют точно так же, как и новые строки.
источник
В прошлом я превращал комментарии в один токен как часть лексического анализа. То же самое касается строк. Оттуда жизнь проста.
В конкретном случае последнего созданного мной анализатора правило escape передается в процедуру синтаксического анализа верхнего уровня. Правило escape используется для обработки токенов, таких как комментарии, встроенные в основную грамматику. В общем, эти токены были отброшены.
Следствием этого является то, что в примере, который вы разместили с комментарием в середине идентификатора, идентификатор не будет единичным идентификатором - это ожидаемое поведение во всех языках (из памяти), с которыми я работал ,
Случай комментария внутри строки должен быть неявно обработан лексическим анализом. Правила для обработки строки не интересуют комментарии, и поэтому комментарий рассматривается как содержимое строки. То же самое относится к строке (или литералу в кавычках) внутри комментария - строка является частью комментария, который явно является единственным токеном; правила обработки комментария не интересуют строки.
Я надеюсь, что это имеет смысл / помогает.
источник
console.log(/*a comment containing "quotes" is possible*/ "and a string containing /*slash-star, star-slash*/ is possible")
, где в строке есть кавычки, а в строке - синтаксис комментария, как лексер узнает, как правильно его токенизировать? Можете ли вы отредактировать свой ответ, предоставив общее описание этих случаев?Это зависит от цели вашего парсера. Если вы напишите синтаксический анализатор для построения дерева разбора для компиляции, тогда комментарий не будет иметь семантического значения, кроме потенциально разделяющих токенов (например, метод / комментарий / (/ комментарий /)). В этом случае его рассматривают как пробелы.
Если ваш синтаксический анализатор является частью транспилятора, переводящего один исходный язык на другой исходный язык, или если ваш анализатор является препроцессором, который берет модуль компиляции на исходном языке, анализирует его, изменяет его и записывает измененную версию на том же исходном языке, комментарии как и все остальное становится очень важным.
Также, если у вас есть метаинформация в комментариях и вы особенно заботитесь о комментариях, например, при создании API-документации, как это делает JavaDoc, комментарии внезапно становятся очень важными.
Здесь комментарии часто прикрепляются к самим токенам. Если вы находите комментарий, вы присоединяете его к комментарию токена. Поскольку токен может иметь несколько токенов до и после, он снова зависит от того, как обрабатывать эти комментарии.
Идея аннотировать токены без комментариев с комментариями состоит в том, чтобы полностью удалить комментарии из грамматики.
Как только у вас есть дерево разбора, некоторые AST начинают распаковывать комментарии, представляющие каждый токен своим собственным AST-элементом, но присоединяемые к другому AST-элементу, помимо обычных вмещений. Хорошей идеей является проверка всех реализаций синтаксического анализатора / AST на наличие исходных языков, доступных в IDE с открытым исходным кодом.
Одна очень хорошая реализация - инфраструктура компилятора Eclipse для языка Java. Они сохраняют комментарии во время токенизации и представляют комментарии в AST - насколько я помню. Кроме того, эта реализация синтаксического анализатора / AST сохраняет форматирование.
источник