1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
4
5#ifndef SYMBOLS_H
6#define SYMBOLS_H
7
8#include "token.h"
9#include <qdebug.h>
10#include <qhash.h>
11#include <qlist.h>
12#include <qstack.h>
13#include <qstring.h>
14#include <qset.h>
15
16QT_BEGIN_NAMESPACE
17
18//#define USE_LEXEM_STORE
19
20struct SubArray
21{
22 inline SubArray() = default;
23 inline SubArray(const QByteArray &a):array(a),from(0), len(a.size()){}
24 inline SubArray(const char *s):array(s),from(0) { len = array.size(); }
25 SubArray(const QByteArray &a, qsizetype from, qsizetype len)
26 : array(a), from(from), len(len)
27 {
28 }
29 QByteArray array;
30 qsizetype from = 0;
31 qsizetype len = -1;
32 inline bool operator==(const SubArray &other) const {
33 if (len != other.len)
34 return false;
35 const auto begin = array.cbegin() + from;
36 const auto end = begin + len;
37 const auto other_begin = other.array.cbegin() + other.from;
38 return std::equal(first1: begin, last1: end, first2: other_begin);
39 }
40};
41
42inline size_t qHash(const SubArray &key)
43{
44 return qHash(key: QLatin1StringView(key.array.constData() + key.from, key.len));
45}
46
47
48struct Symbol
49{
50
51#ifdef USE_LEXEM_STORE
52 typedef QHash<SubArray, QHashDummyValue> LexemStore;
53 static LexemStore lexemStore;
54
55 inline Symbol() : lineNum(-1),token(NOTOKEN){}
56 inline Symbol(int lineNum, Token token):
57 lineNum(lineNum), token(token){}
58 inline Symbol(int lineNum, Token token, const QByteArray &lexem):
59 lineNum(lineNum), token(token),lex(lexem){}
60 inline Symbol(int lineNum, Token token, const QByteArray &lexem, int from, int len):
61 lineNum(lineNum), token(token){
62 LexemStore::const_iterator it = lexemStore.constFind(SubArray(lexem, from, len));
63
64 if (it != lexemStore.constEnd()) {
65 lex = it.key().array;
66 } else {
67 lex = lexem.mid(from, len);
68 lexemStore.insert(lex, QHashDummyValue());
69 }
70 }
71 int lineNum;
72 Token token;
73 inline QByteArray unquotedLexem() const { return lex.mid(1, lex.length()-2); }
74 inline QByteArray lexem() const { return lex; }
75 inline operator QByteArray() const { return lex; }
76 QByteArray lex;
77
78#else
79
80 inline Symbol() = default;
81 inline Symbol(int lineNum, Token token) : lineNum(lineNum), token(token) { }
82 inline Symbol(int lineNum, Token token, const QByteArray &lexem)
83 : lineNum(lineNum), token(token), lex(lexem), len(lex.size())
84 {
85 }
86 Symbol(int lineNum, Token token, const QByteArray &lexem, qsizetype from, qsizetype len)
87 : lineNum(lineNum), token(token), lex(lexem), from(from), len(len)
88 {
89 }
90 int lineNum = -1;
91 Token token = NOTOKEN;
92 inline QByteArray lexem() const { return lex.mid(index: from, len); }
93 inline QByteArray unquotedLexem() const { return lex.mid(index: from+1, len: len-2); }
94 inline operator SubArray() const { return SubArray(lex, from, len); }
95 bool operator==(const Symbol& o) const
96 {
97 return SubArray(lex, from, len) == SubArray(o.lex, o.from, o.len);
98 }
99 QByteArray lex;
100 qsizetype from = 0;
101 qsizetype len = -1;
102
103#endif
104};
105Q_DECLARE_TYPEINFO(Symbol, Q_RELOCATABLE_TYPE);
106
107typedef QList<Symbol> Symbols;
108
109struct SafeSymbols {
110 Symbols symbols;
111 QByteArray expandedMacro;
112 QSet<QByteArray> excludedSymbols;
113 qsizetype index;
114};
115Q_DECLARE_TYPEINFO(SafeSymbols, Q_RELOCATABLE_TYPE);
116
117class SymbolStack : public QStack<SafeSymbols>
118{
119public:
120 inline bool hasNext() {
121 while (!isEmpty() && top().index >= top().symbols.size())
122 pop();
123 return !isEmpty();
124 }
125 inline Token next() {
126 while (!isEmpty() && top().index >= top().symbols.size())
127 pop();
128 if (isEmpty())
129 return NOTOKEN;
130 return top().symbols.at(i: top().index++).token;
131 }
132 bool test(Token);
133 inline const Symbol &symbol() const { return top().symbols.at(i: top().index-1); }
134 inline Token token() { return symbol().token; }
135 inline QByteArray lexem() const { return symbol().lexem(); }
136 inline QByteArray unquotedLexem() { return symbol().unquotedLexem(); }
137
138 bool dontReplaceSymbol(const QByteArray &name) const;
139 QSet<QByteArray> excludeSymbols() const;
140};
141
142inline bool SymbolStack::test(Token token)
143{
144 qsizetype stackPos = size() - 1;
145 while (stackPos >= 0 && at(i: stackPos).index >= at(i: stackPos).symbols.size())
146 --stackPos;
147 if (stackPos < 0)
148 return false;
149 if (at(i: stackPos).symbols.at(i: at(i: stackPos).index).token == token) {
150 next();
151 return true;
152 }
153 return false;
154}
155
156inline bool SymbolStack::dontReplaceSymbol(const QByteArray &name) const
157{
158 auto matchesName = [&name](const SafeSymbols &sf) {
159 return name == sf.expandedMacro || sf.excludedSymbols.contains(value: name);
160 };
161 return std::any_of(first: cbegin(), last: cend(), pred: matchesName);
162}
163
164inline QSet<QByteArray> SymbolStack::excludeSymbols() const
165{
166 QSet<QByteArray> set;
167 for (const SafeSymbols &sf : *this) {
168 set << sf.expandedMacro;
169 set += sf.excludedSymbols;
170 }
171 return set;
172}
173
174QT_END_NAMESPACE
175
176#endif // SYMBOLS_H
177

source code of qtbase/src/tools/moc/symbols.h