Как семантические действия (с использованием _val и _attr) влияют на определение правил с помощью% = и x3 :: rule's force_attribute = true? - PullRequest
0 голосов
/ 29 декабря 2018

Учитывая семантический актер

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 несколькими способами.Чтобы быть полностью законченным: у меня есть рабочий код (числовой материал здесь и фактическая вещь, которую я создаю / анализ здесь ), но он кажется излишне сложным (из-за вышеизложенного он кажетсяМне нужно правило для преобразования типа / значения, которое кажется глупым.

1 Ответ

0 голосов
/ 29 декабря 2018

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

Это так, поведение было скопировано из Ци (qi::rule документы , How Do Rules Propagate Their Attributes?).

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

%= - это то же самое, что и установка третьего * x3::rule параметра шаблона force_attribute в значение true

Да, это не задокументировано, см. Код boost/spirit/home/x3/nonterminal/rule.hpp.

Экспериментируя далее, я также обнаружил, что вместо этого могу определить 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)

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

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

...