summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp')
-rw-r--r--lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp1717
1 files changed, 781 insertions, 936 deletions
diff --git a/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp b/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp
index 0f136f7e61d..327b9df43db 100644
--- a/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp
@@ -11,1025 +11,870 @@
#include "GoParser.h"
+#include "Plugins/ExpressionParser/Go/GoAST.h"
#include "lldb/Core/Error.h"
#include "llvm/ADT/SmallString.h"
-#include "Plugins/ExpressionParser/Go/GoAST.h"
using namespace lldb_private;
using namespace lldb;
-namespace
-{
-llvm::StringRef
-DescribeToken(GoLexer::TokenType t)
-{
- switch (t)
- {
- case GoLexer::TOK_EOF:
- return "<eof>";
- case GoLexer::TOK_IDENTIFIER:
- return "identifier";
- case GoLexer::LIT_FLOAT:
- return "float";
- case GoLexer::LIT_IMAGINARY:
- return "imaginary";
- case GoLexer::LIT_INTEGER:
- return "integer";
- case GoLexer::LIT_RUNE:
- return "rune";
- case GoLexer::LIT_STRING:
- return "string";
- default:
- return GoLexer::LookupToken(t);
- }
+namespace {
+llvm::StringRef DescribeToken(GoLexer::TokenType t) {
+ switch (t) {
+ case GoLexer::TOK_EOF:
+ return "<eof>";
+ case GoLexer::TOK_IDENTIFIER:
+ return "identifier";
+ case GoLexer::LIT_FLOAT:
+ return "float";
+ case GoLexer::LIT_IMAGINARY:
+ return "imaginary";
+ case GoLexer::LIT_INTEGER:
+ return "integer";
+ case GoLexer::LIT_RUNE:
+ return "rune";
+ case GoLexer::LIT_STRING:
+ return "string";
+ default:
+ return GoLexer::LookupToken(t);
+ }
}
} // namespace
-class GoParser::Rule
-{
- public:
- Rule(llvm::StringRef name, GoParser *p) : m_name(name), m_parser(p), m_pos(p->m_pos) {}
-
- std::nullptr_t
- error()
- {
- if (!m_parser->m_failed)
- {
- // Set m_error in case this is the top level.
- if (m_parser->m_last_tok == GoLexer::TOK_INVALID)
- m_parser->m_error = m_parser->m_last;
- else
- m_parser->m_error = DescribeToken(m_parser->m_last_tok);
- // And set m_last in case it isn't.
- m_parser->m_last = m_name;
- m_parser->m_last_tok = GoLexer::TOK_INVALID;
- m_parser->m_pos = m_pos;
- }
- return nullptr;
+class GoParser::Rule {
+public:
+ Rule(llvm::StringRef name, GoParser *p)
+ : m_name(name), m_parser(p), m_pos(p->m_pos) {}
+
+ std::nullptr_t error() {
+ if (!m_parser->m_failed) {
+ // Set m_error in case this is the top level.
+ if (m_parser->m_last_tok == GoLexer::TOK_INVALID)
+ m_parser->m_error = m_parser->m_last;
+ else
+ m_parser->m_error = DescribeToken(m_parser->m_last_tok);
+ // And set m_last in case it isn't.
+ m_parser->m_last = m_name;
+ m_parser->m_last_tok = GoLexer::TOK_INVALID;
+ m_parser->m_pos = m_pos;
}
+ return nullptr;
+ }
- private:
- llvm::StringRef m_name;
- GoParser *m_parser;
- size_t m_pos;
+private:
+ llvm::StringRef m_name;
+ GoParser *m_parser;
+ size_t m_pos;
};
-GoParser::GoParser(const char *src) : m_lexer(src), m_pos(0), m_failed(false)
-{
-}
-
-GoASTStmt *
-GoParser::Statement()
-{
- Rule r("Statement", this);
- GoLexer::TokenType t = peek();
- GoASTStmt *ret = nullptr;
- switch (t)
- {
- case GoLexer::TOK_EOF:
- case GoLexer::OP_SEMICOLON:
- case GoLexer::OP_RPAREN:
- case GoLexer::OP_RBRACE:
- case GoLexer::TOK_INVALID:
- return EmptyStmt();
- case GoLexer::OP_LBRACE:
- return Block();
-
- /* TODO:
- case GoLexer::KEYWORD_GO:
- return GoStmt();
- case GoLexer::KEYWORD_RETURN:
- return ReturnStmt();
- case GoLexer::KEYWORD_BREAK:
- case GoLexer::KEYWORD_CONTINUE:
- case GoLexer::KEYWORD_GOTO:
- case GoLexer::KEYWORD_FALLTHROUGH:
- return BranchStmt();
- case GoLexer::KEYWORD_IF:
- return IfStmt();
- case GoLexer::KEYWORD_SWITCH:
- return SwitchStmt();
- case GoLexer::KEYWORD_SELECT:
- return SelectStmt();
- case GoLexer::KEYWORD_FOR:
- return ForStmt();
- case GoLexer::KEYWORD_DEFER:
- return DeferStmt();
- case GoLexer::KEYWORD_CONST:
- case GoLexer::KEYWORD_TYPE:
- case GoLexer::KEYWORD_VAR:
- return DeclStmt();
- case GoLexer::TOK_IDENTIFIER:
- if ((ret = LabeledStmt()) ||
- (ret = ShortVarDecl()))
- {
- return ret;
- }
+GoParser::GoParser(const char *src) : m_lexer(src), m_pos(0), m_failed(false) {}
+
+GoASTStmt *GoParser::Statement() {
+ Rule r("Statement", this);
+ GoLexer::TokenType t = peek();
+ GoASTStmt *ret = nullptr;
+ switch (t) {
+ case GoLexer::TOK_EOF:
+ case GoLexer::OP_SEMICOLON:
+ case GoLexer::OP_RPAREN:
+ case GoLexer::OP_RBRACE:
+ case GoLexer::TOK_INVALID:
+ return EmptyStmt();
+ case GoLexer::OP_LBRACE:
+ return Block();
+
+ /* TODO:
+case GoLexer::KEYWORD_GO:
+ return GoStmt();
+case GoLexer::KEYWORD_RETURN:
+ return ReturnStmt();
+case GoLexer::KEYWORD_BREAK:
+case GoLexer::KEYWORD_CONTINUE:
+case GoLexer::KEYWORD_GOTO:
+case GoLexer::KEYWORD_FALLTHROUGH:
+ return BranchStmt();
+case GoLexer::KEYWORD_IF:
+ return IfStmt();
+case GoLexer::KEYWORD_SWITCH:
+ return SwitchStmt();
+case GoLexer::KEYWORD_SELECT:
+ return SelectStmt();
+case GoLexer::KEYWORD_FOR:
+ return ForStmt();
+case GoLexer::KEYWORD_DEFER:
+ return DeferStmt();
+case GoLexer::KEYWORD_CONST:
+case GoLexer::KEYWORD_TYPE:
+case GoLexer::KEYWORD_VAR:
+ return DeclStmt();
+case GoLexer::TOK_IDENTIFIER:
+ if ((ret = LabeledStmt()) ||
+ (ret = ShortVarDecl()))
+ {
+ return ret;
+ }
*/
- default:
- break;
- }
- GoASTExpr *expr = Expression();
- if (expr == nullptr)
- return r.error();
- if (/*(ret = SendStmt(expr)) ||*/
- (ret = IncDecStmt(expr)) || (ret = Assignment(expr)) || (ret = ExpressionStmt(expr)))
- {
- return ret;
- }
- delete expr;
+ default:
+ break;
+ }
+ GoASTExpr *expr = Expression();
+ if (expr == nullptr)
return r.error();
-}
-
-GoASTStmt *
-GoParser::ExpressionStmt(GoASTExpr *e)
-{
- if (Semicolon())
- return new GoASTExprStmt(e);
- return nullptr;
-}
-
-GoASTStmt *
-GoParser::IncDecStmt(GoASTExpr *e)
-{
- Rule r("IncDecStmt", this);
- if (match(GoLexer::OP_PLUS_PLUS))
- return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_PLUS_PLUS) : r.error();
- if (match(GoLexer::OP_MINUS_MINUS))
- return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_MINUS_MINUS) : r.error();
+ if (/*(ret = SendStmt(expr)) ||*/
+ (ret = IncDecStmt(expr)) || (ret = Assignment(expr)) ||
+ (ret = ExpressionStmt(expr))) {
+ return ret;
+ }
+ delete expr;
+ return r.error();
+}
+
+GoASTStmt *GoParser::ExpressionStmt(GoASTExpr *e) {
+ if (Semicolon())
+ return new GoASTExprStmt(e);
+ return nullptr;
+}
+
+GoASTStmt *GoParser::IncDecStmt(GoASTExpr *e) {
+ Rule r("IncDecStmt", this);
+ if (match(GoLexer::OP_PLUS_PLUS))
+ return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_PLUS_PLUS)
+ : r.error();
+ if (match(GoLexer::OP_MINUS_MINUS))
+ return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_MINUS_MINUS)
+ : r.error();
+ return nullptr;
+}
+
+GoASTStmt *GoParser::Assignment(lldb_private::GoASTExpr *e) {
+ Rule r("Assignment", this);
+ std::vector<std::unique_ptr<GoASTExpr>> lhs;
+ for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList())
+ lhs.push_back(std::unique_ptr<GoASTExpr>(l));
+ switch (peek()) {
+ case GoLexer::OP_EQ:
+ case GoLexer::OP_PLUS_EQ:
+ case GoLexer::OP_MINUS_EQ:
+ case GoLexer::OP_PIPE_EQ:
+ case GoLexer::OP_CARET_EQ:
+ case GoLexer::OP_STAR_EQ:
+ case GoLexer::OP_SLASH_EQ:
+ case GoLexer::OP_PERCENT_EQ:
+ case GoLexer::OP_LSHIFT_EQ:
+ case GoLexer::OP_RSHIFT_EQ:
+ case GoLexer::OP_AMP_EQ:
+ case GoLexer::OP_AMP_CARET_EQ:
+ break;
+ default:
+ return r.error();
+ }
+ // We don't want to own e until we know this is an assignment.
+ std::unique_ptr<GoASTAssignStmt> stmt(new GoASTAssignStmt(false));
+ stmt->AddLhs(e);
+ for (auto &l : lhs)
+ stmt->AddLhs(l.release());
+ for (GoASTExpr *r = Expression(); r; r = MoreExpressionList())
+ stmt->AddRhs(r);
+ if (!Semicolon() || stmt->NumRhs() == 0)
+ return new GoASTBadStmt;
+ return stmt.release();
+}
+
+GoASTStmt *GoParser::EmptyStmt() {
+ if (match(GoLexer::TOK_EOF))
return nullptr;
-}
-
-GoASTStmt *
-GoParser::Assignment(lldb_private::GoASTExpr *e)
-{
- Rule r("Assignment", this);
- std::vector<std::unique_ptr<GoASTExpr>> lhs;
- for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList())
- lhs.push_back(std::unique_ptr<GoASTExpr>(l));
- switch (peek())
- {
- case GoLexer::OP_EQ:
- case GoLexer::OP_PLUS_EQ:
- case GoLexer::OP_MINUS_EQ:
- case GoLexer::OP_PIPE_EQ:
- case GoLexer::OP_CARET_EQ:
- case GoLexer::OP_STAR_EQ:
- case GoLexer::OP_SLASH_EQ:
- case GoLexer::OP_PERCENT_EQ:
- case GoLexer::OP_LSHIFT_EQ:
- case GoLexer::OP_RSHIFT_EQ:
- case GoLexer::OP_AMP_EQ:
- case GoLexer::OP_AMP_CARET_EQ:
- break;
- default:
- return r.error();
+ if (Semicolon())
+ return new GoASTEmptyStmt;
+ return nullptr;
+}
+
+GoASTStmt *GoParser::GoStmt() {
+ if (match(GoLexer::KEYWORD_GO)) {
+ if (GoASTCallExpr *e =
+ llvm::dyn_cast_or_null<GoASTCallExpr>(Expression())) {
+ return FinishStmt(new GoASTGoStmt(e));
+ }
+ m_last = "call expression";
+ m_failed = true;
+ return new GoASTBadStmt();
+ }
+ return nullptr;
+}
+
+GoASTStmt *GoParser::ReturnStmt() {
+ if (match(GoLexer::KEYWORD_RETURN)) {
+ std::unique_ptr<GoASTReturnStmt> r(new GoASTReturnStmt());
+ for (GoASTExpr *e = Expression(); e; e = MoreExpressionList())
+ r->AddResults(e);
+ return FinishStmt(r.release());
+ }
+ return nullptr;
+}
+
+GoASTStmt *GoParser::BranchStmt() {
+ GoLexer::Token *tok;
+ if ((tok = match(GoLexer::KEYWORD_BREAK)) ||
+ (tok = match(GoLexer::KEYWORD_CONTINUE)) ||
+ (tok = match(GoLexer::KEYWORD_GOTO))) {
+ auto *e = Identifier();
+ if (tok->m_type == GoLexer::KEYWORD_GOTO && !e)
+ return syntaxerror();
+ return FinishStmt(new GoASTBranchStmt(e, tok->m_type));
+ }
+ if ((tok = match(GoLexer::KEYWORD_FALLTHROUGH)))
+ return FinishStmt(new GoASTBranchStmt(nullptr, tok->m_type));
+
+ return nullptr;
+}
+
+GoASTIdent *GoParser::Identifier() {
+ if (auto *tok = match(GoLexer::TOK_IDENTIFIER))
+ return new GoASTIdent(*tok);
+ return nullptr;
+}
+
+GoASTExpr *GoParser::MoreExpressionList() {
+ if (match(GoLexer::OP_COMMA)) {
+ auto *e = Expression();
+ if (!e)
+ return syntaxerror();
+ return e;
+ }
+ return nullptr;
+}
+
+GoASTIdent *GoParser::MoreIdentifierList() {
+ if (match(GoLexer::OP_COMMA)) {
+ auto *i = Identifier();
+ if (!i)
+ return syntaxerror();
+ return i;
+ }
+ return nullptr;
+}
+
+GoASTExpr *GoParser::Expression() {
+ Rule r("Expression", this);
+ if (GoASTExpr *ret = OrExpr())
+ return ret;
+ return r.error();
+}
+
+GoASTExpr *GoParser::UnaryExpr() {
+ switch (peek()) {
+ case GoLexer::OP_PLUS:
+ case GoLexer::OP_MINUS:
+ case GoLexer::OP_BANG:
+ case GoLexer::OP_CARET:
+ case GoLexer::OP_STAR:
+ case GoLexer::OP_AMP:
+ case GoLexer::OP_LT_MINUS: {
+ const GoLexer::Token t = next();
+ if (GoASTExpr *e = UnaryExpr()) {
+ if (t.m_type == GoLexer::OP_STAR)
+ return new GoASTStarExpr(e);
+ else
+ return new GoASTUnaryExpr(t.m_type, e);
}
- // We don't want to own e until we know this is an assignment.
- std::unique_ptr<GoASTAssignStmt> stmt(new GoASTAssignStmt(false));
- stmt->AddLhs(e);
- for (auto &l : lhs)
- stmt->AddLhs(l.release());
- for (GoASTExpr *r = Expression(); r; r = MoreExpressionList())
- stmt->AddRhs(r);
- if (!Semicolon() || stmt->NumRhs() == 0)
- return new GoASTBadStmt;
- return stmt.release();
-}
-
-GoASTStmt *
-GoParser::EmptyStmt()
-{
- if (match(GoLexer::TOK_EOF))
- return nullptr;
- if (Semicolon())
- return new GoASTEmptyStmt;
- return nullptr;
-}
-
-GoASTStmt *
-GoParser::GoStmt()
-{
- if (match(GoLexer::KEYWORD_GO))
- {
- if (GoASTCallExpr *e = llvm::dyn_cast_or_null<GoASTCallExpr>(Expression()))
- {
- return FinishStmt(new GoASTGoStmt(e));
- }
- m_last = "call expression";
- m_failed = true;
- return new GoASTBadStmt();
+ return syntaxerror();
+ }
+ default:
+ return PrimaryExpr();
+ }
+}
+
+GoASTExpr *GoParser::OrExpr() {
+ std::unique_ptr<GoASTExpr> l(AndExpr());
+ if (l) {
+ while (match(GoLexer::OP_PIPE_PIPE)) {
+ GoASTExpr *r = AndExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_PIPE_PIPE));
+ else
+ return syntaxerror();
}
- return nullptr;
-}
-
-GoASTStmt *
-GoParser::ReturnStmt()
-{
- if (match(GoLexer::KEYWORD_RETURN))
- {
- std::unique_ptr<GoASTReturnStmt> r(new GoASTReturnStmt());
- for (GoASTExpr *e = Expression(); e; e = MoreExpressionList())
- r->AddResults(e);
- return FinishStmt(r.release());
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *GoParser::AndExpr() {
+ std::unique_ptr<GoASTExpr> l(RelExpr());
+ if (l) {
+ while (match(GoLexer::OP_AMP_AMP)) {
+ GoASTExpr *r = RelExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_AMP_AMP));
+ else
+ return syntaxerror();
}
- return nullptr;
-}
-
-GoASTStmt *
-GoParser::BranchStmt()
-{
- GoLexer::Token *tok;
- if ((tok = match(GoLexer::KEYWORD_BREAK)) || (tok = match(GoLexer::KEYWORD_CONTINUE)) ||
- (tok = match(GoLexer::KEYWORD_GOTO)))
- {
- auto *e = Identifier();
- if (tok->m_type == GoLexer::KEYWORD_GOTO && !e)
- return syntaxerror();
- return FinishStmt(new GoASTBranchStmt(e, tok->m_type));
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *GoParser::RelExpr() {
+ std::unique_ptr<GoASTExpr> l(AddExpr());
+ if (l) {
+ for (GoLexer::Token *t;
+ (t = match(GoLexer::OP_EQ_EQ)) || (t = match(GoLexer::OP_BANG_EQ)) ||
+ (t = match(GoLexer::OP_LT)) || (t = match(GoLexer::OP_LT_EQ)) ||
+ (t = match(GoLexer::OP_GT)) || (t = match(GoLexer::OP_GT_EQ));) {
+ GoLexer::TokenType op = t->m_type;
+ GoASTExpr *r = AddExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, op));
+ else
+ return syntaxerror();
}
- if ((tok = match(GoLexer::KEYWORD_FALLTHROUGH)))
- return FinishStmt(new GoASTBranchStmt(nullptr, tok->m_type));
-
- return nullptr;
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *GoParser::AddExpr() {
+ std::unique_ptr<GoASTExpr> l(MulExpr());
+ if (l) {
+ for (GoLexer::Token *t;
+ (t = match(GoLexer::OP_PLUS)) || (t = match(GoLexer::OP_MINUS)) ||
+ (t = match(GoLexer::OP_PIPE)) || (t = match(GoLexer::OP_CARET));) {
+ GoLexer::TokenType op = t->m_type;
+ GoASTExpr *r = MulExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, op));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *GoParser::MulExpr() {
+ std::unique_ptr<GoASTExpr> l(UnaryExpr());
+ if (l) {
+ for (GoLexer::Token *t;
+ (t = match(GoLexer::OP_STAR)) || (t = match(GoLexer::OP_SLASH)) ||
+ (t = match(GoLexer::OP_PERCENT)) || (t = match(GoLexer::OP_LSHIFT)) ||
+ (t = match(GoLexer::OP_RSHIFT)) || (t = match(GoLexer::OP_AMP)) ||
+ (t = match(GoLexer::OP_AMP_CARET));) {
+ GoLexer::TokenType op = t->m_type;
+ GoASTExpr *r = UnaryExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, op));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
}
-GoASTIdent *
-GoParser::Identifier()
-{
- if (auto *tok = match(GoLexer::TOK_IDENTIFIER))
- return new GoASTIdent(*tok);
+GoASTExpr *GoParser::PrimaryExpr() {
+ GoASTExpr *l;
+ GoASTExpr *r;
+ (l = Conversion()) || (l = Operand());
+ if (!l)
return nullptr;
-}
-
-GoASTExpr *
-GoParser::MoreExpressionList()
-{
- if (match(GoLexer::OP_COMMA))
- {
- auto *e = Expression();
- if (!e)
- return syntaxerror();
- return e;
- }
+ while ((r = Selector(l)) || (r = IndexOrSlice(l)) || (r = TypeAssertion(l)) ||
+ (r = Arguments(l))) {
+ l = r;
+ }
+ return l;
+}
+
+GoASTExpr *GoParser::Operand() {
+ GoLexer::Token *lit;
+ if ((lit = match(GoLexer::LIT_INTEGER)) ||
+ (lit = match(GoLexer::LIT_FLOAT)) ||
+ (lit = match(GoLexer::LIT_IMAGINARY)) ||
+ (lit = match(GoLexer::LIT_RUNE)) || (lit = match(GoLexer::LIT_STRING)))
+ return new GoASTBasicLit(*lit);
+ if (match(GoLexer::OP_LPAREN)) {
+ GoASTExpr *e;
+ if (!((e = Expression()) && match(GoLexer::OP_RPAREN)))
+ return syntaxerror();
+ return e;
+ }
+ // MethodExpr should be handled by Selector
+ if (GoASTExpr *e = CompositeLit())
+ return e;
+ if (GoASTExpr *n = Name())
+ return n;
+ return FunctionLit();
+}
+
+GoASTExpr *GoParser::FunctionLit() {
+ if (!match(GoLexer::KEYWORD_FUNC))
return nullptr;
+ auto *sig = Signature();
+ if (!sig)
+ return syntaxerror();
+ auto *body = Block();
+ if (!body) {
+ delete sig;
+ return syntaxerror();
+ }
+ return new GoASTFuncLit(sig, body);
}
-GoASTIdent *
-GoParser::MoreIdentifierList()
-{
- if (match(GoLexer::OP_COMMA))
- {
- auto *i = Identifier();
- if (!i)
- return syntaxerror();
- return i;
- }
+GoASTBlockStmt *GoParser::Block() {
+ if (!match(GoLexer::OP_LBRACE))
return nullptr;
+ std::unique_ptr<GoASTBlockStmt> block(new GoASTBlockStmt);
+ for (auto *s = Statement(); s; s = Statement())
+ block->AddList(s);
+ if (!match(GoLexer::OP_RBRACE))
+ return syntaxerror();
+ return block.release();
}
-GoASTExpr *
-GoParser::Expression()
-{
- Rule r("Expression", this);
- if (GoASTExpr *ret = OrExpr())
- return ret;
+GoASTExpr *GoParser::CompositeLit() {
+ Rule r("CompositeLit", this);
+ GoASTExpr *type;
+ (type = StructType()) || (type = ArrayOrSliceType(true)) ||
+ (type = MapType()) || (type = Name());
+ if (!type)
return r.error();
+ GoASTCompositeLit *lit = LiteralValue();
+ if (!lit)
+ return r.error();
+ lit->SetType(type);
+ return lit;
}
-GoASTExpr *
-GoParser::UnaryExpr()
-{
- switch (peek())
- {
- case GoLexer::OP_PLUS:
- case GoLexer::OP_MINUS:
- case GoLexer::OP_BANG:
- case GoLexer::OP_CARET:
- case GoLexer::OP_STAR:
- case GoLexer::OP_AMP:
- case GoLexer::OP_LT_MINUS:
- {
- const GoLexer::Token t = next();
- if (GoASTExpr *e = UnaryExpr())
- {
- if (t.m_type == GoLexer::OP_STAR)
- return new GoASTStarExpr(e);
- else
- return new GoASTUnaryExpr(t.m_type, e);
- }
- return syntaxerror();
- }
- default:
- return PrimaryExpr();
- }
-}
-
-GoASTExpr *
-GoParser::OrExpr()
-{
- std::unique_ptr<GoASTExpr> l(AndExpr());
- if (l)
- {
- while (match(GoLexer::OP_PIPE_PIPE))
- {
- GoASTExpr *r = AndExpr();
- if (r)
- l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_PIPE_PIPE));
- else
- return syntaxerror();
- }
- return l.release();
- }
+GoASTCompositeLit *GoParser::LiteralValue() {
+ if (!match(GoLexer::OP_LBRACE))
return nullptr;
-}
-
-GoASTExpr *
-GoParser::AndExpr()
-{
- std::unique_ptr<GoASTExpr> l(RelExpr());
- if (l)
- {
- while (match(GoLexer::OP_AMP_AMP))
- {
- GoASTExpr *r = RelExpr();
- if (r)
- l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_AMP_AMP));
- else
- return syntaxerror();
- }
- return l.release();
- }
+ std::unique_ptr<GoASTCompositeLit> lit(new GoASTCompositeLit);
+ for (GoASTExpr *e = Element(); e; e = Element()) {
+ lit->AddElts(e);
+ if (!match(GoLexer::OP_COMMA))
+ break;
+ }
+ if (!mustMatch(GoLexer::OP_RBRACE))
return nullptr;
+ return lit.release();
}
-GoASTExpr *
-GoParser::RelExpr()
-{
- std::unique_ptr<GoASTExpr> l(AddExpr());
- if (l)
- {
- for (GoLexer::Token *t; (t = match(GoLexer::OP_EQ_EQ)) || (t = match(GoLexer::OP_BANG_EQ)) ||
- (t = match(GoLexer::OP_LT)) || (t = match(GoLexer::OP_LT_EQ)) ||
- (t = match(GoLexer::OP_GT)) || (t = match(GoLexer::OP_GT_EQ));)
- {
- GoLexer::TokenType op = t->m_type;
- GoASTExpr *r = AddExpr();
- if (r)
- l.reset(new GoASTBinaryExpr(l.release(), r, op));
- else
- return syntaxerror();
- }
- return l.release();
- }
+GoASTExpr *GoParser::Element() {
+ GoASTExpr *key;
+ if (!((key = Expression()) || (key = LiteralValue())))
return nullptr;
-}
-
-GoASTExpr *
-GoParser::AddExpr()
-{
- std::unique_ptr<GoASTExpr> l(MulExpr());
- if (l)
- {
- for (GoLexer::Token *t; (t = match(GoLexer::OP_PLUS)) || (t = match(GoLexer::OP_MINUS)) ||
- (t = match(GoLexer::OP_PIPE)) || (t = match(GoLexer::OP_CARET));)
- {
- GoLexer::TokenType op = t->m_type;
- GoASTExpr *r = MulExpr();
- if (r)
- l.reset(new GoASTBinaryExpr(l.release(), r, op));
- else
- return syntaxerror();
- }
- return l.release();
- }
- return nullptr;
-}
-
-GoASTExpr *
-GoParser::MulExpr()
-{
- std::unique_ptr<GoASTExpr> l(UnaryExpr());
- if (l)
- {
- for (GoLexer::Token *t; (t = match(GoLexer::OP_STAR)) || (t = match(GoLexer::OP_SLASH)) ||
- (t = match(GoLexer::OP_PERCENT)) || (t = match(GoLexer::OP_LSHIFT)) ||
- (t = match(GoLexer::OP_RSHIFT)) || (t = match(GoLexer::OP_AMP)) ||
- (t = match(GoLexer::OP_AMP_CARET));)
- {
- GoLexer::TokenType op = t->m_type;
- GoASTExpr *r = UnaryExpr();
- if (r)
- l.reset(new GoASTBinaryExpr(l.release(), r, op));
- else
- return syntaxerror();
- }
- return l.release();
- }
- return nullptr;
-}
-
-GoASTExpr *
-GoParser::PrimaryExpr()
-{
- GoASTExpr *l;
- GoASTExpr *r;
- (l = Conversion()) || (l = Operand());
- if (!l)
+ if (!match(GoLexer::OP_COLON))
+ return key;
+ GoASTExpr *value;
+ if ((value = Expression()) || (value = LiteralValue()))
+ return new GoASTKeyValueExpr(key, value);
+ delete key;
+ return syntaxerror();
+}
+
+GoASTExpr *GoParser::Selector(GoASTExpr *e) {
+ Rule r("Selector", this);
+ if (match(GoLexer::OP_DOT)) {
+ if (auto *name = Identifier())
+ return new GoASTSelectorExpr(e, name);
+ }
+ return r.error();
+}
+
+GoASTExpr *GoParser::IndexOrSlice(GoASTExpr *e) {
+ Rule r("IndexOrSlice", this);
+ if (match(GoLexer::OP_LBRACK)) {
+ std::unique_ptr<GoASTExpr> i1(Expression()), i2, i3;
+ bool slice = false;
+ if (match(GoLexer::OP_COLON)) {
+ slice = true;
+ i2.reset(Expression());
+ if (i2 && match(GoLexer::OP_COLON)) {
+ i3.reset(Expression());
+ if (!i3)
+ return syntaxerror();
+ }
+ }
+ if (!(slice || i1))
+ return syntaxerror();
+ if (!mustMatch(GoLexer::OP_RBRACK))
+ return nullptr;
+ if (slice) {
+ bool slice3 = i3.get();
+ return new GoASTSliceExpr(e, i1.release(), i2.release(), i3.release(),
+ slice3);
+ }
+ return new GoASTIndexExpr(e, i1.release());
+ }
+ return r.error();
+}
+
+GoASTExpr *GoParser::TypeAssertion(GoASTExpr *e) {
+ Rule r("TypeAssertion", this);
+ if (match(GoLexer::OP_DOT) && match(GoLexer::OP_LPAREN)) {
+ if (auto *t = Type()) {
+ if (!mustMatch(GoLexer::OP_RPAREN))
return nullptr;
- while ((r = Selector(l)) || (r = IndexOrSlice(l)) || (r = TypeAssertion(l)) || (r = Arguments(l)))
- {
- l = r;
+ return new GoASTTypeAssertExpr(e, t);
}
- return l;
+ return syntaxerror();
+ }
+ return r.error();
}
-GoASTExpr *
-GoParser::Operand()
-{
- GoLexer::Token *lit;
- if ((lit = match(GoLexer::LIT_INTEGER)) || (lit = match(GoLexer::LIT_FLOAT)) ||
- (lit = match(GoLexer::LIT_IMAGINARY)) || (lit = match(GoLexer::LIT_RUNE)) || (lit = match(GoLexer::LIT_STRING)))
- return new GoASTBasicLit(*lit);
- if (match(GoLexer::OP_LPAREN))
- {
- GoASTExpr *e;
- if (!((e = Expression()) && match(GoLexer::OP_RPAREN)))
- return syntaxerror();
- return e;
+GoASTExpr *GoParser::Arguments(GoASTExpr *e) {
+ if (match(GoLexer::OP_LPAREN)) {
+ std::unique_ptr<GoASTCallExpr> call(new GoASTCallExpr(false));
+ GoASTExpr *arg;
+ // ( ExpressionList | Type [ "," ExpressionList ] )
+ for ((arg = Expression()) || (arg = Type()); arg;
+ arg = MoreExpressionList()) {
+ call->AddArgs(arg);
}
- // MethodExpr should be handled by Selector
- if (GoASTExpr *e = CompositeLit())
- return e;
- if (GoASTExpr *n = Name())
- return n;
- return FunctionLit();
-}
+ if (match(GoLexer::OP_DOTS))
+ call->SetEllipsis(true);
-GoASTExpr *
-GoParser::FunctionLit()
-{
- if (!match(GoLexer::KEYWORD_FUNC))
- return nullptr;
- auto *sig = Signature();
- if (!sig)
- return syntaxerror();
- auto *body = Block();
- if (!body)
- {
- delete sig;
- return syntaxerror();
- }
- return new GoASTFuncLit(sig, body);
-}
+ // Eat trailing comma
+ match(GoLexer::OP_COMMA);
-GoASTBlockStmt *
-GoParser::Block()
-{
- if (!match(GoLexer::OP_LBRACE))
- return nullptr;
- std::unique_ptr<GoASTBlockStmt> block(new GoASTBlockStmt);
- for (auto *s = Statement(); s; s = Statement())
- block->AddList(s);
- if (!match(GoLexer::OP_RBRACE))
+ if (!mustMatch(GoLexer::OP_RPAREN))
+ return nullptr;
+ call->SetFun(e);
+ return call.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *GoParser::Conversion() {
+ Rule r("Conversion", this);
+ if (GoASTExpr *t = Type2()) {
+ if (match(GoLexer::OP_LPAREN)) {
+ GoASTExpr *v = Expression();
+ if (!v)
return syntaxerror();
- return block.release();
-}
-
-GoASTExpr *
-GoParser::CompositeLit()
-{
- Rule r("CompositeLit", this);
- GoASTExpr *type;
- (type = StructType()) || (type = ArrayOrSliceType(true)) || (type = MapType()) || (type = Name());
- if (!type)
+ match(GoLexer::OP_COMMA);
+ if (!mustMatch(GoLexer::OP_RPAREN))
return r.error();
- GoASTCompositeLit *lit = LiteralValue();
- if (!lit)
- return r.error();
- lit->SetType(type);
- return lit;
+ GoASTCallExpr *call = new GoASTCallExpr(false);
+ call->SetFun(t);
+ call->AddArgs(v);
+ return call;
+ }
+ }
+ return r.error();
+}
+
+GoASTExpr *GoParser::Type2() {
+ switch (peek()) {
+ case GoLexer::OP_LBRACK:
+ return ArrayOrSliceType(false);
+ case GoLexer::KEYWORD_STRUCT:
+ return StructType();
+ case GoLexer::KEYWORD_FUNC:
+ return FunctionType();
+ case GoLexer::KEYWORD_INTERFACE:
+ return InterfaceType();
+ case GoLexer::KEYWORD_MAP:
+ return MapType();
+ case GoLexer::KEYWORD_CHAN:
+ return ChanType2();
+ default:
+ return nullptr;
+ }
}
-GoASTCompositeLit *
-GoParser::LiteralValue()
-{
- if (!match(GoLexer::OP_LBRACE))
- return nullptr;
- std::unique_ptr<GoASTCompositeLit> lit(new GoASTCompositeLit);
- for (GoASTExpr *e = Element(); e; e = Element())
- {
- lit->AddElts(e);
- if (!match(GoLexer::OP_COMMA))
- break;
+GoASTExpr *GoParser::ArrayOrSliceType(bool allowEllipsis) {
+ Rule r("ArrayType", this);
+ if (match(GoLexer::OP_LBRACK)) {
+ std::unique_ptr<GoASTExpr> len;
+ if (allowEllipsis && match(GoLexer::OP_DOTS)) {
+ len.reset(new GoASTEllipsis(nullptr));
+ } else {
+ len.reset(Expression());
}
- if (!mustMatch(GoLexer::OP_RBRACE))
- return nullptr;
- return lit.release();
-}
-GoASTExpr *
-GoParser::Element()
-{
- GoASTExpr *key;
- if (!((key = Expression()) || (key = LiteralValue())))
- return nullptr;
- if (!match(GoLexer::OP_COLON))
- return key;
- GoASTExpr *value;
- if ((value = Expression()) || (value = LiteralValue()))
- return new GoASTKeyValueExpr(key, value);
- delete key;
- return syntaxerror();
+ if (!match(GoLexer::OP_RBRACK))
+ return r.error();
+ GoASTExpr *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTArrayType(len.release(), elem);
+ }
+ return r.error();
}
-GoASTExpr *
-GoParser::Selector(GoASTExpr *e)
-{
- Rule r("Selector", this);
- if (match(GoLexer::OP_DOT))
- {
- if (auto *name = Identifier())
- return new GoASTSelectorExpr(e, name);
- }
- return r.error();
+GoASTExpr *GoParser::StructType() {
+ if (!(match(GoLexer::KEYWORD_STRUCT) && mustMatch(GoLexer::OP_LBRACE)))
+ return nullptr;
+ std::unique_ptr<GoASTFieldList> fields(new GoASTFieldList);
+ while (auto *field = FieldDecl())
+ fields->AddList(field);
+ if (!mustMatch(GoLexer::OP_RBRACE))
+ return nullptr;
+ return new GoASTStructType(fields.release());
}
-GoASTExpr *
-GoParser::IndexOrSlice(GoASTExpr *e)
-{
- Rule r("IndexOrSlice", this);
- if (match(GoLexer::OP_LBRACK))
- {
- std::unique_ptr<GoASTExpr> i1(Expression()), i2, i3;
- bool slice = false;
- if (match(GoLexer::OP_COLON))
- {
- slice = true;
- i2.reset(Expression());
- if (i2 && match(GoLexer::OP_COLON))
- {
- i3.reset(Expression());
- if (!i3)
- return syntaxerror();
- }
- }
- if (!(slice || i1))
- return syntaxerror();
- if (!mustMatch(GoLexer::OP_RBRACK))
- return nullptr;
- if (slice)
- {
- bool slice3 = i3.get();
- return new GoASTSliceExpr(e, i1.release(), i2.release(), i3.release(), slice3);
- }
- return new GoASTIndexExpr(e, i1.release());
- }
- return r.error();
-}
+GoASTField *GoParser::FieldDecl() {
+ std::unique_ptr<GoASTField> f(new GoASTField);
+ GoASTExpr *t = FieldNamesAndType(f.get());
+ if (!t)
+ t = AnonymousFieldType();
+ if (!t)
+ return nullptr;
-GoASTExpr *
-GoParser::TypeAssertion(GoASTExpr *e)
-{
- Rule r("TypeAssertion", this);
- if (match(GoLexer::OP_DOT) && match(GoLexer::OP_LPAREN))
- {
- if (auto *t = Type())
- {
- if (!mustMatch(GoLexer::OP_RPAREN))
- return nullptr;
- return new GoASTTypeAssertExpr(e, t);
- }
- return syntaxerror();
- }
- return r.error();
+ if (auto *tok = match(GoLexer::LIT_STRING))
+ f->SetTag(new GoASTBasicLit(*tok));
+ if (!Semicolon())
+ return syntaxerror();
+ return f.release();
}
-GoASTExpr *
-GoParser::Arguments(GoASTExpr *e)
-{
- if (match(GoLexer::OP_LPAREN))
- {
- std::unique_ptr<GoASTCallExpr> call(new GoASTCallExpr(false));
- GoASTExpr *arg;
- // ( ExpressionList | Type [ "," ExpressionList ] )
- for ((arg = Expression()) || (arg = Type()); arg; arg = MoreExpressionList())
- {
- call->AddArgs(arg);
- }
- if (match(GoLexer::OP_DOTS))
- call->SetEllipsis(true);
-
- // Eat trailing comma
- match(GoLexer::OP_COMMA);
-
- if (!mustMatch(GoLexer::OP_RPAREN))
- return nullptr;
- call->SetFun(e);
- return call.release();
- }
+GoASTExpr *GoParser::FieldNamesAndType(GoASTField *field) {
+ Rule r("FieldNames", this);
+ for (auto *id = Identifier(); id; id = MoreIdentifierList())
+ field->AddNames(id);
+ if (m_failed)
return nullptr;
+ GoASTExpr *t = Type();
+ if (t)
+ return t;
+ return r.error();
}
-GoASTExpr *
-GoParser::Conversion()
-{
- Rule r("Conversion", this);
- if (GoASTExpr *t = Type2())
- {
- if (match(GoLexer::OP_LPAREN))
- {
- GoASTExpr *v = Expression();
- if (!v)
- return syntaxerror();
- match(GoLexer::OP_COMMA);
- if (!mustMatch(GoLexer::OP_RPAREN))
- return r.error();
- GoASTCallExpr *call = new GoASTCallExpr(false);
- call->SetFun(t);
- call->AddArgs(v);
- return call;
- }
- }
- return r.error();
+GoASTExpr *GoParser::AnonymousFieldType() {
+ bool pointer = match(GoLexer::OP_STAR);
+ GoASTExpr *t = Type();
+ if (!t)
+ return nullptr;
+ if (pointer)
+ return new GoASTStarExpr(t);
+ return t;
}
-GoASTExpr *
-GoParser::Type2()
-{
- switch (peek())
- {
- case GoLexer::OP_LBRACK:
- return ArrayOrSliceType(false);
- case GoLexer::KEYWORD_STRUCT:
- return StructType();
- case GoLexer::KEYWORD_FUNC:
- return FunctionType();
- case GoLexer::KEYWORD_INTERFACE:
- return InterfaceType();
- case GoLexer::KEYWORD_MAP:
- return MapType();
- case GoLexer::KEYWORD_CHAN:
- return ChanType2();
- default:
- return nullptr;
- }
+GoASTExpr *GoParser::FunctionType() {
+ if (!match(GoLexer::KEYWORD_FUNC))
+ return nullptr;
+ return Signature();
}
-GoASTExpr *
-GoParser::ArrayOrSliceType(bool allowEllipsis)
-{
- Rule r("ArrayType", this);
- if (match(GoLexer::OP_LBRACK))
- {
- std::unique_ptr<GoASTExpr> len;
- if (allowEllipsis && match(GoLexer::OP_DOTS))
- {
- len.reset(new GoASTEllipsis(nullptr));
- }
- else
- {
- len.reset(Expression());
- }
-
- if (!match(GoLexer::OP_RBRACK))
- return r.error();
- GoASTExpr *elem = Type();
- if (!elem)
- return syntaxerror();
- return new GoASTArrayType(len.release(), elem);
+GoASTFuncType *GoParser::Signature() {
+ auto *params = Params();
+ if (!params)
+ return syntaxerror();
+ auto *result = Params();
+ if (!result) {
+ if (auto *t = Type()) {
+ result = new GoASTFieldList;
+ auto *f = new GoASTField;
+ f->SetType(t);
+ result->AddList(f);
}
- return r.error();
-}
-
-GoASTExpr *
-GoParser::StructType()
-{
- if (!(match(GoLexer::KEYWORD_STRUCT) && mustMatch(GoLexer::OP_LBRACE)))
- return nullptr;
- std::unique_ptr<GoASTFieldList> fields(new GoASTFieldList);
- while (auto *field = FieldDecl())
- fields->AddList(field);
- if (!mustMatch(GoLexer::OP_RBRACE))
- return nullptr;
- return new GoASTStructType(fields.release());
+ }
+ return new GoASTFuncType(params, result);
}
-GoASTField *
-GoParser::FieldDecl()
-{
- std::unique_ptr<GoASTField> f(new GoASTField);
- GoASTExpr *t = FieldNamesAndType(f.get());
- if (!t)
- t = AnonymousFieldType();
- if (!t)
- return nullptr;
-
- if (auto *tok = match(GoLexer::LIT_STRING))
- f->SetTag(new GoASTBasicLit(*tok));
- if (!Semicolon())
- return syntaxerror();
- return f.release();
-}
-
-GoASTExpr *
-GoParser::FieldNamesAndType(GoASTField *field)
-{
- Rule r("FieldNames", this);
- for (auto *id = Identifier(); id; id = MoreIdentifierList())
- field->AddNames(id);
- if (m_failed)
- return nullptr;
- GoASTExpr *t = Type();
- if (t)
- return t;
- return r.error();
-}
-
-GoASTExpr *
-GoParser::AnonymousFieldType()
-{
- bool pointer = match(GoLexer::OP_STAR);
- GoASTExpr *t = Type();
- if (!t)
- return nullptr;
- if (pointer)
- return new GoASTStarExpr(t);
+GoASTFieldList *GoParser::Params() {
+ if (!match(GoLexer::OP_LPAREN))
+ return nullptr;
+ std::unique_ptr<GoASTFieldList> l(new GoASTFieldList);
+ while (GoASTField *p = ParamDecl()) {
+ l->AddList(p);
+ if (!match(GoLexer::OP_COMMA))
+ break;
+ }
+ if (!mustMatch(GoLexer::OP_RPAREN))
+ return nullptr;
+ return l.release();
+}
+
+GoASTField *GoParser::ParamDecl() {
+ std::unique_ptr<GoASTField> field(new GoASTField);
+ GoASTIdent *id = Identifier();
+ if (id) {
+ // Try `IdentifierList [ "..." ] Type`.
+ // If that fails, backtrack and try `[ "..." ] Type`.
+ Rule r("NamedParam", this);
+ for (; id; id = MoreIdentifierList())
+ field->AddNames(id);
+ GoASTExpr *t = ParamType();
+ if (t) {
+ field->SetType(t);
+ return field.release();
+ }
+ field.reset(new GoASTField);
+ r.error();
+ }
+ GoASTExpr *t = ParamType();
+ if (t) {
+ field->SetType(t);
+ return field.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *GoParser::ParamType() {
+ bool dots = match(GoLexer::OP_DOTS);
+ GoASTExpr *t = Type();
+ if (!dots)
return t;
+ if (!t)
+ return syntaxerror();
+ return new GoASTEllipsis(t);
}
-GoASTExpr *
-GoParser::FunctionType()
-{
- if (!match(GoLexer::KEYWORD_FUNC))
- return nullptr;
- return Signature();
-}
-
-GoASTFuncType *
-GoParser::Signature()
-{
- auto *params = Params();
- if (!params)
- return syntaxerror();
- auto *result = Params();
- if (!result)
- {
- if (auto *t = Type())
- {
- result = new GoASTFieldList;
- auto *f = new GoASTField;
- f->SetType(t);
- result->AddList(f);
- }
- }
- return new GoASTFuncType(params, result);
-}
-
-GoASTFieldList *
-GoParser::Params()
-{
- if (!match(GoLexer::OP_LPAREN))
- return nullptr;
- std::unique_ptr<GoASTFieldList> l(new GoASTFieldList);
- while (GoASTField *p = ParamDecl())
- {
- l->AddList(p);
- if (!match(GoLexer::OP_COMMA))
- break;
+GoASTExpr *GoParser::InterfaceType() {
+ if (!match(GoLexer::KEYWORD_INTERFACE) || !mustMatch(GoLexer::OP_LBRACE))
+ return nullptr;
+ std::unique_ptr<GoASTFieldList> methods(new GoASTFieldList);
+ while (true) {
+ Rule r("MethodSpec", this);
+ // ( identifier Signature | TypeName ) ;
+ std::unique_ptr<GoASTIdent> id(Identifier());
+ if (!id)
+ break;
+ GoASTExpr *type = Signature();
+ if (!type) {
+ r.error();
+ id.reset();
+ type = Name();
}
- if (!mustMatch(GoLexer::OP_RPAREN))
- return nullptr;
- return l.release();
-}
-
-GoASTField *
-GoParser::ParamDecl()
-{
- std::unique_ptr<GoASTField> field(new GoASTField);
- GoASTIdent *id = Identifier();
+ if (!Semicolon())
+ return syntaxerror();
+ auto *f = new GoASTField;
if (id)
- {
- // Try `IdentifierList [ "..." ] Type`.
- // If that fails, backtrack and try `[ "..." ] Type`.
- Rule r("NamedParam", this);
- for (; id; id = MoreIdentifierList())
- field->AddNames(id);
- GoASTExpr *t = ParamType();
- if (t)
- {
- field->SetType(t);
- return field.release();
- }
- field.reset(new GoASTField);
- r.error();
- }
- GoASTExpr *t = ParamType();
- if (t)
- {
- field->SetType(t);
- return field.release();
- }
+ f->AddNames(id.release());
+ f->SetType(type);
+ methods->AddList(f);
+ }
+ if (!mustMatch(GoLexer::OP_RBRACE))
return nullptr;
+ return new GoASTInterfaceType(methods.release());
}
-GoASTExpr *
-GoParser::ParamType()
-{
- bool dots = match(GoLexer::OP_DOTS);
- GoASTExpr *t = Type();
- if (!dots)
- return t;
- if (!t)
- return syntaxerror();
- return new GoASTEllipsis(t);
-}
-
-GoASTExpr *
-GoParser::InterfaceType()
-{
- if (!match(GoLexer::KEYWORD_INTERFACE) || !mustMatch(GoLexer::OP_LBRACE))
- return nullptr;
- std::unique_ptr<GoASTFieldList> methods(new GoASTFieldList);
- while (true)
- {
- Rule r("MethodSpec", this);
- // ( identifier Signature | TypeName ) ;
- std::unique_ptr<GoASTIdent> id(Identifier());
- if (!id)
- break;
- GoASTExpr *type = Signature();
- if (!type)
- {
- r.error();
- id.reset();
- type = Name();
- }
- if (!Semicolon())
- return syntaxerror();
- auto *f = new GoASTField;
- if (id)
- f->AddNames(id.release());
- f->SetType(type);
- methods->AddList(f);
- }
- if (!mustMatch(GoLexer::OP_RBRACE))
- return nullptr;
- return new GoASTInterfaceType(methods.release());
-}
-
-GoASTExpr *
-GoParser::MapType()
-{
- if (!(match(GoLexer::KEYWORD_MAP) && mustMatch(GoLexer::OP_LBRACK)))
- return nullptr;
- std::unique_ptr<GoASTExpr> key(Type());
- if (!key)
- return syntaxerror();
- if (!mustMatch(GoLexer::OP_RBRACK))
- return nullptr;
- auto *elem = Type();
- if (!elem)
- return syntaxerror();
- return new GoASTMapType(key.release(), elem);
-}
-
-GoASTExpr *
-GoParser::ChanType()
-{
- Rule r("chan", this);
- if (match(GoLexer::OP_LT_MINUS))
- {
- if (match(GoLexer::KEYWORD_CHAN))
- {
- auto *elem = Type();
- if (!elem)
- return syntaxerror();
- return new GoASTChanType(GoASTNode::eChanRecv, elem);
- }
- return r.error();
- }
- return ChanType2();
-}
-
-GoASTExpr *
-GoParser::ChanType2()
-{
- if (!match(GoLexer::KEYWORD_CHAN))
- return nullptr;
- auto dir = GoASTNode::eChanBidir;
- if (match(GoLexer::OP_LT_MINUS))
- dir = GoASTNode::eChanSend;
- auto *elem = Type();
- if (!elem)
- return syntaxerror();
- return new GoASTChanType(dir, elem);
-}
-
-GoASTExpr *
-GoParser::Type()
-{
- if (GoASTExpr *t = Type2())
- return t;
- if (GoASTExpr *t = Name())
- return t;
- if (GoASTExpr *t = ChanType())
- return t;
- if (match(GoLexer::OP_STAR))
- {
- GoASTExpr *t = Type();
- if (!t)
- return syntaxerror();
- return new GoASTStarExpr(t);
- }
- if (match(GoLexer::OP_LPAREN))
- {
- std::unique_ptr<GoASTExpr> t(Type());
- if (!t || !match(GoLexer::OP_RPAREN))
- return syntaxerror();
- return t.release();
- }
+GoASTExpr *GoParser::MapType() {
+ if (!(match(GoLexer::KEYWORD_MAP) && mustMatch(GoLexer::OP_LBRACK)))
return nullptr;
-}
-
-bool
-GoParser::Semicolon()
-{
- if (match(GoLexer::OP_SEMICOLON))
- return true;
- switch (peek())
- {
- case GoLexer::OP_RPAREN:
- case GoLexer::OP_RBRACE:
- case GoLexer::TOK_EOF:
- return true;
- default:
- return false;
- }
-}
-
-GoASTExpr *
-GoParser::Name()
-{
- if (auto *id = Identifier())
- {
- if (GoASTExpr *qual = QualifiedIdent(id))
- return qual;
- return id;
- }
+ std::unique_ptr<GoASTExpr> key(Type());
+ if (!key)
+ return syntaxerror();
+ if (!mustMatch(GoLexer::OP_RBRACK))
return nullptr;
+ auto *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTMapType(key.release(), elem);
}
-GoASTExpr *
-GoParser::QualifiedIdent(lldb_private::GoASTIdent *p)
-{
- Rule r("QualifiedIdent", this);
- llvm::SmallString<32> path(p->GetName().m_value);
- GoLexer::Token *next;
- bool have_slashes = false;
- // LLDB extension: support full/package/path.name
- while (match(GoLexer::OP_SLASH) && (next = match(GoLexer::TOK_IDENTIFIER)))
- {
- have_slashes = true;
- path.append("/");
- path.append(next->m_value);
- }
- if (match(GoLexer::OP_DOT))
- {
- auto *name = Identifier();
- if (name)
- {
- if (have_slashes)
- {
- p->SetName(GoLexer::Token(GoLexer::TOK_IDENTIFIER, CopyString(path)));
- }
- return new GoASTSelectorExpr(p, name);
- }
+GoASTExpr *GoParser::ChanType() {
+ Rule r("chan", this);
+ if (match(GoLexer::OP_LT_MINUS)) {
+ if (match(GoLexer::KEYWORD_CHAN)) {
+ auto *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTChanType(GoASTNode::eChanRecv, elem);
}
return r.error();
+ }
+ return ChanType2();
}
-llvm::StringRef
-GoParser::CopyString(llvm::StringRef s)
-{
- return m_strings.insert(std::make_pair(s, 'x')).first->getKey();
+GoASTExpr *GoParser::ChanType2() {
+ if (!match(GoLexer::KEYWORD_CHAN))
+ return nullptr;
+ auto dir = GoASTNode::eChanBidir;
+ if (match(GoLexer::OP_LT_MINUS))
+ dir = GoASTNode::eChanSend;
+ auto *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTChanType(dir, elem);
}
-void
-GoParser::GetError(Error &error)
-{
- llvm::StringRef want;
- if (m_failed)
- want = m_last_tok == GoLexer::TOK_INVALID ? DescribeToken(m_last_tok) : m_last;
- else
- want = m_error;
- size_t len = m_lexer.BytesRemaining();
- if (len > 10)
- len = 10;
- llvm::StringRef got;
- if (len == 0)
- got = "<eof>";
- else
- got = m_lexer.GetString(len);
- error.SetErrorStringWithFormat("Syntax error: expected %s before '%s'.", want.str().c_str(), got.str().c_str());
+GoASTExpr *GoParser::Type() {
+ if (GoASTExpr *t = Type2())
+ return t;
+ if (GoASTExpr *t = Name())
+ return t;
+ if (GoASTExpr *t = ChanType())
+ return t;
+ if (match(GoLexer::OP_STAR)) {
+ GoASTExpr *t = Type();
+ if (!t)
+ return syntaxerror();
+ return new GoASTStarExpr(t);
+ }
+ if (match(GoLexer::OP_LPAREN)) {
+ std::unique_ptr<GoASTExpr> t(Type());
+ if (!t || !match(GoLexer::OP_RPAREN))
+ return syntaxerror();
+ return t.release();
+ }
+ return nullptr;
+}
+
+bool GoParser::Semicolon() {
+ if (match(GoLexer::OP_SEMICOLON))
+ return true;
+ switch (peek()) {
+ case GoLexer::OP_RPAREN:
+ case GoLexer::OP_RBRACE:
+ case GoLexer::TOK_EOF:
+ return true;
+ default:
+ return false;
+ }
+}
+
+GoASTExpr *GoParser::Name() {
+ if (auto *id = Identifier()) {
+ if (GoASTExpr *qual = QualifiedIdent(id))
+ return qual;
+ return id;
+ }
+ return nullptr;
+}
+
+GoASTExpr *GoParser::QualifiedIdent(lldb_private::GoASTIdent *p) {
+ Rule r("QualifiedIdent", this);
+ llvm::SmallString<32> path(p->GetName().m_value);
+ GoLexer::Token *next;
+ bool have_slashes = false;
+ // LLDB extension: support full/package/path.name
+ while (match(GoLexer::OP_SLASH) && (next = match(GoLexer::TOK_IDENTIFIER))) {
+ have_slashes = true;
+ path.append("/");
+ path.append(next->m_value);
+ }
+ if (match(GoLexer::OP_DOT)) {
+ auto *name = Identifier();
+ if (name) {
+ if (have_slashes) {
+ p->SetName(GoLexer::Token(GoLexer::TOK_IDENTIFIER, CopyString(path)));
+ }
+ return new GoASTSelectorExpr(p, name);
+ }
+ }
+ return r.error();
+}
+
+llvm::StringRef GoParser::CopyString(llvm::StringRef s) {
+ return m_strings.insert(std::make_pair(s, 'x')).first->getKey();
+}
+
+void GoParser::GetError(Error &error) {
+ llvm::StringRef want;
+ if (m_failed)
+ want =
+ m_last_tok == GoLexer::TOK_INVALID ? DescribeToken(m_last_tok) : m_last;
+ else
+ want = m_error;
+ size_t len = m_lexer.BytesRemaining();
+ if (len > 10)
+ len = 10;
+ llvm::StringRef got;
+ if (len == 0)
+ got = "<eof>";
+ else
+ got = m_lexer.GetString(len);
+ error.SetErrorStringWithFormat("Syntax error: expected %s before '%s'.",
+ want.str().c_str(), got.str().c_str());
}
OpenPOWER on IntegriCloud