File indexing completed on 2024-04-14 05:36:26
0001 /*************************************************************************** 0002 * Copyright (C) 2004-2005 by Daniel Clarke * 0003 * daniel.jc@gmail.com * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 0021 #ifndef PARSER_H 0022 #define PARSER_H 0023 0024 #include "expression.h" 0025 #include "instruction.h" 0026 #include "microbe.h" 0027 0028 #include <QMap> 0029 #include <QList> 0030 0031 class PIC14; 0032 0033 /** 0034 @author Daniel Clarke 0035 @author David Saxton 0036 */ 0037 class Statement 0038 { 0039 public: 0040 Statement(); 0041 0042 /** 0043 * Is the assembly output generated for this statement. 0044 */ 0045 InstructionList * code; 0046 /** 0047 * The original microbe source line. 0048 */ 0049 SourceLineMicrobe content; 0050 /** 0051 * Returns the microbe code from content. 0052 */ 0053 QString text() const { return content.text(); } 0054 /** 0055 * If this Statement is for a for loop, then content will contain 0056 * something like "for x = 1 to 10", and bracedCode will contain the 0057 * source code within (but not including) the braces. 0058 */ 0059 SourceLineList bracedCode; 0060 /** 0061 * Just returns whether or not the braced code is empty. 0062 */ 0063 bool hasBracedCode() const { return !bracedCode.isEmpty(); } 0064 /** 0065 * This breaks up the line separated by spaces,{,and =/ 0066 */ 0067 static QStringList tokenise(const QString &line); 0068 /** 0069 * @see tokenise(const QString &line) 0070 */ 0071 QStringList tokenise() const { return tokenise( content.text() ); } 0072 /** 0073 * @returns whether or not the content looks like a label (ends with a 0074 * colon). 0075 */ 0076 bool isLabel() const { return content.text().right(1) == ":"; } 0077 }; 0078 0079 typedef QList<Statement> StatementList; 0080 0081 /** 0082 @author Daniel Clarke 0083 @author David Saxton 0084 */ 0085 class Field 0086 { 0087 public: 0088 enum Type 0089 { 0090 // String that doesn't change the program logic, but might or might 0091 // not need to be there depending on the statement (e.g. "then" in 0092 // the if-statement). 0093 FixedString, 0094 0095 // Label, Variable, Name are all treated similarly (only different 0096 // error messages are given). 0097 Label, // e.g. in "goto [Label]" 0098 Variable, // e.g. in "increment [Variable]" 0099 Name, // e.g. in "sevenseg [Name]" 0100 0101 // List of strings which should be pin names. 0102 PinList, 0103 0104 // Braced code. 0105 Code, 0106 0107 Expression, 0108 Newline, 0109 None 0110 }; 0111 0112 /** 0113 * Create a Field of type None. 0114 */ 0115 Field(); 0116 /** 0117 * Create a Field. 0118 */ 0119 Field( Type type, const QString & key = nullptr ); 0120 /** 0121 * Create a Field (this constructor should only be used with 0122 * FixedStrings. 0123 */ 0124 Field( Type type, const QString & key, const QString & string, bool compulsory = true); 0125 0126 /** 0127 * The type of field expected. 0128 */ 0129 Type type() const { return m_type; } 0130 /** 0131 * String data relevant to the field dependent on m_type. 0132 */ 0133 QString string() const { return m_string; } 0134 /** 0135 * The key in which the found token will be attached to 0136 * in the output map. If it is an empty string, then the field will be 0137 * processed but not put in the output, effectively ignoring it. 0138 */ 0139 QString key() const { return m_key; } 0140 /** 0141 * Only FixedStrings may be compulsory, that is the only type that can 0142 * actually have its presence checked. 0143 * This flag is set to indicate that no error should be rasied if the 0144 * field is not present. Note that if a field is found missing, then 0145 * the rest of the statement is ignored (regardless of whether the rest 0146 * is marked compulsory or not.) 0147 */ 0148 bool compulsory() const { return m_compulsory; } 0149 0150 private: 0151 Type m_type; 0152 QString m_string; 0153 QString m_key; 0154 bool m_compulsory; 0155 }; 0156 0157 0158 class OutputField 0159 { 0160 public: 0161 /** 0162 * Constructs an empty output field. 0163 */ 0164 OutputField(); 0165 /** 0166 * Constructs an output field consisting of braced code. 0167 */ 0168 OutputField( const SourceLineList & bracedCode ); 0169 /** 0170 * Constructs an output field consisting of a single string. 0171 */ 0172 OutputField( const QString &string ); 0173 0174 QString string() const { return m_string; } 0175 SourceLineList bracedCode() const { return m_bracedCode; } 0176 bool found() const { return m_found; } 0177 0178 private: 0179 QString m_string; 0180 SourceLineList m_bracedCode; 0181 /** 0182 * This specifies if a non compulsory field was found or not. 0183 */ 0184 bool m_found; 0185 }; 0186 0187 typedef QList<Field> StatementDefinition; 0188 typedef QMap<QString,StatementDefinition> DefinitionMap; 0189 typedef QMap<QString,OutputField> OutputFieldMap; 0190 0191 0192 /** 0193 @author Daniel Clarke 0194 @author David Saxton 0195 */ 0196 class Parser 0197 { 0198 public: 0199 Parser( MicrobeApp * mb ); 0200 ~Parser(); 0201 0202 /** 0203 * Report a compile error to MicrobeApp; the current source line will be 0204 * sent. Context is extra information to be inserted into the error 0205 * message, only applicable to some errors (such as a use of a reserved 0206 * keyword). 0207 */ 0208 void mistake( MicrobeApp::MistakeType type, const QString & context = nullptr ); 0209 /** 0210 * Creates a new instance of the parser class with all state information 0211 * (class members) copied from this instance of the class. Don't forget to 0212 * delete it when you are done! 0213 */ 0214 Parser * createChildParser(); 0215 /** 0216 * Creates a child class and uses it to parse recursively. 0217 */ 0218 Code * parseWithChild( const SourceLineList & lines ); 0219 /** 0220 * This is the actual parsing function, make sure to use parseUsingChild 0221 * instead (???) 0222 */ 0223 Code * parse( const SourceLineList & lines ); 0224 /** 0225 * Returns the lines between the braces, excluding the braces, e.g. 0226 * defproc name 0227 * { 0228 * more code 0229 * some more code 0230 * } 0231 * returns ("more code","some more code"). 0232 * Note that MicrobeApp has already put the braces on separate lines for us. 0233 * @param it is the iterator at the position of the first brace, this 0234 * function will return with it pointing at the matching closing brace. 0235 * @param end is the iterator pointing to the end of the source line 0236 * list, so that we don't search past it. 0237 * @returns The braced code (excluding the braces). 0238 */ 0239 SourceLineList getBracedCode( SourceLineList::const_iterator * it, SourceLineList::const_iterator end ); 0240 /** 0241 * Returns expression type. 0242 * 0 = directly usable number (literal). 0243 * 1 = variable. 0244 * 2 = expression that needs evaluating. 0245 */ 0246 ExprType getExpressionType( const QString & expression ); 0247 /** 0248 * Examines the text to see if it looks like a literal, i.e. of the form 0249 * "321890","021348","0x3C","b'0100110'","0101001b","h'43A'", or "2Ah". 0250 * Everything else is considered non-literal. 0251 * @see literalToInt. 0252 */ 0253 static bool isLiteral( const QString &text ); 0254 /** 0255 * Tries to convert the given literal string into a integer. If it fails, 0256 * i.e. it is not any recognised literal, then it returns -1 and sets *ok to 0257 * false. Else, *ok is set to true and the literal value is returned. 0258 * @see isLiteral 0259 */ 0260 static int literalToInt( const QString & literal, bool * ok = nullptr ); 0261 /** 0262 * Does the specified operation on the given numbers and returns the result. 0263 */ 0264 static int doArithmetic( int lvalue, int rvalue, Expression::Operation op ); 0265 /** 0266 * @return whether it was an assignment (which might not have been in 0267 * the proper form). 0268 */ 0269 bool processAssignment(const QString &line); 0270 0271 void compileConditionalExpression( const QString & expression, Code * ifCode, Code * elseCode ) const; 0272 QString processConstant(const QString &expression, bool * isConstant, bool suppressNumberTooBig = false) const; 0273 0274 private: 0275 /** 0276 * This is called when the bulk of the actual parsing has been carried 0277 * out and is ready to be turned into assembly code. 0278 * @param name Name of the statement to be processed 0279 * @param fieldMap A map of named fields as appropriate to the statement 0280 */ 0281 void processStatement( const QString & name, const OutputFieldMap & fieldMap ); 0282 0283 DefinitionMap m_definitionMap; 0284 PIC14 * m_pPic; 0285 bool m_bPassedEnd; 0286 MicrobeApp * mb; 0287 Code * m_code; 0288 SourceLineMicrobe m_currentSourceLine; 0289 0290 private: // Disable copy constructor and operator= 0291 Parser( const Parser & ); 0292 Parser &operator=( const Parser & ); 0293 }; 0294 0295 #endif