синтаксический анализ вызовов функций как выражений с использованием boost spirit x3

#c #parsing #boost-spirit #boost-spirit-x3

#c #синтаксический анализ #boost-spirit #boost-spirit-x3

Вопрос:

В настоящее время я разрабатываю DSL с использованием boost spirit X3. Я использую этот пример для реализации выражений и иерархии операторов и избежания левой рекурсии в анализаторах выражений. Я также хотел бы реализовать . -оператор для доступа к элементам, [] -оператор для доступа к индексу, например, для массивов, и поскольку DSL будет функциональным языком, я хотел бы реализовать вызовы функций, () -оператор, также в качестве оператора, поскольку каждое выражение может возвращать функцию, () -оператор должен быть применим к любому другому выражению. Результаты, которые я хочу проанализировать, выглядят следующим образом:

 enum class operator_t {
    _eq_,       // ==
    _ne_,       // !=
   ...
    _idx_,      // []
    _apply_,    // ()
    _access_    // .
};

typedef x3::variant<
        nil,
        std::string,
        NumberLiteral,
        x3::forward_ast<Unary>,
        x3::forward_ast<Expression>,
> Operand;

struct Unary {
    operator_t operator_;
    Operand operand_;
};

struct Operation {
    operator_t operator_;
    Operand operand_;
};

struct Expression {
    Operand first_;
    std::vector<Operation> rest_;
};
  

Я смог создать синтаксические анализаторы для []-operator и .-operator , используя следующие правила (взгляните на mcve в РЕДАКТИРОВАНИИ):

 typedef x3::rule<struct primary_expr_class, ast::Operand> primary_expr_type;
typedef x3::rule<struct index_access_expr_class, ast::Expression> index_access_expr_type;
typedef x3::rule<struct data_access_expr_class, ast::Expression> data_access_expr_type;

auto const index_access_expr_def =
        primary_expr >> *(helper::idxaccess_op > expression > "]");

auto const data_access_expr_def =
        index_access_expr >> *(helper::access_op > index_access_expr);
  

теперь я пытаюсь сделать то же самое для вызовов функций, но я не смог этого сделать, также index_access_expr и data_access_expr не имеет приоритета, как я могу заставить эти два правила иметь приоритет и как я могу реализовать вызовы функций как выражения оператора, также с тем же приоритетом?

РЕДАКТИРОВАТЬ: здесь приведен mcve о том, как я сделал это с помощью index_access_expr и data_access_expr . К этому примеру я хотел бы добавить ()-operator , и я хотел бы, чтобы у трех операторов был одинаковый приоритет.

РЕДАКТИРОВАТЬ II: вот еще один mcve, о том, как я устал реализовывать вызовы функций в виде выражений, но, как вы можете видеть в примере, это вообще не работает. Мой подход состоял в том, чтобы добавить std::vector<Expression> к Operand варианту, а затем попытался добавить анализатор вызовов функций следующим образом:

  auto const func_call_expr_def =
        data_access_expr >> *(func_call_op > (expression % ",") > ")");
  

Это вообще не работает, взгляните на мои тесты в main , также проблема с иерархией операторов все еще существует.