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