#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
, также проблема с иерархией операторов все еще существует.