Как семантические действия (с использованием _val и _attr) влияют на определение правила с% = и x3 :: rule force_attribute = true?

Данный семантический актор

template<typename ValueType>
class divide
{
public:
  divide(ValueType value) : divisor{value} {}

  template<typename ContextType>
  void operator()(ContextType& context) const
  {
    _val(context) /= divisor;
  }
private:
  const ValueType divisor;
};

похоже, я улавливаю тот факт, что наличие семантических действий препятствует синтезу атрибутов (или распространению?), т.е.

const auto norm = x3::rule<struct _, double>{"norm"}
                = x3::double_[normalize{100.}];

дает мне значение 0.

Поэтому я попытался заставить распространение атрибута с помощью %=

const auto norm_rule = x3::rule<struct _, double>{"norm"}
                    %= x3::double_[normalize{100.}];

Это дает мне ожидаемое проанализированное значение, деленное на 100.

Затем я обнаружил, что у x3::rule есть третий аргумент шаблона, bool force_attribute, и заметил, что

const auto norm_rule = x3::rule<struct _, double, true>{"norm"}
                     = x3::double_[divide{100.}];

Имеет желаемый результат в виде значения, деленного на 100.

Поэкспериментировав дальше, я обнаружил, что вместо этого могу определить divide::operator() следующим образом:

void operator()(ContextType& context)
{
  _attr(context) = _val(context) / divisor;
}

Последний, кажется, сильно связывает / осуждает семантический актор на верхний уровень правила, поскольку он действует на атрибут _attr первого правила вместо значения _val синтаксического анализатора, к которому он прикреплен.

Правильно ли я сделаю вывод, что

  1. %= это то же самое, что задать для третьего x3::rule параметра шаблона force_attribute значение true?
  2. Этот тип семантических действий обработки значений должен работать исключительно с _val, чтобы они работали с присоединенным синтаксическим анализатором вместо первого rule, встречающегося в иерархии?

Я понимаю, что эти вопросы могут показаться несвязанными, но они действительно связаны, поскольку я пытаюсь обработать проанализированное число (float) и преобразовать его в uint8 несколькими способами. Чтобы быть полностью полным: у меня есть рабочий код (числовой код здесь и то, что я создаю / разбираю здесь), но это кажется излишне сложным (из-за вышеизложенного мне кажется, что мне нужно правило для преобразования типа / значения, что кажется глупым.


person rubenvb    schedule 29.12.2018    source источник
comment
Хм кажется я поменял местами значения _attr и _val. Первый должен быть результатом присоединенного парсера, а второй - атрибутом правила. По крайней мере, я могу понять собственное замешательство. Я оставлю вопрос как есть, пока я не разберусь с этим, я боюсь, что его изменение сделает его хуже, чем сейчас.   -  person rubenvb    schedule 29.12.2018


Ответы (1)


кажется, я улавливаю тот факт, что наличие семантических действий препятствует синтезу атрибутов (или распространению?)

Это так, поведение было скопировано из Qi (_ 1_ docs, _ 2_).

Соответствующие части кода: позвоните на сайт, обработка.

%= это то же самое, что задать для третьего x3::rule параметра шаблона force_attribute значение true?

Да, это не задокументировано, см. Код _ 6_.

Поэкспериментировав дальше, я обнаружил, что могу определить divide::operator() следующим образом:

void operator()(ContextType& context)
{
  _attr(context) = _val(context) / divisor;
}

Последний, кажется, сильно связывает / осуждает семантический актор на верхний уровень правила, поскольку он действует на атрибут _attr первого правила вместо значения _val синтаксического анализатора, к которому он прикреплен.

Вы поняли почти правильно, но поменяли их местами. Это должно быть _val(context) = _attr(context) / divisor, подробности ниже.

Этот тип семантических действий обработки значений должен работать исключительно с _val, чтобы они работали с присоединенным синтаксическим анализатором вместо первого rule, встречающегося в иерархии?

Документация по семантическим действиям описывает, что такое _val и _attr:

Function  Description                                         Example
--------  --------------------------------------------------  -----------------------
_val      A reference to the attribute of the innermost rule  _val(ctx) = "Gotya!"
          that directly or indirectly invokes the parser p    
_attr     A reference to the attribute of the parser p        _val(ctx) += _attr(ctx)

Какими они будут в конкретной ситуации, зависит от _17 _ / _ 18_ качеств. По умолчанию они будут ссылаться на одно и то же значение, пока у вас не будут вложенные правила с разными типами атрибутов (соответствующий код).

P.S. Я ничего не могу сказать о причине, по которой это так. Я вижу, что многие пользователи Spirit просто используют %= повсюду, потому что интуитивно это должно быть по умолчанию, и вы можете вручную отключить распространение с помощью директивы omit. Более того, у Qi есть некоторые ошибки из-за этого механизма, когда вы используете ленивые значения в чем-то вроде директивы repeat (ticket 13313).

person Nikita Kniazev    schedule 29.12.2018