Java-сканер с пустым разделителем - PullRequest
1 голос
/ 26 декабря 2009

Я бы хотел проанализировать некоторый текст, используя рукописный нисходящий синтаксический анализатор. Я использовал Scanner со следующим разделителем: "\\s*". К сожалению, тот факт, что этот шаблон соответствует пустой строке, похоже, приводит к тому, что каждые hasNextFoo и nextFoo больше ничего не соответствуют.

Документация ничего не говорит о возможных пустых разделителях.

Ответы [ 4 ]

1 голос
/ 26 декабря 2009

Вы также можете рассмотреть StreamTokenizer . Вот пример использования его для просмотра одного символа в парсере рекурсивного спуска .

1 голос
/ 26 декабря 2009

Да, потому что я хочу использовать сканер как лексер времени выполнения. Короче говоря, я хочу иметь возможность запросить scanner.next (pattern), который либо возвращает совпадающую строку, либо возвращает исключение, не потребляя поток. Пробелы следует игнорировать. Если есть класс лучше, чем сканер, я был бы рад использовать его.

Я не могу придумать ни одного готового библиотечного класса, который бы сделал это для вас. Обычная модель сканера / лексера состоит в том, что любая недопустимая последовательность символов (то есть та, которая приводит к исключению) будет использована. Итак, я думаю, что вам придется внедрить свой собственный сканер вручную, заботясь о том, чтобы символы опережающего чтения не использовались. Вы можете сделать это с помощью считывателя «pushback» или (если эта модель не удобна), явно буферизуя символы самостоятельно с помощью некоторой модели маркировки / сброса. Если все, что вы делаете, это разбиваетесь на токены, разделенные одним или несколькими пробелами, тогда подход с возвратом в обратном направлении должен быть в порядке.

1 голос
/ 26 декабря 2009

У вас есть возражения против символа '+'?

Вы уверены, что хотите использовать регулярное выражение вообще, а не просто оператор if для проверки пробелов? Вы говорите «время выполнения». Ваши данные в строке или поступают в поток, или как?

0 голосов
/ 01 марта 2014

Можно использовать lookbehinds / lookaheads, чтобы явно определить, какие разделители нельзя использовать.

Например, этот сканер использует пробелы в качестве разделителя, но не нуждается в них между цифрами и словами:

new Scanner("1A.23 4 BC-5")
.useDelimiter("\\s+|(?<=\\d)(?=[A-Z])|(?<=[A-Z])(?=[-+.\\d])");

Производит:

1
A
.23
4
BC
-5

Регулярное выражение состоит из трех чередований:

  • \s+ последовательные пробелы являются разделителями.
  • (?<=\d)(?=[A-Z]) пустая строка между цифрой и буквой является разделителем.
  • (?<=[A-Z])(?=[-+.\d]) пустая строка между буквой и '-', '+', '.' или же цифра - это разделитель.

(Примечание: \w здесь нельзя использовать, так как оно соответствует цифрам.)

...