summaryrefslogtreecommitdiffstats
path: root/microbe/parser.h
blob: 7a51e4137e1ee081edd7ce77c6526875a13d8790 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
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 "tqmap.h"
#include "tqvaluelist.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.
		 */
		TQString 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 TQStringList tokenise(const TQString &line);
		/**
		 * @see tokenise(const TQString &line)
		 */
		TQStringList 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 TQValueList<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 TQString & key = 0 );
		/**
		 * Create a Field (this constructor should only be used with
		 * FixedStrings.
		 */
		Field( Type type, const TQString & key, const TQString & 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.
		 */
		TQString 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.
		 */
		TQString 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;
		TQString m_string;
		TQString 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 TQString &string );
	
		TQString string() const { return m_string; }
		SourceLineList bracedCode() const { return m_bracedCode; }
		bool found() const { return m_found; }
	
	private:
		TQString m_string;
		SourceLineList m_bracedCode;
		/**
		 * This specifies if a non compulsory field was found or not.
		 */
		bool m_found;
};

typedef TQValueList<Field> StatementDefinition;
typedef TQMap<TQString,StatementDefinition> DefinitionMap;
typedef TQMap<TQString,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 TQString & 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 TQString & 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 TQString &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 TQString & 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 TQString &line);
	
		void compileConditionalExpression( const TQString & expression, Code * ifCode, Code * elseCode ) const;
		TQString processConstant(const TQString &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 TQString & 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