Java – регулярное выражение, содержащее комментарии в коде

На этот раз немного весело с Java. Я хочу написать программу, которая считывает код со стандартного ввода (например, строка за строкой), например:

// some comment class Main { /* blah */ // /* foo foo(); // foo */ foo2(); /* // foo2 */ } 

находит в нем все комментарии и удаляет их. Я пытаюсь использовать регулярные выражения, и теперь я сделал что-то вроде этого:

 private static String ParseCode(String pCode) { String MyCommentsRegex = "(?://.*)|(/\\*(?:.|[\\n\\r])*?\\*/)"; return pCode.replaceAll(MyCommentsRegex, " "); } 

но, похоже, это не работает для всех случаев, например:

 System.out.print("We can use /* comments */ inside a string of course, but it shouldn't start a comment"); 

Любые советы или идеи, отличные от регулярных выражений? Заранее спасибо.

Возможно, вы уже отказались от этого, но я был заинтригован этой проблемой.

Я считаю, что это частичное решение …

Регулярное регулярное выражение:

 //.*|("(?:\\[^"]|\\"|.)*?")|(?s)/\*.*?\*/ 

В Java:

 String clean = original.replaceAll( "//.*|(\"(?:\\\\[^\"]|\\\\\"|.)*?\")|(?s)/\\*.*?\\*/", "$1 " ); 

Кажется, что он правильно обрабатывает комментарии, встроенные в строки, а также правильно экранированные кавычки внутри строк. Я бросил несколько вещей, чтобы проверить, но не исчерпывающе.

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

 int/* some comment */foo = 5; 

Простой цикл Matcher.find / appendReplacement может условно проверять группу (1) перед заменой пробелом и будет всего лишь несколькими строками кода. Возможно, еще проще, чем полный парсер. (Я мог бы добавить петлю сопряжения, если кто-то заинтересован.)

Последний пример не проблема, я думаю:

 /* we comment out some code System.out.print("We can use */ inside a string of course"); we end the comment */ 

… потому что комментарий на самом деле заканчивается на "We can use */ . Этот код не компилируется.

Но у меня есть еще один проблемный случай:

 int/*comment*/foo=3; 

Ваш шаблон превратит это в:

 intfoo=3; 

… что такое неверный код. Поэтому лучше замените свои комментарии словами " " вместо "" .

Я думаю, что 100% -ное правильное решение с использованием регулярных выражений является либо бесчеловечным, либо невозможным (с учетом побегов и т. Д.).

Я считаю, что лучшим вариантом будет использование ANTLR – я считаю, что они даже предоставляют грамматику Java, которую вы можете использовать.

Я закончил с этим решением.

 public class CommentsFun { static List commentMatches = new ArrayList(); public static void main(String[] args) { Pattern commentsPattern = Pattern.compile("(//.*?$)|(/\\*.*?\\*/)", Pattern.MULTILINE | Pattern.DOTALL); Pattern stringsPattern = Pattern.compile("(\".*?(? commentsToRemove = new ArrayList(); Matcher stringsMatcher = stringsPattern.matcher(text); while (stringsMatcher.find()) { for (Match comment : commentMatches) { if (comment.start > stringsMatcher.start() && comment.start < stringsMatcher.end()) commentsToRemove.add(comment); } } for (Match comment : commentsToRemove) commentMatches.remove(comment); for (Match comment : commentMatches) text = text.replace(comment.text, " "); System.out.println(text); } //Single-line // "String? Nope" /* * "This is not String either" */ //Complex */ ///*More complex*/ /*Single line, but */ String moreFun = " /* comment? doubt that */"; String evenMoreFun = " // comment? doubt that "; static class Match { int start; String text; } } 

Другая альтернатива – использовать некоторую библиотеку, поддерживающую parsing АСТ, например, org.eclipse.jdt.core имеет все API-интерфейсы, необходимые для этого и многое другое. Но тогда это всего лишь одна альтернатива 🙂

  • Как объединить 2 или более запросов в представлении Django?
  • Проверьте, присутствует ли элемент в массиве Bash
  • Как искать материалы «R»?
  • pandas loc против iloc против ix против vs. iat?
  • Регулярное выражение для идентификации слов CamelCased с ведущей буквой верхнего регистра
  • Исключить папки из поиска Eclipse
  • Реализация бинарного поиска в объектах
  • Изменение размера текстового поля UISearchBar?
  • Использование XPATH для поиска текста, содержащего & nbsp;
  • grep файл, но показывать несколько окружающих линий?
  • Реализация расстояния Левенштейна для mysql / нечеткого поиска?
  • Давайте будем гением компьютера.