summaryrefslogtreecommitdiffstats
path: root/languages/cpp/debugger/mi/milexer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'languages/cpp/debugger/mi/milexer.cpp')
-rw-r--r--languages/cpp/debugger/mi/milexer.cpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/languages/cpp/debugger/mi/milexer.cpp b/languages/cpp/debugger/mi/milexer.cpp
new file mode 100644
index 00000000..ecf18373
--- /dev/null
+++ b/languages/cpp/debugger/mi/milexer.cpp
@@ -0,0 +1,290 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Roberto Raggi *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 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. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "milexer.h"
+#include "tokens.h"
+#include <cctype>
+#include <iostream>
+
+bool MILexer::s_initialized = false;
+scan_fun_ptr MILexer::s_scan_table[];
+
+
+MILexer::MILexer()
+{
+ if (!s_initialized)
+ setupScanTable();
+}
+
+MILexer::~MILexer()
+{
+}
+
+void MILexer::setupScanTable()
+{
+ s_initialized = true;
+
+ for (int i=0; i<128; ++i) {
+ switch (i) {
+ case '\n':
+ s_scan_table[i] = &MILexer::scanNewline;
+ break;
+
+ case '"':
+ s_scan_table[i] = &MILexer::scanStringLiteral;
+ break;
+
+ default:
+ if (isspace(i))
+ s_scan_table[i] = &MILexer::scanWhiteSpaces;
+ else if (isalpha(i) || i == '_')
+ s_scan_table[i] = &MILexer::scanIdentifier;
+ else if (isdigit(i))
+ s_scan_table[i] = &MILexer::scanNumberLiteral;
+ else
+ s_scan_table[i] = &MILexer::scanChar;
+ }
+ }
+
+ s_scan_table[128] = &MILexer::scanUnicodeChar;
+}
+
+/*
+
+ m_firstToken = m_tokens.data();
+ m_currentToken = 0;
+
+ m_firstToken = m_tokens.data();
+ m_currentToken = m_firstToken;
+ */
+
+TokenStream *MILexer::tokenize(const FileSymbol *fileSymbol)
+{
+ m_tokensCount = 0;
+ m_tokens.resize(64);
+
+ m_contents = fileSymbol->contents;
+ m_length = m_contents.length();
+ m_ptr = 0;
+
+ m_lines.resize(8);
+ m_line = 0;
+
+ m_lines[m_line++] = 0;
+
+ m_cursor = 0;
+
+ // tokenize
+ int pos, len;
+
+ for (;;) {
+ if (m_tokensCount == (int)m_tokens.size())
+ m_tokens.resize(m_tokensCount * 2);
+
+ Token &tk = m_tokens[m_tokensCount++];
+ tk.kind = nextToken(pos, len);
+ tk.position = pos;
+ tk.length = len;
+
+ if (tk.kind == 0)
+ break;
+ }
+
+ TokenStream *tokenStream = new TokenStream;
+ tokenStream->m_contents = m_contents;
+
+ tokenStream->m_lines = m_lines;
+ tokenStream->m_line = m_line;
+
+ tokenStream->m_tokens = m_tokens;
+ tokenStream->m_tokensCount = m_tokensCount;
+
+ tokenStream->m_firstToken = tokenStream->m_tokens.data();
+ tokenStream->m_currentToken = tokenStream->m_firstToken;;
+
+ tokenStream->m_cursor = m_cursor;
+
+ return tokenStream;
+}
+
+int MILexer::nextToken(int &pos, int &len)
+{
+ int start = 0;
+ int kind = 0;
+ unsigned char ch = 0;
+
+ while (m_ptr < m_length) {
+ start = m_ptr;
+
+ ch = (unsigned char)m_contents[m_ptr];
+ (this->*s_scan_table[ch < 128 ? ch : 128])(&kind);
+
+ switch (kind) {
+ case Token_whitespaces:
+ case '\n':
+ break;
+
+ default:
+ pos = start;
+ len = m_ptr - start;
+ return kind;
+ }
+
+ if (kind == 0)
+ break;
+ }
+
+ return 0;
+}
+
+void MILexer::scanChar(int *kind)
+{
+ *kind = m_contents[m_ptr++];
+}
+
+void MILexer::scanWhiteSpaces(int *kind)
+{
+ *kind = Token_whitespaces;
+
+ char ch;
+ while (m_ptr < m_length) {
+ ch = m_contents[m_ptr];
+ if (!(isspace(ch) && ch != '\n'))
+ break;
+
+ ++m_ptr;
+ }
+}
+
+void MILexer::scanNewline(int *kind)
+{
+ if (m_line == (int)m_lines.size())
+ m_lines.resize(m_lines.size() * 2);
+
+ if (m_lines.at(m_line) < m_ptr)
+ m_lines[m_line++] = m_ptr;
+
+ *kind = m_contents[m_ptr++];
+}
+
+void MILexer::scanUnicodeChar(int *kind)
+{
+ *kind = m_contents[m_ptr++];
+}
+
+void MILexer::scanStringLiteral(int *kind)
+{
+ ++m_ptr;
+ while (char c = m_contents[m_ptr]) {
+ switch (c) {
+ case '\n':
+ // ### error
+ *kind = Token_string_literal;
+ return;
+ case '\\':
+ {
+ char next = m_contents.at(m_ptr+1);
+ if (next == '"' || next == '\\')
+ m_ptr += 2;
+ else
+ ++m_ptr;
+ }
+ break;
+ case '"':
+ ++m_ptr;
+ *kind = Token_string_literal;
+ return;
+ default:
+ ++m_ptr;
+ break;
+ }
+ }
+
+ // ### error
+ *kind = Token_string_literal;
+}
+
+void MILexer::scanIdentifier(int *kind)
+{
+ char ch;
+ while (m_ptr < m_length) {
+ ch = m_contents[m_ptr];
+ if (!(isalnum(ch) || ch == '-' || ch == '_'))
+ break;
+
+ ++m_ptr;
+ }
+
+ *kind = Token_identifier;
+}
+
+void MILexer::scanNumberLiteral(int *kind)
+{
+ char ch;
+ while (m_ptr < m_length) {
+ ch = m_contents[m_ptr];
+ if (!(isalnum(ch) || ch == '.'))
+ break;
+
+ ++m_ptr;
+ }
+
+ // ### finish to implement me!!
+ *kind = Token_number_literal;
+}
+
+void TokenStream::positionAt(int position, int *line, int *column) const
+{
+ if (!(line && column && !m_lines.isEmpty()))
+ return;
+
+ int first = 0;
+ int len = m_line;
+ int half;
+ int middle;
+
+ while (len > 0) {
+ half = len >> 1;
+ middle = first;
+
+ middle += half;
+
+ if (m_lines[middle] < position) {
+ first = middle;
+ ++first;
+ len = len - half - 1;
+ }
+ else
+ len = half;
+ }
+
+ *line = QMAX(first - 1, 0);
+ *column = position - m_lines.at(*line);
+
+ Q_ASSERT( *column >= 0 );
+}
+
+QCString TokenStream::tokenText(int index) const
+{
+ Token *t = index < 0 ? m_currentToken : m_firstToken + index;
+ const char* data = m_contents;
+ return QCString(data + t->position, t->length+1);
+}
+