Kate Stone b9c1b51e45 *** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style.  This kind of mass change has
*** two obvious implications:

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
2016-09-06 20:57:50 +00:00

881 lines
22 KiB
C++

//===-- 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/Core/Error.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_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)
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()) {
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::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(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());
}