Maison > développement back-end > C++ > Comment pouvons-nous analyser des expressions booléennes en C à l'aide de Boost.Spirit pour créer une structure arborescente, respectant la priorité des opérateurs ?

Comment pouvons-nous analyser des expressions booléennes en C à l'aide de Boost.Spirit pour créer une structure arborescente, respectant la priorité des opérateurs ?

Mary-Kate Olsen
Libérer: 2024-12-25 19:36:13
original
572 Les gens l'ont consulté

How can we parse Boolean expressions in C   using Boost.Spirit to create a tree structure, respecting operator precedence?

Analyse d'expressions booléennes en C

Introduction

Nous visons à créer un analyseur qui transforme une expression booléenne en une structure arborescente, en respectant les règles de priorité des opérateurs (pas, et, xor, ou).

Tokenisation

Pour commencer, nous allons définir des expressions régulières pour faire correspondre différents jetons dans l'expression :

  • Variables : Séquences d'un ou plusieurs caractères alphabétiques
  • Opérateurs : "et", "ou", "xor", "not"
  • Parenthèses : "(" et ")"
using namespace boost::spirit::qi;
typedef std::string var;
qi::rule<std::string::const_iterator, var(), qi::space_type> var_ = qi::lexeme[+alpha];
qi::rule<std::string::const_iterator, std::string(), qi::space_type> operator_ = 
    keywords("and" | "or" | "xor" | "not");
qi::rule<std::string::const_iterator, char(), qi::space_type> parenthesis_ = qi::char_("()[]");
Copier après la connexion

Règles de grammaire

Ensuite, nous définissons des règles de grammaire à combiner tokens :

  • Expression : Commence par soit une expression entre parenthèses, une variable ou "pas" suivi d'une expression
  • Sous-expression : Suit les règles de priorité (non, et, xor, ou)
qi::rule<std::string::const_iterator, expr(), qi::space_type> expression_ = (
    '(' >> expression_ >> ')'
) | var_ | operator_ >> expression_;

qi::rule<std::string::const_iterator, expr(), qi::space_type> sub_expression_ = 
    expression_ >> *operator_ >> expression_;
Copier après la connexion

Parsing

Pour analyser l'expression, nous utilisons une fonction boost::spirit phrase_parse, qui tente de faire correspondre la chaîne d'entrée entière aux règles de grammaire.

std::string input = "(a and b) xor (c and d)";
auto it = input.begin();
auto end = input.end();
expr parsed_expression;

bool success = phrase_parse(it, end, expression_, qi::space, parsed_expression);

if (success && it == end) {
    std::cout << "Parse successful!" << std::endl;
} else {
    std::cerr << "Parse failed!" << std::endl;
}
Copier après la connexion

Construire l'arbre

Une fois l'expression analysée, nous pouvons construire l'arbre arborescence. Voici un exemple d'implémentation :

typedef std::vector<expr> expr_set;
expr_set nodes;

void create_node(const expr& sub_expr) {
    if (sub_expr.is<std::string>()) {
        nodes.push_back(sub_expr.get<std::string>());
    } else {
        nodes.push_back(expr_set{sub_expr.get<expr_set>()});
    }
}

void build_tree(const expr& root) {
    if (root.is<std::string>()) {
        nodes.push_back(root.get<std::string>());
    } else {
        expr_set sub_expressions = root.get<expr_set>();
        for (const auto& sub_expr : sub_expressions) {
            create_node(sub_expr);
        }
    }
}
Copier après la connexion

Exemple d'utilisation

input = "(a and b) xor (c and d)";
it = input.begin();
end = input.end();

if (phrase_parse(it, end, expression_, qi::space, parsed_expression)) {
    std::cout << "Parse successful!" << std::endl;
    build_tree(parsed_expression);
} else {
    std::cerr << "Parse failed!" << std::endl;
}

for (const auto& node : nodes) {
    std::cout << node << std::endl;
}
Copier après la connexion

Sortie :

(
a
and
b
)
xor
(
c
and
d
)
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal