числовые парсеры Boost-Spirit и получение нужных синтезированных атрибутов - PullRequest
1 голос
/ 06 апреля 2011

- edit - Решил вопрос: комментарий к последнему sidenote будет полезным.Также были бы полезны комментарии по обработке перегрузки phoenix :: bind (в моем ответе).

Я работаю в системе со строгими требованиями к типизации, я хочу убедиться, что я анализирую целые числа, которые соответствуютИз ограничений int32_t и int64_t я не хочу, чтобы синтаксические анализаторы синтезировали и ограничивали анализируемые строки указанными типами.

Как мне это сделать?В документе упоминается, что long_long доступен только на платформах с поддержкой 64-битных систем, но мне также нужно анализировать int64_t на 32-битных платформах.

Отрывок из моего анализатора:следующим образом:

...
  eps(_b == VALUE_INT4) >> qi::long_ 
    [phoenix::bind(&AddEntry, _r1,_a, _1, _pass)] ) // 
| ( eps(_b == VALUE_INT8) >> qi::long_long)
...

AddEntry имеет перегрузку int32_t и перегрузку int64_t, является ли phoenix :: static_cast_ на _1 в порядке?И если это так, то как мне проанализировать 64-битные целые на современной 32-битной платформе?Я предполагаю, что BOOST_HAS_LONG_LONG не определен только на устаревшем оборудовании, таком как 8008 ;).

<Rant> Хотелось бы, чтобы они придерживались стандартов, изложенных в c99 и <boost/cstdint.hpp>Большинство из нас хотят программировать против чистых абстракций.Вероятно, есть веские причины для того, чтобы числовые парсеры были определены так, как они есть.однако использование грандиозной схемы может быть лучше определено в документации.</Rant>

С другой стороны: Соответствует ли вышеприведенный условный стиль epsilon утверждению case в исполнении?

Ответы [ 2 ]

1 голос
/ 06 апреля 2011

1) Парсеры Qi уже проверяют условия переполнения. Компонент парсера потерпит неудачу, если входные данные не будут представлены типом, которому должен соответствовать компонент. Например, int_parser<int32_t, 10> завершится ошибкой для чисел, не помещающихся в 32-разрядное целое число со знаком.

Вы можете использовать синтаксический анализатор long_long (то есть предопределенный 64-битный целочисленный синтаксический анализатор), только если определено BOOST_HAS_LONG_LONG. Если у вас есть платформа, где это не так, вы все равно можете эмулировать 64-битное целое число, написав свой собственный тип оболочки, предоставляющий функциональность, ожидаемую для числовых парсеров Qi (см. здесь ), например:

struct my_64bit_int {
    //...
};
typedef int_parser<my_64bit_int, 10> my_64bit_int_parser_type;
my_64bit_int_parser_type const my_64bit_int_parser;

и используйте его как:

my_64bit_int bigint;
parse(b, e, my_64bit_int_parser, bigint);

2) Вы не можете связывать перегруженные функции без помощи компилятора, т. Е. С учетом:

void AddEntry(int32_t);
void AddEntry(int64_t);

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

phoenix::bind((void(*)(int32_t))&AddEntry, _1);

Ответ на sidenote: Нет. Альтернативный синтаксический анализатор всегда последовательно выполняет различные альтернативы в той же последовательности, как указано, останавливаясь, когда первый из этих совпадений. Его общая сложность составляет O(N), где N - количество отдельных альтернатив (см. здесь ).

0 голосов
/ 06 апреля 2011

Эти шаблоны дадут вам семантику, которую вы хотите.

qi::int_parser< int32_t,  10, 1,10>  p_int32_t;
qi::int_parser< int64_t, 10, 1, 19> p_int64_t;

Эти парсеры прошли модульное тестирование и создали ошибки ожидания при переполнении, т.е. при >= 2^31 и >= 2^63 соответственно.

Перегрузка не воспринимается Phoenix :: bind afaik ( поправьте меня, если я ошибаюсь, пожалуйста ),

поэтому макрос по линиям

#define  ADD_ENTRY(TP,prefix)                                           \
    void AddEntry_##prefix( value_variant_vector & v, uint32_t ordinal, \
                            TP entry, bool & ok_)                       \

Для тех, кто заинтересован, сообщение об ошибке компилятора выглядит следующим образом (когда AddEntry является функцией шаблона):

/opt/dev_64_swat/dsl/src/parser/RowAndTable.cc:43: error: no matching function 
for call to ‘bind(<unresolved overloaded function type>, const
boost::phoenix::actor<boost::spirit::attribute<1> >&, const 
boost::phoenix::actor<boost::spirit::local_variable<0> >&, const 
boost::phoenix::actor<boost::spirit::argument<0> >&, const   
boost::phoenix::actor<boost::phoenix::argument<2> >&)’

Я также получаю сообщения об ошибках, написанных от руки.

...