1 #include "parsercontext.h"
2 #include "parsererror.h"
3 #include "lexer.h"
4 #include <QDebug>
5
~ParserContext()6 ParserContext::~ParserContext()
7 {
8 cleanUp();
9 }
10
addQuery(SqliteQuery * query)11 void ParserContext::addQuery(SqliteQuery *query)
12 {
13 parsedQueries << SqliteQueryPtr(query);
14 }
15
error(TokenPtr token,const QString & text)16 void ParserContext::error(TokenPtr token, const QString &text)
17 {
18 if (token->start > -1 && token->end > -1)
19 errors << new ParserError(token, text);
20 else if (managedTokens.size() > 0)
21 errors << new ParserError(managedTokens.last()->start, managedTokens.last()->end + 1, text);
22 else
23 errors << new ParserError(text);
24
25 successful = false;
26 }
27
error(Token * token,const QString & text)28 void ParserContext::error(Token* token, const QString& text)
29 {
30 if (token->type != Token::INVALID)
31 error(getTokenPtr(token), text);
32 else if (managedTokens.size() > 0)
33 error(managedTokens.last(), text);
34 else
35 error(text);
36 }
37
error(const QString & text)38 void ParserContext::error(const QString &text)
39 {
40 errors << new ParserError(text);
41 successful = false;
42 }
43
minorErrorAfterLastToken(const QString & text)44 void ParserContext::minorErrorAfterLastToken(const QString &text)
45 {
46 if (ignoreMinorErrors)
47 return;
48
49 if (managedTokens.isEmpty())
50 {
51 qCritical() << "Tried to report minor error after last token, but there's no tokens!";
52 return;
53 }
54
55 error(managedTokens.last(), text);
56 }
57
minorErrorBeforeNextToken(const QString & text)58 void ParserContext::minorErrorBeforeNextToken(const QString &text)
59 {
60 if (ignoreMinorErrors)
61 return;
62
63 raiseErrorBeforeNextToken = true;
64 nextTokenError = text;
65 }
66
errorAfterLastToken(const QString & text)67 void ParserContext::errorAfterLastToken(const QString& text)
68 {
69 if (managedTokens.isEmpty())
70 {
71 qCritical() << "Tried to report error after last token, but there's no tokens!";
72 return;
73 }
74
75 error(managedTokens.last(), text);
76 }
77
errorBeforeNextToken(const QString & text)78 void ParserContext::errorBeforeNextToken(const QString& text)
79 {
80 raiseErrorBeforeNextToken = true;
81 nextTokenError = text;
82 }
83
errorAtToken(const QString & text,int pos)84 void ParserContext::errorAtToken(const QString& text, int pos)
85 {
86 if (managedTokens.isEmpty())
87 {
88 qCritical() << "Tried to report error at token" << pos << ", but there's no tokens!";
89 return;
90 }
91
92 int idx = managedTokens.size() - 1 + pos;
93 if (idx < 0 && idx >= managedTokens.size())
94 {
95 qCritical() << "Tried to report error at token" << pos << ", calculated idx was out of range:" << idx
96 << "(manages tokens size:" << managedTokens.size() << ").";
97 return;
98 }
99
100 error(managedTokens[idx], text);
101 }
102
flushErrors()103 void ParserContext::flushErrors()
104 {
105 if (raiseErrorBeforeNextToken && !ignoreMinorErrors)
106 {
107 if (managedTokens.size() > 0)
108 error(managedTokens.last(), QObject::tr("Incomplete query."));
109 else
110 error(QObject::tr("Incomplete query."));
111
112 nextTokenError = QString();
113 raiseErrorBeforeNextToken = false;
114 }
115 }
116
getTokenPtr(Token * token)117 TokenPtr ParserContext::getTokenPtr(Token* token)
118 {
119 if (tokenPtrMap.contains(token))
120 return tokenPtrMap[token];
121
122 TokenPtr tokenPtr = Lexer::getEveryTokenTypePtr(token);
123 if (!tokenPtr.isNull())
124 return tokenPtr;
125
126 qWarning() << "No TokenPtr for Token*. Token asked:" << token->toString();
127 return TokenPtr();
128 }
129
getTokenPtrList(const QList<Token * > & tokens)130 TokenList ParserContext::getTokenPtrList(const QList<Token*>& tokens)
131 {
132 TokenList resList;
133 for (Token* token : tokens)
134 resList << getTokenPtr(token);
135
136 return resList;
137 }
138
addManagedToken(TokenPtr token)139 void ParserContext::addManagedToken(TokenPtr token)
140 {
141 managedTokens << token;
142 tokenPtrMap[token.data()] = token;
143
144 if (raiseErrorBeforeNextToken)
145 {
146 error(token, nextTokenError);
147 nextTokenError = QString();
148 raiseErrorBeforeNextToken = false;
149 }
150 }
151
isSuccessful() const152 bool ParserContext::isSuccessful() const
153 {
154 return successful;
155 }
156
getQueries()157 const QList<SqliteQueryPtr>& ParserContext::getQueries()
158 {
159 return parsedQueries;
160 }
161
getErrors()162 const QList<ParserError *> &ParserContext::getErrors()
163 {
164 return errors;
165 }
166
handleNumberToken(const QString & tokenValue)167 QVariant *ParserContext::handleNumberToken(const QString &tokenValue)
168 {
169 recentNumberIsCandidateForMaxNegative = false;
170 if (tokenValue.startsWith("0x", Qt::CaseInsensitive))
171 {
172 bool ok;
173 qint64 i64 = tokenValue.toLongLong(&ok, 16);
174 if (!ok)
175 {
176 quint64 ui64 = tokenValue.toULongLong(&ok, 16);
177 i64 = static_cast<qint64>(ui64);
178 }
179 return new QVariant(i64);
180 }
181 else if (tokenValue == "9223372036854775808") // max negative longlong value, but without a sign
182 {
183 recentNumberIsCandidateForMaxNegative = true;
184 return new QVariant(static_cast<qint64>(0L));
185 }
186 else
187 {
188 return new QVariant(QVariant(tokenValue).toLongLong());
189 }
190 }
191
isCandidateForMaxNegativeNumber() const192 bool ParserContext::isCandidateForMaxNegativeNumber() const
193 {
194 return recentNumberIsCandidateForMaxNegative;
195 }
196
cleanUp()197 void ParserContext::cleanUp()
198 {
199 for (ParserError* err : errors)
200 delete err;
201
202 parsedQueries.clear();
203 errors.clear();
204 managedTokens.clear();
205 nextTokenError.clear();
206 tokenPtrMap.clear();
207 raiseErrorBeforeNextToken = false;
208 successful = true;
209 }
210
isManagedToken(Token * token)211 bool ParserContext::isManagedToken(Token* token)
212 {
213 return tokenPtrMap.contains(token);
214 }
215
getManagedTokens()216 TokenList ParserContext::getManagedTokens()
217 {
218 return managedTokens;
219 }
220