]> gitweb.ps.run Git - toc/blob - antlr4-cpp-runtime-4.9.2-source/runtime/src/Lexer.cpp
add antlr source code and ReadMe
[toc] / antlr4-cpp-runtime-4.9.2-source / runtime / src / Lexer.cpp
1 /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
2  * Use of this file is governed by the BSD 3-clause license that
3  * can be found in the LICENSE.txt file in the project root.
4  */
5
6 #include "atn/LexerATNSimulator.h"
7 #include "Exceptions.h"
8 #include "misc/Interval.h"
9 #include "CommonTokenFactory.h"
10 #include "LexerNoViableAltException.h"
11 #include "ANTLRErrorListener.h"
12 #include "support/CPPUtils.h"
13 #include "CommonToken.h"
14 #include "support/StringUtils.h"
15
16 #include "Lexer.h"
17
18 #define DEBUG_LEXER 0
19
20 using namespace antlrcpp;
21 using namespace antlr4;
22
23 Lexer::Lexer() : Recognizer() {
24   InitializeInstanceFields();
25   _input = nullptr;
26 }
27
28 Lexer::Lexer(CharStream *input) : Recognizer(), _input(input) {
29   InitializeInstanceFields();
30 }
31
32 void Lexer::reset() {
33   // wack Lexer state variables
34   _input->seek(0); // rewind the input
35
36   _syntaxErrors = 0;
37   token.reset();
38   type = Token::INVALID_TYPE;
39   channel = Token::DEFAULT_CHANNEL;
40   tokenStartCharIndex = INVALID_INDEX;
41   tokenStartCharPositionInLine = 0;
42   tokenStartLine = 0;
43   type = 0;
44   _text = "";
45
46   hitEOF = false;
47   mode = Lexer::DEFAULT_MODE;
48   modeStack.clear();
49
50   getInterpreter<atn::LexerATNSimulator>()->reset();
51 }
52
53 std::unique_ptr<Token> Lexer::nextToken() {
54   // Mark start location in char stream so unbuffered streams are
55   // guaranteed at least have text of current token
56   ssize_t tokenStartMarker = _input->mark();
57
58   auto onExit = finally([this, tokenStartMarker]{
59     // make sure we release marker after match or
60     // unbuffered char stream will keep buffering
61     _input->release(tokenStartMarker);
62   });
63
64   while (true) {
65   outerContinue:
66     if (hitEOF) {
67       emitEOF();
68       return std::move(token);
69     }
70
71     token.reset();
72     channel = Token::DEFAULT_CHANNEL;
73     tokenStartCharIndex = _input->index();
74     tokenStartCharPositionInLine = getInterpreter<atn::LexerATNSimulator>()->getCharPositionInLine();
75     tokenStartLine = getInterpreter<atn::LexerATNSimulator>()->getLine();
76     _text = "";
77     do {
78       type = Token::INVALID_TYPE;
79       size_t ttype;
80       try {
81         ttype = getInterpreter<atn::LexerATNSimulator>()->match(_input, mode);
82       } catch (LexerNoViableAltException &e) {
83         notifyListeners(e); // report error
84         recover(e);
85         ttype = SKIP;
86       }
87       if (_input->LA(1) == EOF) {
88         hitEOF = true;
89       }
90       if (type == Token::INVALID_TYPE) {
91         type = ttype;
92       }
93       if (type == SKIP) {
94         goto outerContinue;
95       }
96     } while (type == MORE);
97     if (token == nullptr) {
98       emit();
99     }
100     return std::move(token);
101   }
102 }
103
104 void Lexer::skip() {
105   type = SKIP;
106 }
107
108 void Lexer::more() {
109   type = MORE;
110 }
111
112 void Lexer::setMode(size_t m) {
113   mode = m;
114 }
115
116 void Lexer::pushMode(size_t m) {
117 #if DEBUG_LEXER == 1
118     std::cout << "pushMode " << m << std::endl;
119 #endif
120
121   modeStack.push_back(mode);
122   setMode(m);
123 }
124
125 size_t Lexer::popMode() {
126   if (modeStack.empty()) {
127     throw EmptyStackException();
128   }
129 #if DEBUG_LEXER == 1
130     std::cout << std::string("popMode back to ") << modeStack.back() << std::endl;
131 #endif
132
133   setMode(modeStack.back());
134   modeStack.pop_back();
135   return mode;
136 }
137
138
139 TokenFactory<CommonToken>* Lexer::getTokenFactory() {
140   return _factory;
141 }
142
143 void Lexer::setInputStream(IntStream *input) {
144   reset();
145   _input = dynamic_cast<CharStream*>(input);
146 }
147
148 std::string Lexer::getSourceName() {
149   return _input->getSourceName();
150 }
151
152 CharStream* Lexer::getInputStream() {
153   return _input;
154 }
155
156 void Lexer::emit(std::unique_ptr<Token> newToken) {
157   token = std::move(newToken);
158 }
159
160 Token* Lexer::emit() {
161   emit(_factory->create({ this, _input }, type, _text, channel,
162     tokenStartCharIndex, getCharIndex() - 1, tokenStartLine, tokenStartCharPositionInLine));
163   return token.get();
164 }
165
166 Token* Lexer::emitEOF() {
167   size_t cpos = getCharPositionInLine();
168   size_t line = getLine();
169   emit(_factory->create({ this, _input }, EOF, "", Token::DEFAULT_CHANNEL, _input->index(), _input->index() - 1, line, cpos));
170   return token.get();
171 }
172
173 size_t Lexer::getLine() const {
174   return getInterpreter<atn::LexerATNSimulator>()->getLine();
175 }
176
177 size_t Lexer::getCharPositionInLine() {
178   return getInterpreter<atn::LexerATNSimulator>()->getCharPositionInLine();
179 }
180
181 void Lexer::setLine(size_t line) {
182   getInterpreter<atn::LexerATNSimulator>()->setLine(line);
183 }
184
185 void Lexer::setCharPositionInLine(size_t charPositionInLine) {
186   getInterpreter<atn::LexerATNSimulator>()->setCharPositionInLine(charPositionInLine);
187 }
188
189 size_t Lexer::getCharIndex() {
190   return _input->index();
191 }
192
193 std::string Lexer::getText() {
194   if (!_text.empty()) {
195     return _text;
196   }
197   return getInterpreter<atn::LexerATNSimulator>()->getText(_input);
198 }
199
200 void Lexer::setText(const std::string &text) {
201   _text = text;
202 }
203
204 std::unique_ptr<Token> Lexer::getToken() {
205   return std::move(token);
206 }
207
208 void Lexer::setToken(std::unique_ptr<Token> newToken) {
209   token = std::move(newToken);
210 }
211
212 void Lexer::setType(size_t ttype) {
213   type = ttype;
214 }
215
216 size_t Lexer::getType() {
217   return type;
218 }
219
220 void Lexer::setChannel(size_t newChannel) {
221   channel = newChannel;
222 }
223
224 size_t Lexer::getChannel() {
225   return channel;
226 }
227
228 std::vector<std::unique_ptr<Token>> Lexer::getAllTokens() {
229   std::vector<std::unique_ptr<Token>> tokens;
230   std::unique_ptr<Token> t = nextToken();
231   while (t->getType() != EOF) {
232     tokens.push_back(std::move(t));
233     t = nextToken();
234   }
235   return tokens;
236 }
237
238 void Lexer::recover(const LexerNoViableAltException &/*e*/) {
239   if (_input->LA(1) != EOF) {
240     // skip a char and try again
241     getInterpreter<atn::LexerATNSimulator>()->consume(_input);
242   }
243 }
244
245 void Lexer::notifyListeners(const LexerNoViableAltException & /*e*/) {
246   ++_syntaxErrors;
247   std::string text = _input->getText(misc::Interval(tokenStartCharIndex, _input->index()));
248   std::string msg = std::string("token recognition error at: '") + getErrorDisplay(text) + std::string("'");
249
250   ProxyErrorListener &listener = getErrorListenerDispatch();
251   listener.syntaxError(this, nullptr, tokenStartLine, tokenStartCharPositionInLine, msg, std::current_exception());
252 }
253
254 std::string Lexer::getErrorDisplay(const std::string &s) {
255   std::stringstream ss;
256   for (auto c : s) {
257     switch (c) {
258     case '\n':
259       ss << "\\n";
260       break;
261     case '\t':
262       ss << "\\t";
263       break;
264     case '\r':
265       ss << "\\r";
266       break;
267     default:
268       ss << c;
269       break;
270     }
271   }
272   return ss.str();
273 }
274
275 void Lexer::recover(RecognitionException * /*re*/) {
276   // TODO: Do we lose character or line position information?
277   _input->consume();
278 }
279
280 size_t Lexer::getNumberOfSyntaxErrors() {
281   return _syntaxErrors;
282 }
283
284 void Lexer::InitializeInstanceFields() {
285   _syntaxErrors = 0;
286   token = nullptr;
287   _factory = CommonTokenFactory::DEFAULT.get();
288   tokenStartCharIndex = INVALID_INDEX;
289   tokenStartLine = 0;
290   tokenStartCharPositionInLine = 0;
291   hitEOF = false;
292   channel = 0;
293   type = 0;
294   mode = Lexer::DEFAULT_MODE;
295 }