-
Notifications
You must be signed in to change notification settings - Fork 0
/
translator.h
269 lines (236 loc) · 7.63 KB
/
translator.h
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
// vim:ts=4:sw=4:
//
// Interactive BASIC Compiler Project
// File: translator.h - translator class definitions file
// Copyright (C) 2012 Thunder422
//
// 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 3 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.
//
// For a copy of the GNU General Public License,
// see <http://www.gnu.org/licenses/>.
//
//
// Change History:
//
// 2012-11-03 initial version (parts removed from ibcp.h)
#ifndef TRANSLATOR_H
#define TRANSLATOR_H
#include <QList>
#include <QStack>
#include "token.h"
class Table;
// command stack item flag values
// some flags are used for all commands and some are used only for
// specific commands, the values of command specific flags may be reused
// for different commands so each flag will be assigned a value
enum {
// FLAGS FOR ALL COMMANDS
None_CmdFlag = 0x00000000, // initial value of command flag
// FLAGS FOR PRINT COMMAND
PrintStay_CmdFlag = 0x00010000, // PRINT stay on line flag
PrintFunc_CmdFlag = 0x00020000, // print function flag
// FLAGS FOR ASSIGNMENT COMMANDS
AssignList_CmdFlag = 0x00010000, // currently an assign list
// FLAGS FOR INPUT COMMAND
InputBegin_CmdFlag = 0x00010000, // beginning processed
InputStay_CmdFlag = 0x00020000 // INPUT stay on line flag
};
// command item
struct CmdItem {
Token *token; // pointer to command token
int flag; // generic flag for command use
int index; // index into output list for command use
};
// structure for holding RPN output list information
class RpnItem {
Token *m_token; // pointer to token
int m_nOperands; // number of operands
RpnItem **m_operand; // array of operand pointers
public:
RpnItem(Token *token, int nOperands = 0, RpnItem **operand = NULL)
{
m_token = token;
m_nOperands = nOperands;
m_operand = operand;
}
~RpnItem()
{
delete m_token;
if (m_nOperands > 0)
{
delete[] m_operand;
}
}
// access functions
Token *token(void)
{
return m_token;
}
void setToken(Token *token)
{
m_token = token;
}
int nOperands(void)
{
return m_nOperands;
}
void setNOperands(int nOperands)
{
m_nOperands = nOperands;
}
RpnItem **operand(void)
{
return m_operand;
}
void setOperand(RpnItem **operand)
{
m_operand = operand;
}
RpnItem *operand(int index)
{
return m_operand[index];
}
void setOperand(int index, RpnItem *operand)
{
m_operand[index] = operand;
}
// function to set operands without allocating a new array
void set(int nOperands, RpnItem **operand)
{
m_nOperands = nOperands;
m_operand = operand;
}
};
class Translator {
struct HoldItem {
Token *token; // token pointer on hold stack
Token *first; // operator token's first operand pointer
};
struct DoneItem {
RpnItem *rpnItem; // pointer to RPN item
Token *first; // operator token's first operand pointer
Token *last; // operator token's last operand pointer
};
struct CountItem {
char nOperands; // number of operands seen
char nExpected; // number of arguments expected
Code code; // table index of internal function
};
enum State {
Initial_State, // initial state
BinOp_State, // expecting binary operator
Operand_State, // expecting unary operator or operand
OperandOrEnd_State, // expecting operand or end (2010-06-10)
EndExpr_State, // expecting end of expression (2011-03-05)
EndStmt_State, // expecting end of statement (2011-03-19)
sizeof_State
} m_state; // current state of translator
Table &m_table; // reference to the table instance
QList<RpnItem *> *m_output; // pointer to RPN list output
QStack<HoldItem> m_holdStack; // operator/function holding stack
QStack<DoneItem> m_doneStack; // items processed stack
Token *m_pendingParen; // closing parentheses token is pending
int m_lastPrecedence; // precedence of last op added during paren
QStack<CountItem> m_countStack; // number of operands counter stack
TokenMode m_mode; // current assignment mode
QStack<CmdItem> m_cmdStack; // stack of commands waiting processing
bool m_exprMode; // expression only mode active flag
Token *m_errorToken; // token when error occurred
QString m_errorMessage; // message of error that occurred
public:
Translator(Table &table): m_table(table), m_output(NULL),
m_pendingParen(NULL), m_errorToken(NULL) {}
~Translator(void)
{
if (m_errorToken != NULL)
{
delete m_errorToken;
}
}
bool setInput(const QString &input, bool exprMode = false);
QList<RpnItem *> *output(void) // only call when setInput() returns true
{
QList<RpnItem *> *list = m_output;
m_output = NULL;
return list;
}
Token *errorToken(void) // only call when setInput() returns false
{
return m_errorToken;
}
QString errorMessage(void) // only call when setInput() returns false
{
return m_errorMessage;
}
private:
enum Match {
No_Match,
Yes_Match,
Cvt_Match,
sizeof_Match
};
TokenStatus addToken(Token *&token);
TokenStatus processOperand(Token *&token);
TokenStatus endExpressionError(void);
bool processUnaryOperator(Token *&token, TokenStatus &status);
TokenStatus processBinaryOperator(Token *&token);
TokenStatus processOperator(Token *&token);
TokenStatus operatorError(void);
TokenStatus processFirstOperand(Token *&token);
TokenStatus processFinalOperand(Token *&token, Token *token2,
int operandIndex, int nOperands = 0);
TokenStatus findCode(Token *&token, int operandIndex,
Token **first = NULL, Token **last = NULL);
void doPendingParen(Token *token);
TokenStatus expressionEnd(void);
TokenStatus parenStatus(void);
TokenStatus getExprDataType(DataType &dataType);
void deleteOpenParen(Token *token);
void deleteCloseParen(Token *token);
TokenStatus callCommandHandler(Token *&token);
void cleanUp(void); // only call when addToken() returns error
// COMMAND SPECIFIC FUNCTIONS
TokenStatus addPrintCode(void);
TokenStatus checkAssignListToken(Token *&token);
TokenStatus setAssignCommand(Token *&token, Code assign_code);
// By DataType Access Functions
static TokenStatus expectedErrStatus(DataType dataType);
static TokenStatus actualErrStatus(DataType dataType);
static TokenStatus variableErrStatus(DataType dataType);
static DataType equivalentDataType(DataType dataType);
// set error token (deleting any previous error token first)
void setErrorToken(Token *errorToken)
{
if (m_errorToken != NULL)
{
delete m_errorToken;
}
m_errorToken = errorToken;
}
public:
// token handler friend function definitions section
friend TokenStatus Operator_Handler(Translator &t, Token *&token);
friend TokenStatus Equal_Handler(Translator &t, Token *&token);
friend TokenStatus Comma_Handler(Translator &t, Token *&token);
friend TokenStatus CloseParen_Handler(Translator &t, Token *&token);
friend TokenStatus EndOfLine_Handler(Translator &t, Token *&token);
friend TokenStatus SemiColon_Handler(Translator &t, Token *&token);
// command handler friend function definitions section
friend TokenStatus Assign_CmdHandler(Translator &t, CmdItem *cmd_item,
Token *token);
friend TokenStatus Print_CmdHandler(Translator &t, CmdItem *cmd_item,
Token *token);
friend TokenStatus Let_CmdHandler(Translator &t, CmdItem *cmd_item,
Token *token);
friend TokenStatus Input_CmdHandler(Translator &t, CmdItem *cmd_item,
Token *token);
};
#endif // TRANSLATOR_H