diff options
Diffstat (limited to 'microbe/parser.h')
-rw-r--r-- | microbe/parser.h | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/microbe/parser.h b/microbe/parser.h new file mode 100644 index 0000000..ece433d --- /dev/null +++ b/microbe/parser.h @@ -0,0 +1,293 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 by Daniel Clarke * + * [email protected] * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef PARSER_H +#define PARSER_H + +#include "expression.h" +#include "instruction.h" +#include "microbe.h" + +#include "qmap.h" +#include "qvaluelist.h" + +class PIC14; + +/** +@author Daniel Clarke +@author David Saxton +*/ +class Statement +{ + public: + /** + * Is the assembly output generated for this statement. + */ + InstructionList * code; + /** + * The original microbe source line. + */ + SourceLine content; + /** + * Returns the microbe code from content. + */ + QString text() const { return content.text(); } + /** + * If this Statement is for a for loop, then content will contain + * something like "for x = 1 to 10", and bracedCode will contain the + * source code within (but not including) the braces. + */ + SourceLineList bracedCode; + /** + * Just returns whether or not the braced code is empty. + */ + bool hasBracedCode() const { return !bracedCode.isEmpty(); } + /** + * This breaks up the line seperated by spaces,{,and =/ + */ + static QStringList tokenise(const QString &line); + /** + * @see tokenise(const QString &line) + */ + QStringList tokenise() const { return tokenise( content.text() ); } + /** + * @returns whether or not the content looks like a label (ends with a + * colon). + */ + bool isLabel() const { return content.text().right(1) == ":"; } +}; + +typedef QValueList<Statement> StatementList; + +/** +@author Daniel Clarke +@author David Saxton +*/ +class Field +{ + public: + enum Type + { + // String that doesn't change the program logic, but might or might + // not need to be there depending on the statement (e.g. "then" in + // the if-statement). + FixedString, + + // Label, Variable, Name are all treated similarly (only different + // error messages are given). + Label, // e.g. in "goto [Label]" + Variable, // e.g. in "increment [Variable]" + Name, // e.g. in "sevenseg [Name]" + + // List of strings which should be pin names. + PinList, + + // Braced code. + Code, + + Expression, + Newline, + None + }; + + /** + * Create a Field of type None. + */ + Field(); + /** + * Create a Field. + */ + Field( Type type, const QString & key = 0 ); + /** + * Create a Field (this constructor should only be used with + * FixedStrings. + */ + Field( Type type, const QString & key, const QString & string, bool compulsory = true); + + /** + * The type of field expected. + */ + Type type() const { return m_type; } + /** + * String data relevant to the field dependent on m_type. + */ + QString string() const { return m_string; } + /** + * The key in which the found token will be attached to + * in the output map. If it is an empty string, then the field will be + * processed but not put in the output, effectively ignoring it. + */ + QString key() const { return m_key; } + /** + * Only FixedStrings may be compulsory, that is the only type that can + * actually have its presence checked. + * This flag is set to indicate that no error should be rasied if the + * field is not present. Note that if a field is found missing, then + * the rest of the statement is ignored (regardless of whether the rest + * is marked compulsory or not.) + */ + bool compulsory() const { return m_compulsory; } + + private: + Type m_type; + QString m_string; + QString m_key; + bool m_compulsory; +}; + + +class OutputField +{ + public: + /** + * Constructs an empty output field. + */ + OutputField(); + /** + * Constructs an output field consisting of braced code. + */ + OutputField( const SourceLineList & bracedCode ); + /** + * Constructs an output field consisting of a single string. + */ + OutputField( const QString &string ); + + QString string() const { return m_string; } + SourceLineList bracedCode() const { return m_bracedCode; } + bool found() const { return m_found; } + + private: + QString m_string; + SourceLineList m_bracedCode; + /** + * This specifies if a non compulsory field was found or not. + */ + bool m_found; +}; + +typedef QValueList<Field> StatementDefinition; +typedef QMap<QString,StatementDefinition> DefinitionMap; +typedef QMap<QString,OutputField> OutputFieldMap; + + +/** +@author Daniel Clarke +@author David Saxton +*/ +class Parser +{ + public: + Parser( Microbe * mb ); + ~Parser(); + + /** + * Report a compile error to Microbe; the current source line will be + * sent. Context is extra information to be inserted into the error + * message, only applicable to some errors (such as a use of a reserved + * keyword). + */ + void mistake( Microbe::MistakeType type, const QString & context = 0 ); + /** + * Creates a new instance of the parser class with all state information + * (class members) copied from this instance of the class. Don't forget to + * delete it when you are done! + */ + Parser * createChildParser(); + /** + * Creates a child class and uses it to parse recursively. + */ + Code * parseWithChild( const SourceLineList & lines ); + /** + * This is the actual parsing function, make sure to use parseUsingChild + * instead (???) + */ + Code * parse( const SourceLineList & lines ); + /** + * Returns the lines between the braces, excluding the braces, e.g. + * defproc name + * { + * more code + * some more code + * } + * returns ("more code","some more code"). + * Note that Microbe has already put the braces on separate lines for us. + * @param it is the iterator at the position of the first brace, this + * function will return with it pointing at the matching closing brace. + * @param end is the iterator pointing to the end of the source line + * list, so that we don't search past it. + * @returns The braced code (excluding the braces). + */ + SourceLineList getBracedCode( SourceLineList::const_iterator * it, SourceLineList::const_iterator end ); + /** + * Returns expression type. + * 0 = directly usable number (literal). + * 1 = variable. + * 2 = expression that needs evaluating. + */ + ExprType getExpressionType( const QString & expression ); + /** + * Examines the text to see if it looks like a literal, i.e. of the form + * "321890","021348","0x3C","b'0100110'","0101001b","h'43A'", or "2Ah". + * Everything else is considered non-literal. + * @see literalToInt. + */ + static bool isLiteral( const QString &text ); + /** + * Tries to convert the given literal string into a integer. If it fails, + * i.e. it is not any recognised literal, then it returns -1 and sets *ok to + * false. Else, *ok is set to true and the literal value is returned. + * @see isLiteral + */ + static int literalToInt( const QString & literal, bool * ok = 0l ); + /** + * Does the specified operation on the given numbers and returns the result. + */ + static int doArithmetic( int lvalue, int rvalue, Expression::Operation op ); + /** + * @return whether it was an assignment (which might not have been in + * the proper form). + */ + bool processAssignment(const QString &line); + + void compileConditionalExpression( const QString & expression, Code * ifCode, Code * elseCode ) const; + QString processConstant(const QString &expression, bool * isConstant, bool suppressNumberTooBig = false) const; + + private: + /** + * This is called when the bulk of the actual parsing has been carried + * out and is ready to be turned into assembly code. + * @param name Name of the statement to be processed + * @param fieldMap A map of named fields as appropriate to the statement + */ + void processStatement( const QString & name, const OutputFieldMap & fieldMap ); + + DefinitionMap m_definitionMap; + PIC14 * m_pPic; + bool m_bPassedEnd; + Microbe * mb; + Code * m_code; + SourceLine m_currentSourceLine; + + private: // Disable copy constructor and operator= + Parser( const Parser & ); + Parser &operator=( const Parser & ); +}; + +#endif |