2014-12-13 4 views
2

При написании грамматики для Github для программ подсветки синтаксиса, написанных на языке Racket, я наткнулся на проблему.Соответствующие вложенные конструкции в текстовых грамматиках TextMate/Sublime Text/Atom

В Racket #| начинается многострочный комментарий, и |# заканчивает его.

Проблема заключается в том, что многострочные комментарии могут быть вложенными:

#| a comment #| still a comment |# even 
             more comment |# 

Вот моя нерабочим попытка:

repository: 
    multilinecomment: 
    begin:   \#\| 
    end:   \|\# 
    name:   comment 
    contentName: comment 
    patterns: 
    - include:  "#multilinecomment" 
     name:  comment 
    - match:  ([^\|]|\|(?=[^#]))* 
     name:  comment 

Намерение моделей матчей:

  1. "#multilinecomment" Многострочный комментарий может содержать еще один многострочный комментарий.
  2. ([^\|]|\|(?=[^#]))* Смысл подвыражений:

    [^\|]  any characters not an `|` 
    \|(?=[^#]) an `|` followed by a non-`#` 
    

Все выражение, таким образом, соответствует строке не с указанным | #

Обновление:

Получил ответ от Allan Odgaard на список рассылки TextMate:

http://textmate.1073791.n5.nabble.com/TextMate-grammars-and-nested-multiline-comments-td28743.html

ответ

2

Поэтому я тестировал кучу языков в Sublime, которые имеют многострочные комментарии (C/C++, Java, HTML, PHP, JavaScript), и ни один из синтаксисов языка не поддерживает многострочные комментарии, встроенные в многострочные комментарии - синтаксис выделение для области comment заканчивается первым маркером «comment close», а не с симметричными маркерами. Теперь это не означает, что это невозможно, потому что плагин BracketHighlighter отлично подходит для сопоставления симметричных тегов, скобок и других маркеров. Тем не менее, он написан на Python и использует пользовательскую логику для своих алгоритмов соответствия, что может быть недоступно в движке Oniguruma, который управляет синтаксисом синтаксиса Sublime и, видимо, Github's.

В принципе, из вашего описания проблемы необходим анализатор кода, чтобы гарантировать, что вложенные комментарии легальны, что вы не можете сделать с помощью определения подсветки синтаксиса. Если вы пишете это только для Sublime, пользовательский плагин мог бы позаботиться об этом, но я не знаю достаточно о синтаксической синтаксисе системы Giantub Linguist, чтобы сказать, разрешено ли вам это делать. Я еще не являюсь мастером регулярных выражений, но мне кажется, что было бы довольно сложно добиться этого только регулярным выражением, так как вам нужно каким-то образом отслеживать произвольное количество внутренних симметричных «открытых» и «закрытых», маркеров, прежде чем найти (и идентифицировать!) окончательный.

К сожалению, я не мог обеспечить окончательный ответ, кроме я не уверен, что это возможно, но это лучшее, что я могу придумать, не зная больше о Sublime-х и внутренних GitHub, в чем-то, что (по крайней мере, Случай Sublime) не произойдет, если он не будет открытым. Удачи!

+0

Спасибо за расследование. Я бы с удовольствием заменил грамматику TextMate на правильный синтаксический анализатор - увы, потому что я смотрю на грамматику TextMate, в первую очередь, потому что Github отказался от поддержки Pyigs (включая правильный парсер для Racket). То есть я застрял, используя грамматику TextMate. Теперь не конец света, что многострочные комментарии не работают, однако если невозможно сопоставить вложенные # | | # правильно, тогда будет очень сложно получить #; комментарии правильно. A #; раскомментирует следующее s-выражение - что-то очень распространенное в Racket/Scheme/Lisp. – soegaard

+0

Я буду держать вопрос открытым на пару дней, и если никто не придумает решение, я приму ваш ответ. – soegaard

1

Вы имели правильное представление, но это выглядит как ваша вторая модель также соответствует для «начать вложенную комментарий» последовательности #|, которая никогда не даст шанса для вашего рекурсивного #multilinecomment шаблона пнуть в.

Все, что вам нужно сделать, это заменить свой второй шаблон с чем-то похож на

(#(?=[^|])|\|(?=[^#])|[^|#])+ 
+0

'(# (?! \ |) | \ | (?! #) | [^ | #]) +' –

1

Старый пост, и я не имею репутацию комментарий, но это решительно невозможно обнаружить произвольно вложенные комментарии, используя чисто регулярные выражения. Интуитивно это связано с тем, что все регулярные выражения могут быть преобразованы в конечную машину состояний, и для отслеживания глубины гнездования требуется (теоретически) бесконечное количество состояний (число состояний должно быть равно, по крайней мере, разных возможных глубин гнездования, которая здесь бесконечна).

На практике это число растет очень медленно, поэтому, если вы не хотите слишком много беспокоиться, вы, вероятно, могли бы написать что-то, что позволяет вложить до разумной глубины. В противном случае вам, вероятно, потребуется отдельная фаза, которая анализирует и находит комментарии, чтобы указать синтаксический маркер, чтобы игнорировать их.

+1

Да, используя только регулярные выражения, это было бы невозможно. Графика TextMate позволяет «репозиторий» регулярных выражений, которые могут использоваться для создания рекурсивных правил. – soegaard

Смежные вопросы