File indexing completed on 2024-04-21 03:41:36
0001 /* 0002 SPDX-FileCopyrightText: 2005 Inge Wallin <inge@lysator.liu.se> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #ifndef MOLECULEPARSER_H 0007 #define MOLECULEPARSER_H 0008 0009 #include "science_export.h" 0010 0011 #include "element.h" 0012 #include "parser.h" 0013 0014 #include <QList> 0015 #include <QMap> 0016 0017 /** 0018 * @class ElementCount 0019 * @author Inge Wallin 0020 */ 0021 class SCIENCE_EXPORT ElementCount 0022 { 0023 public: 0024 /** 0025 * Constructor 0026 */ 0027 ElementCount(Element *_element, int _count) 0028 { 0029 m_element = _element; 0030 m_count = _count; 0031 } 0032 0033 /** 0034 * Constructor 0035 */ 0036 explicit ElementCount(Element *_element) 0037 { 0038 m_element = _element; 0039 m_count = 0; 0040 } 0041 /** 0042 * Destructor 0043 */ 0044 ~ElementCount(); 0045 0046 /** 0047 * @return the Element 0048 */ 0049 Element *element() const 0050 { 0051 return m_element; 0052 } 0053 0054 /** 0055 * @return the number of occurrences of the Element 0056 */ 0057 int count() const 0058 { 0059 return m_count; 0060 } 0061 0062 /** 0063 * Add @p _count occurrences of the Element 0064 * @param _count The number of times the Element occurs 0065 */ 0066 void add(int _count) 0067 { 0068 m_count += _count; 0069 } 0070 void multiply(int _factor) 0071 { 0072 m_count *= _factor; 0073 } 0074 0075 /** 0076 * The Element of the object 0077 */ 0078 Element *m_element; 0079 /** 0080 * The number of occurrences 0081 */ 0082 int m_count; 0083 }; 0084 0085 /** 0086 * This class is used to count the elements in the molecule 0087 * which is being calculated 0088 * 0089 * @class ElementCountMap 0090 * @author Inge Wallin 0091 */ 0092 class SCIENCE_EXPORT ElementCountMap 0093 { 0094 public: 0095 /** 0096 * Constructor 0097 */ 0098 ElementCountMap(); 0099 0100 /** 0101 * Destructor 0102 */ 0103 ~ElementCountMap(); 0104 0105 /** 0106 * Clear the map of ElementCount pointers 0107 */ 0108 void clear() 0109 { 0110 m_map.clear(); 0111 } 0112 0113 /** 0114 * @param _element the searched Element 0115 * @return the Element which is searched 0116 */ 0117 ElementCount *search(Element *_element); 0118 0119 /** 0120 * @param _map 0121 */ 0122 void add(ElementCountMap &_map); 0123 0124 /** 0125 * Returns the elements in the molecule. For example, if the molecule 0126 * is CO2, a list with C and O will be returned. 0127 * @return the elements in the molecule 0128 */ 0129 QList<Element *> elements() const; 0130 0131 /** 0132 * @param _element 0133 * @param _count 0134 */ 0135 void add(Element *_element, int _count); 0136 0137 /** 0138 * @param _factor 0139 */ 0140 void multiply(int _factor); 0141 0142 QList<ElementCount *> map() 0143 { 0144 return m_map; 0145 } 0146 0147 private: 0148 QList<ElementCount *> m_map; 0149 }; 0150 0151 /** 0152 * @class MoleculeParser 0153 * 0154 * Parse molecule formulas. 0155 * 0156 * Usage: 0157 * @code 0158 * MoleculeParser parser; 0159 * QString chemical_formula = "C2H5OH"; 0160 * double weight; 0161 * 0162 * if (parser.weight(chemical_formula, &weight)) 0163 * cout << "Weight of " << chemical_formula << " = " << weight << ".\n"; 0164 * else 0165 * cout << "Parse error\n"; 0166 * @endcode 0167 * 0168 * If a short form of a compound is specified, it will be expanded. 0169 * Example :- EtOH -> (C2H5OH) 0170 * @code 0171 * MoleculeParser parser; 0172 * QString chemical_formula = "EtOH"; 0173 * double weight; 0174 * 0175 * if (parser.weight(chemical_formula, &weight)) 0176 * cout << "Weight of " << chemical_formula << " = " << weight << ".\n"; 0177 * else 0178 * cout << "Parse error\n"; 0179 * @endcode 0180 * 0181 * @author Inge Wallin 0182 * @author Kashyap R Puranik 0183 */ 0184 class SCIENCE_EXPORT MoleculeParser : public Parser 0185 { 0186 public: 0187 /** 0188 * @param list This list of chemical elements will be used internally 0189 * for searching and matching with searched strings 0190 * Constructor 0191 */ 0192 explicit MoleculeParser(const QList<Element *> &list); 0193 0194 /** 0195 * Constructor 0196 * 0197 * @param _str @ref Parser::start the parsing with @p _str 0198 */ 0199 explicit MoleculeParser(const QString &_str); 0200 0201 /** 0202 * Destructor 0203 */ 0204 ~MoleculeParser() override; 0205 0206 /** 0207 * Try to parse the molecule @p molecule and get the weight of it. 0208 * The calculated weight is stored in @p _result. 0209 * 0210 * @param _moleculeString 0211 * @param _resultMass 0212 * @param _resultMap 0213 * 0214 * @return whether the parsing was successful or not 0215 */ 0216 bool weight(const QString &_moleculeString, double *_resultMass, ElementCountMap *_resultMap); 0217 0218 QSet<QString> aliasList(); 0219 0220 private: 0221 // Helper functions 0222 bool parseSubmolecule(double *_resultMass, ElementCountMap *_resultMap); 0223 bool parseTerm(double *_resultMass, ElementCountMap *_resultMap); 0224 // This function expands the molecule string 0225 // eg expandFormula(EtOH) returns (C2H5)OH 0226 QString expandFormula(const QString &_shortMolecularMass); 0227 // This function expands a term 0228 // eg expandTerm(Et) returns (C2H5) 0229 QString expandTerm(const QString &_group); 0230 0231 QList<Element *> m_elementList; 0232 0233 static const int ELEMENT_TOKEN = 300; 0234 0235 Element *lookupElement(const QString &_name); 0236 0237 QMap<Element *, int> m_elementMap; 0238 0239 // Contains the list of aliases eg, { "Et - C2H5", "Me - CH3"} 0240 QSet<QString> *m_aliasList; 0241 // if this booloean is "true" the parser found an error 0242 bool m_error; 0243 0244 protected: 0245 /** 0246 * Extends the standard tokenizer in Parser::getNextToken(). 0247 */ 0248 int getNextToken() override; 0249 0250 private: 0251 Element *m_elementVal; // Valid if m_nextToken == ELEMENT_TOKEN 0252 }; 0253 0254 #endif // MOLECULEPARSER_H