Разбор Objective-C printf Форматирование строк?

Я хочу получить диапазоны членов внутри NSString, построенных с помощью +[NSString stringWithFormat:]. Каков наилучший способ разбора строки формата objective-c? Я не могу просто использовать синтаксический синтаксический анализатор формата C из-за %@. Я также должен убедиться, что он поддерживает порядок форматирования: %1$d, %[email protected] и т.д.

Например, с строкой, построенной с помощью [NSString stringWithFormat:@"foo %[email protected] bar %[email protected]", @"Heath", @"Borders"], мне бы идеально понравилось следующее NSArray: @[NSMakeRange(15, 5), NSMakeRange(4, 6)]. Первый объект массива соответствует первому элементу данных в строке формата, второму объекту массива - второму элементу данных и т.д.

В этом случае API будет выглядеть примерно так: + (NSString *) stringWithFormatRanges:(NSArray **)outFormatRanges withFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2); Он вернет NSString точно так же, как +[NSString stringWithFormat:], но он также вернет NSArray с NSRange каждого элемента данных формата.

- EDIT -

Учитывая, что этот вопрос составляет 3 года, я был бы доволен реализацией C-only на этом этапе.

Ответ 1

Я изучил это несколько лет назад. Если я понимаю ваш вопрос, нет простого способа получить AST из строки формата для строк формата C или Cocoa.

Я написал NSXMLElement + elementWiспасибоMLFormat, который допускал несвязанную вставку NSXMLElements в строку формата со специальным кодом формата %%%@, который требовал расширения формата Cocoa. Мой метод может быть вам полезен:

https://github.com/rentzsch/nsxmlelement-elementwithxmlformat/blob/937b54b2a830a8fbbd72d6bc5e48bafd495ddcbd/NSXMLElement%2BelementWithXMLFormat.m#L41

Я извлекаю и NUL-разграничивает только коды формата, запускаю его традиционно, а затем снова собираю.

Ответ 2

Я написал синтаксический анализатор для тех, кто работает в Swift (чтобы я мог обнаружить эти заполнители в Localizable.strings и извлечь, какие типы должны были быть получены при вызове stringWithFormat: с этими строками) для моего инструмента SwiftGen

Вы можете увидеть часть кода, выполняющую синтаксический анализ, на моем GitHub.

  • Конечно, это в Swift, а не в Objective-C, но я думаю, что это легко переносится в ObjC, если вы сохраняете логику алгоритма.
  • Мой код не возвращает диапазоны в качестве вывода этих функций - только типы - но код в функциях typesFromFormatString определенно имеет доступ к диапазонам этих заполнителей и может полностью возвращать их в дополнение к обнаруженному типу (что легко изменить, мне просто не нужны эти диапазоны, поэтому я не включил их в тип возвращаемого значения)

(Если у вас есть диапазоны для заполнителей, таких как %d или %[email protected], будет легко определить диапазоны для строковых параметров: первый диапазон будет иметь такое же .location Как и первый заполнитель, но длина замененное значение, у 2-го диапазона будет .location 2-го заполнителя + (firstValue.length-firstRange.length) для учета смещения и т.д.)

НТН.