Outil pour convertir plus rapidement les formules en code C #

Vlad

Outil pour convertir plus rapidement les formules en code C #


Je cherche un outil où je peux simplement taper b * (1 + k) ^ 9 et avoir b * Math.Pow(1 + k, 9) ou encore mieux b * (float)Math.Pow(1 + k, 9) en sortie.

Cela semble assez facile?

Thomas Weller

Quel OS? Quel prix? Comment le convertisseur pouvait-il savoir qu’il fallait un plâtre pour flotter? Et si une partie de l’expression provoque un débordement? Quels opérateurs doivent être pris en charge? Aussi n! (factoriel), sin x, cos x? Avez-vous également x² et x³ ou seulement x ^ 2? La division est-elle / ou: ou les deux? Cela semble facile, mais laisse de nombreuses questions ouvertes.

Vlad

@ThomasWeller tout ce que je peux exécuter sur Windows. x ^ n et arithmétique de base / * + – est suffisant, tout ce qui est supplémentaire est .. extra))

Vlad

@ThomasWeller cast to float – en tant que développeur d’un tel outil (je ne le suis pas), je ferais une case à cocher pour lancer toutes les valeurs de retour double des méthodes Math à float .

svick

Pourquoi voulez-vous les convertir en code C #? Voulez-vous simplement les évaluer dans un programme C #? Voulez-vous les inclure dans votre code C #? Autre chose?

Vlad

@svick « Voulez-vous les inclure dans votre code C #? » – Oui.

Réponses


 Ira Baxter

Je doute que vous trouverez un outil qui fait exactement ce que vous voulez sur étagère; le nombre de paires de traductions du langage informatique A vers le langage B est important car il y a beaucoup d’As et de Bs, et vous en voulez une spécifique. (Voir https://stackoverflow.com/q/3455456/120163 pour une discussion sur les traductions linguistiques)

OTOH, votre traduction est probablement plus facile que la plupart, se limitant à de simples expressions. Vous pouvez probablement le faire avec un traducteur orienté syntaxe , par exemple:

  1. Construisez un analyseur de descente récursif pour la langue source.
  2. Pendant que l’analyseur s’exécute et effectue des réductions, crachez la traduction.

Une variante plus sophistiquée:

  1. Construire un analyseur de descente récursif qui construit un arbre pour l’expression
  2. Parcourez l’arbre dans l’ordre et crachez la traduction

L’un ou l’autre est probablement assez facile.

Si vous voulez une attaque plus structurée, vous pouvez utiliser un système de transformation de programme (PTS) . Ces outils analysent la source selon une grammaire, construisent une arborescence correspondante pour la source, puis vous permettent de fournir des règles de réécriture pour mapper l’arborescence d’origine à une arborescence révisée, puis peuvent imprimer le résultat.

Voici à quoi cela ressemblerait avec mon PTS appelé DMS. Cette réponse ne couvre que votre exemple spécifique et devrait être étendue pour gérer la plage de jetons et de formules Excel que vous souhaitez gérer; par exemple, je ne gère pas une valeur à virgule flottante (extension facile).

Vous auriez besoin d’un lexer et d’un analyseur pour les formules Excel. Vous avez besoin d’un lexer et d’un analyseur pour les expressions C # couvrant ce dont vous avez besoin pour les formules Excel. Avec ces deux en main, DMS nous permettra d’écrire des règles de traduction entre les deux.

Commençons par Excel.

Formule Excel Lexer:

 #skip "[u0020]+" -- ignore whitespace #token '+' "+" -- plus operator #token '*' "*" -- times operator #token '^' "^" -- exponential operator #token '(' "(" -- left paren #token ')' ")" -- right paren #token NUMBER [STRING] "[0-9]+" << (ConvertStringToToken ? 0 0) (= ?:Lexeme:String:Format 0) ; no quote on string >> #token IDENTIFIER [STRING] "[az]" << (ConvertStringToToken ? 0 0) (= ?:Lexeme:String:Format 0) ; no quote on string >> 

Analyseur de formule Excel:

 Excel = expression ; expression = product ; expression = expression '+' product ; product = power product = product '*' power ; power = primitive ; power = power '^' primitive; primitive = IDENTIFIER ; primitive = NUMBER ; primitive = '(' expression ')' ; 

Cela suffit pour que DMS analyse vos formules Excel et produise automatiquement un AST.

Nous avons besoin de la même chose pour les expressions C #:

Formule C # Lexer (notez que les noms terminaux et non terminaux pour C #, bien que nominalement identiques à ceux pour Excel, appartiennent à C # [pensez aux grammaires comme étant des espaces de noms séparés]:

 #skip "[u0020u000du000a]+" -- ignore whitespace and line breaks #precomment "[][] ~[u000duooa]+" -- single line comments #token '+' "+" -- plus operator #token '*' "*" -- times operator #token '^' "^" -- exponential operator #token '.' "." -- dot between identifiers in named entity #token '(' "(" -- left paren #token ')' ")" -- right paren #token NATURAL [STRING] "[0-9]+" << (ConvertStringToToken ? 0 0) (= ?:Lexeme:String:Format 0) ; no quote on string >> #token ID [STRING] "[az]+" << (ConvertStringToToken ? 0 0) (= ?:Lexeme:String:Format 0) ; no quote on string >> 

Analyseur d’expression C # (assez bon pour cette tâche)

 CSharp = expression ; expression = product ; expression = expression '+' product ; product = power product = product '*' power ; power = term ; power = power '^' term; term = named_entity ; term = named_entity '(' expression ')' ; -- function call term = NATURAL ; term = '(' expression ')' ; term = '( ID ')' term ; -- cast named_entity = ID ; named_entity = named_entity '.' ID ; 

Avec cela, DMS analysera les expressions C # simples; nous en profiterons dans la partie droite des règles de réécriture ci-dessous. DMS imprimera également tout C # analysé (ou généré) en utilisant uniquement ces informations; cela nous permettra de traduire Excel en C #, puis d’imprimer le résultat.

Je triche un peu: j’ai besoin de jolies règles d’impression pour C #. Cependant, DMS déduira un ensemble de ces règles à partir de la grammaire uniquement; puisque C # ne se soucie pas des espaces, les règles de jolie impression produites par DMS produiront un texte légal sinon « joli ». (On peut ajouter les règles de prettyprinting pour le rendre plus joli, mais cela n’affecte pas vraiment notre exemple).

OK, maintenant nous sommes prêts à écrire nos règles de traduction. Ces règles ressemblent à:

 rule <rulename>( parameter: nonterminalA, ...) : nonterminalA -> nonterminalB = " <A_syntax_instance> " -> "<B_syntax_replacement>" 

pour les languettes A et B.

Heureusement, les grammaires sont très similaires, donc les règles de traduction sont faciles et ont tendance à mapper les constructions dans Excel à des constructions presque identiques en C #:

 source domain Excel; -- says to read left hand side of rules as 'excel syntax' target domain Csharp; -- and right hand sides as 'CSharp syntax' rule translate_IDENTIFIER(i: IDENTIFIER): IDENTIFIER -> ID "i" -> " i" ; -- tells DMS to translate Excel node to C# node and copy the string -- fortunately for us, the CSharp ID names are a superset of what Excel offers, -- so we don't need any string hack to translate the identifiers rule translate_NUMBER(n: NUMBER): NUMBER -> NATURAL = "n" -> "n" ; -- tells DMS to translate Excel NUMBER to CSharp Natural and copy the numeric value rule translate_parentheses(e: expression): primtive -> term = " ( e ) " -> " ( e ) " ; -- these looks the same module syntax terms across the two langauge rule translate_sum(e: expression, p: product): expression -> expression = " e + p " -> " e + p "; rule translate_product(p1: product, p2: power): product -> product = " p1 * p2 " -> " p1 * p2 "; rule translate_power(p1: power, p2: primitive): power -> power = " p1 ^ p2 " -> " (float)Math.Pow(p1,p2)"; 

Pour comprendre ces règles en détail, voir Règles de réécriture DMS

Pour utiliser tout cela:

  1. l’un donne au sous-outil DMS Refiner la définition de lexer / parser pour Excel, la définition de lexer / parser pour CSharp et l’ensemble de règles ci-dessus.
  2. Le raffineur lit un fichier contenant le texte Excel, l’analyse selon la syntaxe Excel («domaine source Excel») et crée un AST pour le code Excel.
  3. Le raffineur applique les règles jusqu’à ce qu’aucune règle ne s’applique [cela convertit l’AST Excel en AST CSharp]
  4. Le raffineur appelle la jolie imprimante CSharp sur l’arbre résultant.

Cela devrait produire exactement ce que souhaite OP.

Je n’ai pas testé cela, mais c’est assez proche de la droite.

Pour la taille de la tâche que OP veut vraiment faire, le schéma axé sur la syntaxe est probablement moins de travail; c’est certainement une solution beaucoup plus « petite » (le DMS est une machine assez grosse). Mais si vos traductions commencent à devenir plus complexes, l’approche basée sur la syntaxe devient rapidement incontrôlable, tandis que le chemin DMS reste très efficace. YMMV.

 

#, #en, #pour, C, code, convertir, formules, Les, Outil, plus, rapidement

 

elle.fr

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *