diff options
Diffstat (limited to 'source/Plugins/ExpressionParser/Go/GoParser.cpp')
-rw-r--r-- | source/Plugins/ExpressionParser/Go/GoParser.cpp | 886 |
1 files changed, 0 insertions, 886 deletions
diff --git a/source/Plugins/ExpressionParser/Go/GoParser.cpp b/source/Plugins/ExpressionParser/Go/GoParser.cpp deleted file mode 100644 index 9c845d02bca0..000000000000 --- a/source/Plugins/ExpressionParser/Go/GoParser.cpp +++ /dev/null @@ -1,886 +0,0 @@ -//===-- GoParser.cpp ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <vector> - -#include "GoParser.h" - -#include "Plugins/ExpressionParser/Go/GoAST.h" -#include "lldb/Utility/Status.h" -#include "llvm/ADT/SmallString.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 - -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; -}; - -GoParser::GoParser(const char *src) - : m_lexer(src), m_pos(0), m_last_tok(GoLexer::TOK_INVALID), - 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; - 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; - 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); - } - 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(); - } - 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(); - } - 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(); - } - 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; -} - -GoASTExpr *GoParser::PrimaryExpr() { - GoASTExpr *l; - GoASTExpr *r; - (l = Conversion()) || (l = Operand()); - if (!l) - return nullptr; - 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); -} - -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::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) { - delete type; - return r.error(); - } - lit->SetType(type); - return lit; -} - -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; - } - 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(); -} - -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; - return new GoASTTypeAssertExpr(e, t); - } - return syntaxerror(); - } - return r.error(); -} - -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(); - } - return nullptr; -} - -GoASTExpr *GoParser::Conversion() { - Rule r("Conversion", this); - if (GoASTExpr *t = Type2()) { - std::unique_ptr<GoASTExpr> owner(t); - 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); - owner.release(); - 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; - } -} - -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); - } - 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()); -} - -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); - return 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; - } - 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::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(); - } - 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(Status &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()); -} |