Таблицы символов Boost Spirit (X3), приводящие к строкам UTF8

Я пытаюсь разобрать escape-коды LaTeX (например, \alpha) в символы Unicode (математические) (например, U+1D6FC).

Прямо сейчас это означает, что я использую этот symbols парсер (правило):

struct greek_lower_case_letters_ : x3::symbols<char32_t>
{
  greek_lower_case_letters_::greek_lower_case_letters_()
  {
    add("alpha",   U'\u03B1');
  }
} greek_lower_case_letter;

Это работает нормально, но означает, что в результате я получаю std::u32string. Мне нужен элегантный способ сохранить кодовые точки Unicode в коде (возможно, для будущей автоматизации) и по причинам обслуживания. Есть ли способ заставить этот парсер анализировать в UTF-8 std::string?

Я думал о преобразовании структуры symbols в структуру std::string, но это было бы крайне неэффективно (знаю, преждевременная оптимизация, бла-бла).

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

Однако я боюсь, что использование значений кодовых точек и желание UTF8 повлечет за собой затраты времени выполнения преобразования (или возможно ли преобразование constexpr UTF32-> UTF8?).


person rubenvb    schedule 18.12.2015    source источник


Ответы (1)


В примере анализатора JSON в cierelabs показан подход, использующий семантические действия для добавления кодовых точек в utf8. кодировка:

  auto push_utf8 = [](auto& ctx)
  {
     typedef std::back_insert_iterator<std::string> insert_iter;
     insert_iter out_iter(_val(ctx));
     boost::utf8_output_iterator<insert_iter> utf8_iter(out_iter);
     *utf8_iter++ = _attr(ctx);
  };

  // ...

  auto const escape =
         ('u' > hex4)           [push_utf8]
     |   char_("\"\\/bfnrt")    [push_esc]
     ;

Это используется в их

typedef x3::rule<unicode_string_class, std::string> unicode_string_type;

Что, как вы видите, встраивает последовательность utf8 в атрибут std::string.

См. полный код: https://github.com/cierelabs/json_spirit/blob/x3_devel/ciere/json/parser/x3_grammar_def.hpp

person sehe    schedule 18.12.2015
comment
Я решил использовать std::string в качестве ключа/значения символа, и я пытаюсь заставить правило char_ работать как последовательность, используя директиву repeat. Сравнение версий UTF8 и UTF32 здесь. Я не понимаю, почему вторая версия не работает после первой \alpha. - person rubenvb; 19.12.2015
comment
@rubenvb Я посмотрю на это позже сегодня вечером. - person sehe; 19.12.2015
comment
@rubenvb интересно, в моих тестах первая версия не удалась после первого 'a'. Это связано с распространением атрибутов; если symbols дает тот же тип (std::string), что и объемлющий, он получает назначается вместо добавляется (я чувствую, что это ошибка). Поэтому вместо этого я бы использовал std::vector<char> в качестве атрибута, и он работает правильно. Вот немного очищенного кода: coliru.stacked-crooked.com/a/b9555dfd246b5252(note дело reinterpret_cast<> выглядело неправильно, я его изменил). - person sehe; 19.12.2015
comment
@rubenvb, возможно, вам следует опубликовать это как отдельный вопрос. Я постараюсь не забыть спросить в списке рассылки об этом поведении. Прямая трансляция находится здесь: livecoding.tv/video/ (первая часть отсутствует из-за технических проблем) - person sehe; 19.12.2015
comment
В итоге я выбрал пользовательский строковый литерал, который создает std::array. Избегает этой возможной ошибки, является (в принципе) преобразованием кодовой точки во время компиляции в UTF8 и может быть расширено до составных символов без особой суеты. Код, который у меня получился (на данный момент), находится . Я собираюсь преобразовать это в некоторое представление AST, из которого я синтезирую некоторую ограниченную форму поддерживаемого Qt HTML для начала. Спасибо за понимание, хотя. - person rubenvb; 21.12.2015