Написание режима компиляции регулярных выражений

Окончательное рабочее решение, которое учитывает диапазоны строк и столбцов:

(csharp
 "^ *\\(?:[0-9]+>\\)*\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\),\\([0-9]+\\),\\([0-9]+\\),\\([0-9]+\\)) *\: \\(error\\|warning\\) *CS[0-9]+:)"
 1 (2 . 4) (3 . 5) )

Оба ответа ниже были невероятно полезны; Теперь я понимаю систему намного лучше.


Резюме: мои регулярные выражения работают для сопоставления выходных строк, но не работают в compilation-error-regexp-alist-alist для сопоставления ошибок в моих выходных данных компиляции.

Я нахожу регулярное выражение режима компиляции немного запутанным. Я написал регулярное выражение, которое, как я знаю, работает с моей строкой ошибок с использованием rebuilder и исходных регулярных выражений в compile.el.

40> f: \ Projects \ dev \ source \ Helper.cs (37,22,37,45): ошибка CS1061: "foo.bar" не содержит определения для "функции" и нет метода расширения "метод", принимающий Первый аргумент типа 'foo.bar' может быть найден (вам не хватает директивы using или ссылки на сборку?)

И вот мое регулярное выражение:

(pushnew '(csharp
 "^ *\\(?:[0-9]+>\\)*\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\),\\([0-9]+\\),[0-9]+,[0-9]+) *\: \\(?:error *CS[0-9]+:\\)"
 2 3)
     compilation-error-regexp-alist-alist)

Очевидно, я просто пытаюсь добраться до первой пары строка / столбец, которая выводится. (Я удивлен, что компилятор выводит 4 числа вместо двух, но что угодно.)

Если мы посмотрим на регулярное выражение edg-1 в compile.el:

    (edg-1
 "^\\([^ \n]+\\)(\\([0-9]+\\)): \\(?:error\\|warnin\\(g\\)\\|remar\\(k\\)\\)"
 1 2 nil (3 . 4))

Так что я думаю, что меня смущает то, как передаются аргументы. В edg-1 откуда берутся 3 и 4? Я предполагаю, что они не соответствуют группам захвата? Если я запускаю регулярное выражение edg-1 через re-builder для правильно сформированного сообщения об ошибке и вхожу в режим подвыражения, 0 соответствует всей совпадающей строке, 1 соответствует имени файла и пути, а 2 соответствует номеру строки. При просмотре документации (когда я делаю Mx description-variable), кажется, что она просто заботится о том, какое место подвыражения находятся в главном выражении. В любом случае, я явно что-то недопонимаю.

Я также попытался изменить официальное регулярное выражение csharp.el для обработки дополнительных двух чисел, но безуспешно.

(Изменить, немного исправил пример, обновил регулярное выражение csharp)

2 ответа

Решение

Нашел некоторую информацию по этому вопросу.

Эта страница имеет упрощенное объяснение:
http://praveen.kumar.in/2011/03/09/making-gnu-emacs-detect-custom-error-messages-a-maven-example/

Цитата со страницы -

"Each elt has the form (REGEXP FILE [LINE COLUMN TYPE HYPERLINK
HIGHLIGHT...]).  If REGEXP matches, the FILE'th subexpression
gives the file name, and the LINE'th subexpression gives the line
number.  The COLUMN'th subexpression gives the column number on
that line"

Похоже, формат выглядит примерно так:

(REGEXP FILE [LINE COLUMN TYPE HYPERLINK HIGHLIGHT...])

Глядя на регулярное выражение снова, он выглядит как модифицированный BRE.

 ^                   # BOS
 \( [^ \n]+ \)       # Group 1

 (                   # Literal '('
 \( [0-9]+ \)        # Group 2
 )                   # Literal ')'

 : [ ] 

 \(?:
      error
   \|
      warnin\(g\)    # Group 3
   \|
      remar\(k\)     # Group 4
 \)

Вот это edg-1

(edg-1
 "^\\([^ \n]+\\)(\\([0-9]+\\)): \\(?:error\\|warnin\\(g\\)\\|remar\\(k\\)\\)"
 1 2 nil (3 . 4))

куда

"^\\([^ \n]+\\)(\\([0-9]+\\)): \\(?:error\\|warnin\\(g\\)\\|remar\\(k\\)\\)"
REGEXP ^^^^^^^^

 1     2    nil    (3 . 4)
 ^     ^     ^      ^^^^^
FILE LINE  COLUMN   TYPE

"TYPE is 2 or nil for a real error or 1 for warning or 0 for info.
TYPE can also be of the form (WARNING . INFO).  In that case this
will be equivalent to 1 if the WARNING'th subexpression matched
or else equivalent to 0 if the INFO'th subexpression matched."

Таким образом, ТИП имеет эту форму (ВНИМАНИЕ. ИНФОРМАЦИЯ)

In the regex,
if capture group 3 matched (ie. warnin\(g\) ) it is equivalent to a warning.
If capture group 4 matched (ie. remar\(k\) ) it is equivalent to info.  
One of these will match.  

Информация об элементе csharp

Глядя на ваш csharp элемент

"^ *\\(?:[0-9]+>\\)?\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\),\\([0-9]+\\),[0-9]+,[0-9]+) *\: \\(?:error *CS[0-9]+:\\)"
2 3 4

И у вашего регулярного выражения (ниже) на самом деле нет группы захвата 4.
Итак, ваша ФАЙЛОВАЯ КОЛОННА 2 3 4
наверное должно быть 1 2 3

Вот ваше регулярное выражение, так как его двигатель видит это -

 ^ 
 [ ]* 
 \(?:
      [0-9]+ > 
 \)?
 \(                            # Group 1
      \(?:
            [a-zA-Z] : 
      \)?
      [^:(\t\n]+ 
 \)
 (                             # Literal '('
      \( [0-9]+ \)                # Group 2
      ,
      \( [0-9]+ \)                # Group 3
      ,
      [0-9]+
      ,
      [0-9]+ 
 )                             # Literal ')'
 [ ]* \: [ ] 
 \(?:
      error [ ]* CS [0-9]+ :
 \)

Мой хрустальный шар получил странное объяснение: compilation-error-regexp-alist-alist это просто набор соответствующих правил, но он не говорит, какие правила использовать. Так что вам нужно добавить csharp в compilation-error-regexp-alist если вы хотите использовать свое новое правило.

Что касается значения (3 . 4), увидеть C-h v compilation-error-regexp-alist,

Другие вопросы по тегам