Détecter les parenthèses dans BinaryExpression

.net c# expression-trees parentheses

Question

Je suis en train de construire un analyseur d'expression à partir duquel je souhaite générer un code de requête de base de données. Je suis allé assez loin, mais je suis bloqué à analyser BinaryExpressions avec précision. Il est assez facile de les diviser en gauche et en droite, mais je dois détecter les parenthèses et générer mon code en conséquence et je ne vois pas comment faire.

Un exemple [veuillez ignorer la logique erronée :)]:

a => a.Line2 != "1" && (a.Line2 == "a" || a.Line2 != "b") && !a.Line1.EndsWith("a")

Je dois détecter le "set" au milieu et conserver leur regroupement, mais je ne vois aucune différence dans l'expression par rapport à une expression binaire normale lors de l'analyse (je ne voudrais pas vérifier la représentation sous forme de chaîne entre parenthèses)

Toute aide serait appréciée.

(Je devrais probablement mentionner que j'utilise C #)

--Modifier-- J'ai omis de mentionner que j'utilise les classes d'expressions .Net standard pour construire les expressions (espace de noms System.Linq.Expressions)

--Edit2-- Ok, je ne suis pas en train d'analyser du texte en code, je suis en train d'analyser du code en texte. Donc, ma classe de Parser a une méthode comme celle-ci:

void FilterWith<T>(Expression<Func<T, bool>> filterExpression);

ce qui vous permet d'écrire du code comme ceci:

FilterWith<Customer>(c => c.Name =="asd" && c.Surname == "qwe");

ce qui est assez facile à analyser en utilisant les classes .Net standard, mon défi est d'analyser cette expression:

FilterWith<Customer>(c => c.Name == "asd" && (c.Surname == "qwe" && c.Status == 1) && !c.Disabled)

Mon défi est de garder les expressions entre parenthèses comme un seul ensemble. Les classes .Net séparent correctement les parties entre parenthèses des autres, mais n'indiquent pas qu'il s'agit d'un ensemble en raison de la parenthèse.

Réponse acceptée

Je n'ai pas utilisé Expression moi-même, mais si cela fonctionne comme n'importe quel autre AST, le problème est alors plus facile à résoudre que vous ne le croyez. Comme un autre intervenant l'a fait remarquer, il suffit de mettre des parenthèses autour de toutes vos expressions binaires pour éviter les problèmes d'ordre des opérations.

Vous pouvez également vérifier si l'expression que vous générez a une priorité inférieure à celle de l'expression qui la contient et, le cas échéant, mettez-la entre parenthèses. Donc, si vous avez un arbre comme celui-ci [* 4 [+ 5 6]] (où les nœuds d’arbre sont représentés de manière récursive par [node left-subtree right-subtree] ), vous saurez quand vous écrivez l’arbre [+ 4 5] que il était contenu dans une opération * , ce qui est plus prioritaire qu'une opération + et nécessite donc qu'aucun de ses sous-arbres immédiats soit placé entre parenthèses. Le pseudo-code pourrait ressembler à ceci:

function parseBinary(node) {
    if(node.left.operator.precedence < node.operator.precedence)
        write "(" + parseBinary(node.left) + ")"
    else
        write parseBinary(node.left)
    write node.operator
    // and now do the same thing for node.right as you did for node.left above    
}

Vous aurez besoin d'un tableau de priorité pour les différents opérateurs et d'un moyen de contacter l'opérateur lui-même pour savoir de quoi il s'agit et par la suite quel est son ordre de priorité. Cependant, j'imagine que vous pouvez comprendre cette partie.


Réponse populaire

Lors de la construction d’un analyseur d’expression, vous avez d’abord besoin d’un analyseur et, pour cela, d’un tokenizer.

Un tokenizer est un morceau de code qui, en lisant une expression, génère des jetons (qui peuvent être valides ou invalides) pour une syntaxe déterminée.

Par conséquent, votre analyseur, à l'aide du tokenizer, lit l'expression dans l'ordre établi (de gauche à droite, de droite à gauche, de haut en bas, selon votre choix) et crée un arbre qui mappe l'expression.

Ensuite, l'analyseur interprète l'arbre en une expression, en donnant sa signification définitive.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi