Нужны некоторые идеи о том, как сделать это в Java (разбор строк) - PullRequest
0 голосов
/ 02 мая 2010

Извините, я не мог придумать лучшего заголовка, но спасибо за чтение!

Моя конечная цель - прочитать файл .java, разобрать его и вытащить каждый идентификатор. Затем сохраните их все в списке. Два предварительных условия: в файле нет комментариев, и все идентификаторы состоят только из букв.

Сейчас я могу прочитать файл, разобрать его по пробелам и сохранить все в списке. Если что-либо в списке является зарезервированным словом Java, оно удаляется. Также я удаляю любые свободные символы, которые ни к чему не прикреплены (скобки и арифметические символы).

Теперь у меня осталась куча странных строк, но, по крайней мере, в них нет пробелов. Я знаю, что мне придется пересмотреть все с. разделитель, чтобы вытащить идентификаторы, такие как System.out.print, но как насчет строк, подобных этому примеру:

Logger.getLogger (MyHash.class.getName ()). Журнал (Level.SEVERE,

После повторного разбора. У меня останутся более сумасшедшие строки вроде:

getLogger (MyHash

GetName ())

журнал (Уровень

ТЯЖЕЛАЯ

Как я смогу вытащить все идентификаторы, оставив при этом весь мусор? Просто продолжайте повторный анализ каждого символа, который может существовать в коде Java? Это кажется довольно хромым и трудоемким. Я даже не уверен, что это будет работать полностью. Итак, вы можете предложить лучший способ сделать это?

Ответы [ 3 ]

3 голосов
/ 02 мая 2010

Есть несколько решений, которые вы можете использовать, кроме взлома вашего собственного парсера:

  • Использовать существующий синтаксический анализатор, такой как this .
  • Используйте BCEL для чтения байт-кода, который включает все поля и переменные.
  • Взломать компилятор или среду выполнения, используя обработку аннотаций или зеркала - я не уверен, что вы можете найти все идентификаторы таким образом, но поля и параметры точно.
1 голос
/ 02 мая 2010

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

В псевдокоде:

clean buffer
for each letter l in file:
    if l is '
        toggle "character mode"
    if l is "
        toggle "string mode"
    if l is a letter AND "character mode" is off AND "string mode" is off
        add l to end of buffer
    else
        if buffer is NOT a keyword or a literal
            add buffer to list of identifiers
        clean buffer

Обратите внимание, что некоторые строки здесь скрывают дополнительную сложность - например, чтобы проверить, является ли буфер литералом, необходимо проверить как true, false, так и null.

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

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

РЕДАКТИРОВАТЬ:

  • ЭтоРешение может быть легко расширено для работы с идентификаторами с номерами, а также с комментариями.
  • Небольшая ошибка выше - вам нужно обрабатывать \ "иначе, чем", то же самое с \ 'и'.
0 голосов
/ 02 мая 2010

Ух ты, хорошо. Парсинг сложно - действительно трудно - сделать правильно. Свернуть свой собственный анализатор Java будет невероятно сложно, чтобы сделать правильно. Вы обнаружите множество крайних случаев, к которым вы просто не готовы. Чтобы действительно сделать это правильно и справиться со всеми крайними случаями, вам нужно написать real парсер. Настоящий парсер состоит из нескольких вещей:

  1. Лексический анализатор для разбиения входа на логические порции
  2. Грамматика для определения того, как интерпретировать вышеупомянутые куски
  3. Фактический "синтаксический анализатор", который генерируется из грамматики с помощью такого инструмента, как ANTLR
  4. Таблица символов для хранения идентификаторов в
  5. Абстрактное синтаксическое дерево для представления кода, который вы проанализировали

Если у вас есть все это, вы можете получить настоящий парсер. Конечно, вы можете пропустить абстрактное синтаксическое дерево, но вам нужно почти все остальное. Это оставляет вам писать около 1/3 компилятора. Если вы действительно хотите завершить этот проект самостоятельно, вы должны посмотреть, можете ли вы найти пример для ANTLR, который содержит существующее определение грамматики Java. Это позволит вам пройти большую часть пути, а затем вам нужно будет использовать ANTLR для заполнения таблицы символов.

С другой стороны, вы могли бы пойти на умные решения, предложенные Little Bobby Tables (удивительное имя, кстати Бобби).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...