Create an expression parser for Go.

The Go interpreter doesn't JIT or use LLVM, so this also
moves all the JIT related code from UserExpression to a new class LLVMUserExpression.

Differential Revision: http://reviews.llvm.org/D13073

Fix merge

llvm-svn: 251820
diff --git a/lldb/source/Plugins/ExpressionParser/Go/GoLexer.h b/lldb/source/Plugins/ExpressionParser/Go/GoLexer.h
new file mode 100644
index 0000000..e8e1635
--- /dev/null
+++ b/lldb/source/Plugins/ExpressionParser/Go/GoLexer.h
@@ -0,0 +1,201 @@
+//===-- GoLexer.h -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoLexer_h
+#define liblldb_GoLexer_h
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace lldb_private
+{
+
+class GoLexer
+{
+  public:
+    explicit GoLexer(const char *src);
+
+    enum TokenType
+    {
+        TOK_EOF,
+        TOK_INVALID,
+        TOK_IDENTIFIER,
+        LIT_INTEGER,
+        LIT_FLOAT,
+        LIT_IMAGINARY,
+        LIT_RUNE,
+        LIT_STRING,
+        KEYWORD_BREAK,
+        KEYWORD_DEFAULT,
+        KEYWORD_FUNC,
+        KEYWORD_INTERFACE,
+        KEYWORD_SELECT,
+        KEYWORD_CASE,
+        KEYWORD_DEFER,
+        KEYWORD_GO,
+        KEYWORD_MAP,
+        KEYWORD_STRUCT,
+        KEYWORD_CHAN,
+        KEYWORD_ELSE,
+        KEYWORD_GOTO,
+        KEYWORD_PACKAGE,
+        KEYWORD_SWITCH,
+        KEYWORD_CONST,
+        KEYWORD_FALLTHROUGH,
+        KEYWORD_IF,
+        KEYWORD_RANGE,
+        KEYWORD_TYPE,
+        KEYWORD_CONTINUE,
+        KEYWORD_FOR,
+        KEYWORD_IMPORT,
+        KEYWORD_RETURN,
+        KEYWORD_VAR,
+        OP_PLUS,
+        OP_MINUS,
+        OP_STAR,
+        OP_SLASH,
+        OP_PERCENT,
+        OP_AMP,
+        OP_PIPE,
+        OP_CARET,
+        OP_LSHIFT,
+        OP_RSHIFT,
+        OP_AMP_CARET,
+        OP_PLUS_EQ,
+        OP_MINUS_EQ,
+        OP_STAR_EQ,
+        OP_SLASH_EQ,
+        OP_PERCENT_EQ,
+        OP_AMP_EQ,
+        OP_PIPE_EQ,
+        OP_CARET_EQ,
+        OP_LSHIFT_EQ,
+        OP_RSHIFT_EQ,
+        OP_AMP_CARET_EQ,
+        OP_AMP_AMP,
+        OP_PIPE_PIPE,
+        OP_LT_MINUS,
+        OP_PLUS_PLUS,
+        OP_MINUS_MINUS,
+        OP_EQ_EQ,
+        OP_LT,
+        OP_GT,
+        OP_EQ,
+        OP_BANG,
+        OP_BANG_EQ,
+        OP_LT_EQ,
+        OP_GT_EQ,
+        OP_COLON_EQ,
+        OP_DOTS,
+        OP_LPAREN,
+        OP_LBRACK,
+        OP_LBRACE,
+        OP_COMMA,
+        OP_DOT,
+        OP_RPAREN,
+        OP_RBRACK,
+        OP_RBRACE,
+        OP_SEMICOLON,
+        OP_COLON,
+    };
+
+    struct Token
+    {
+        explicit Token(TokenType t, llvm::StringRef text) : m_type(t), m_value(text) {}
+        TokenType m_type;
+        llvm::StringRef m_value;
+    };
+
+    const Token &Lex();
+
+    size_t
+    BytesRemaining() const
+    {
+        return m_end - m_src;
+    }
+    llvm::StringRef
+    GetString(int len) const
+    {
+        return llvm::StringRef(m_src, len);
+    }
+
+    static TokenType LookupKeyword(llvm::StringRef id);
+    static llvm::StringRef LookupToken(TokenType t);
+
+  private:
+    bool
+    IsDecimal(char c)
+    {
+        return c >= '0' && c <= '9';
+    }
+    bool
+    IsHexChar(char c)
+    {
+        if (c >= '0' && c <= '9')
+            return true;
+        if (c >= 'A' && c <= 'F')
+            return true;
+        if (c >= 'a' && c <= 'f')
+            return true;
+        return false;
+    }
+    bool
+    IsLetterOrDigit(char c)
+    {
+        if (c >= 'a' && c <= 'z')
+            return true;
+        if (c >= 'A' && c <= 'Z')
+            return true;
+        if (c == '_')
+            return true;
+        if (c >= '0' && c <= '9')
+            return true;
+        // Treat all non-ascii chars as letters for simplicity.
+        return 0 != (c & 0x80);
+    }
+    bool
+    IsWhitespace(char c)
+    {
+        switch (c)
+        {
+            case ' ':
+            case '\t':
+            case '\r':
+                return true;
+        }
+        return false;
+    }
+
+    bool SkipWhitespace();
+    bool SkipComment();
+
+    TokenType InternalLex(bool newline);
+
+    TokenType DoOperator();
+
+    TokenType DoIdent();
+
+    TokenType DoNumber();
+
+    TokenType DoRune();
+
+    TokenType DoString();
+
+    static llvm::StringMap<TokenType> *InitKeywords();
+
+    static llvm::StringMap<TokenType> *m_keywords;
+
+    const char *m_src;
+    const char *m_end;
+    Token m_last_token;
+};
+
+} // namespace lldb_private
+
+#endif