From b9c1b51e45b845debb76d8658edabca70ca56079 Mon Sep 17 00:00:00 2001 From: Kate Stone Date: Tue, 6 Sep 2016 20:57:50 +0000 Subject: =?UTF-8?q?***=20This=20commit=20represents=20a=20complete=20refor?= =?UTF-8?q?matting=20of=20the=20LLDB=20source=20code=20***=20to=20conform?= =?UTF-8?q?=20to=20clang-format=E2=80=99s=20LLVM=20style.=20=20This=20kind?= =?UTF-8?q?=20of=20mass=20change=20has=20***=20two=20obvious=20implication?= =?UTF-8?q?s:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firstly, merging this particular commit into a downstream fork may be a huge effort. Alternatively, it may be worth merging all changes up to this commit, performing the same reformatting operation locally, and then discarding the merge for this particular commit. The commands used to accomplish this reformatting were as follows (with current working directory as the root of the repository): find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} + find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ; The version of clang-format used was 3.9.0, and autopep8 was 1.2.4. Secondly, “blame” style tools will generally point to this commit instead of a meaningful prior commit. There are alternatives available that will attempt to look through this change and find the appropriate prior commit. YMMV. llvm-svn: 280751 --- .../Plugins/ExpressionParser/Go/GoParser.cpp | 1717 +++++++++----------- 1 file changed, 781 insertions(+), 936 deletions(-) (limited to 'lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp') diff --git a/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp b/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp index 0f136f7..327b9df 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 ""; - 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 ""; + 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> lhs; + for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList()) + lhs.push_back(std::unique_ptr(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 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> lhs; - for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList()) - lhs.push_back(std::unique_ptr(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(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 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 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(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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 methods(new GoASTFieldList); + while (true) { + Rule r("MethodSpec", this); + // ( identifier Signature | TypeName ) ; + std::unique_ptr 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 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 methods(new GoASTFieldList); - while (true) - { - Rule r("MethodSpec", this); - // ( identifier Signature | TypeName ) ; - std::unique_ptr 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 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 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 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 = ""; - 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 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 = ""; + else + got = m_lexer.GetString(len); + error.SetErrorStringWithFormat("Syntax error: expected %s before '%s'.", + want.str().c_str(), got.str().c_str()); } -- cgit v1.1