(Presumo e spero che tu voglia inserire il codice genuino C ++ 11 o C ++ 14 utilizzando il suo standard contenitori & utilità libreria ; non utilizzare una precedente variante di C ++, assicurati di avere un compilatore recente : a giugno 2016, usa GCC versione 5 o 6 e / o Clang / LLVM versione 3.7 o 3.8 , essendo entrambi software gratuito )
Probabilmente vuoi rappresentare l' albero di sintassi astratto (AST) delle tue espressioni analizzate. Ulteriori informazioni su analisi . Potresti voler leggere i primi capitoli del Libro dei draghi . Oppure codifica un semplice parser di discesa ricorsivo . Oppure usa un parser generator (spesso erroneamente chiamato compilatore-compilatore ) come ANTLR3 o GNU bison -o alcuni yacc -). BTW il tuo problema è simile a uno degli esempi forniti in bison
documentazione ( infix calc ).
Non organizzerai il tuo AST come un elenco in C ++, ma come un albero . Ad esempio, potresti avere una superclasse comune (astratta) class expr
e avere una sottoclasse astratta per foglie class leaf_expr: public class expr
con sottoclassi finali concrete come class int_expr: public leaf_expr
per valori letterali interi (ad esempio 12
), class var_expr: public leaf_expr
per variabili (ad es. %codice%). Avrai una superclasse x
per i nodi binari contenenti puntatore intelligente (probabilmente class binary_expr : class_expr
...) per sottoalberi sinistro e destro- con sottoclassi finali in calcestruzzo std::shared_ptr<expr>
ecc per i nodi somma (ad esempio per class sum_expr : public class binary_expr
).
Se hai bisogno di ottenere una traduzione postfissa del tuo AST, definirai un'altra rappresentazione per le espressioni postfisse, forse come una lista di puntatori intelligenti ai componenti postfix, e definirai un'altra gerarchia di classi per i tuoi componenti postfix: una superclasse astratta x+12
con varie sottoclassi class postfix
(per un operando letterale intero postfisso come class int_postfix
), 12
(per un operando variabile postfisso come class var_postfix
), x
(per un operatore postfisso come class plus_postfix
), usando alcune superclassi astratte intermedie come +
per operandi e class operand_postfix : public postfix
e probabilmente class operator_postfix : public postfix
e class unary_operator_postfix : public operator_postfix
ecc ...) ... e hanno una lista di puntatori intelligenti di questi ( per esempio class binary_operator_postfix : public operator_postfix
...). Quindi puoi facilmente codificare un trasformatore da AST a elenco postfix:
std::list<std::unique_ptr<postfix>> transform_ast_to_postfix
(std::shared_ptr<expr>);
The problem is that I don't know how to store operators and operands in the same list
Avrai una lista di puntatori intelligenti per una super classe comune, ad es. %codice%. In alcuni casi (ma non nel tuo) potresti anche considerare di avere un elenco di oggetti contenenti una unione taggata . FWIW C ++ 17 ti darà std :: qualsiasi
(Si potrebbe evitare esplicitamente che rappresenta AST in memoria e costruire direttamente l'elenco di puntatori intelligenti su std::list<std::unique_ptr<postfix>>
elementi nelle azioni del parser, ma credo che la costruzione dell'AST sia più facile e più generale)
Si noti che una buona comprensione dei puntatori e puntatori intelligenti è essenziale . L'utilizzo di puntatori intelligenti invece di puntatori non elaborati (ad esempio std::list<std::unique_ptr<postfix>>
) potrebbe aiutarti a scrivere codice più pulito ed evitare perdite di memoria . Dovresti capire RAII e probabilmente (in C ++ 11) regola di cinque . Vedi questa domanda.
Dovresti leggere la programmazione - Principi e ampli di Stroustrup; pratica usando C ++