Add support for match-expressions in parser
This commit is contained in:
parent
66d7b90f82
commit
1f94b7f799
5 changed files with 163 additions and 0 deletions
|
@ -51,6 +51,7 @@ namespace bolt {
|
||||||
ElifKeyword,
|
ElifKeyword,
|
||||||
IfKeyword,
|
IfKeyword,
|
||||||
ElseKeyword,
|
ElseKeyword,
|
||||||
|
MatchKeyword,
|
||||||
Invalid,
|
Invalid,
|
||||||
EndOfFile,
|
EndOfFile,
|
||||||
BlockStart,
|
BlockStart,
|
||||||
|
@ -70,6 +71,8 @@ namespace bolt {
|
||||||
VarTypeExpression,
|
VarTypeExpression,
|
||||||
BindPattern,
|
BindPattern,
|
||||||
ReferenceExpression,
|
ReferenceExpression,
|
||||||
|
MatchCase,
|
||||||
|
MatchExpression,
|
||||||
NestedExpression,
|
NestedExpression,
|
||||||
ConstantExpression,
|
ConstantExpression,
|
||||||
CallExpression,
|
CallExpression,
|
||||||
|
@ -588,6 +591,20 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MatchKeyword : public Token {
|
||||||
|
public:
|
||||||
|
|
||||||
|
inline MatchKeyword(TextLoc StartLoc):
|
||||||
|
Token(NodeKind::MatchKeyword, StartLoc) {}
|
||||||
|
|
||||||
|
std::string getText() const override;
|
||||||
|
|
||||||
|
static bool classof(const Node* N) {
|
||||||
|
return N->getKind() == NodeKind::MatchKeyword;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class Invalid : public Token {
|
class Invalid : public Token {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -969,6 +986,52 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MatchCase : public Node {
|
||||||
|
public:
|
||||||
|
|
||||||
|
class Pattern* Pattern;
|
||||||
|
class RArrowAlt* RArrowAlt;
|
||||||
|
class Expression* Expression;
|
||||||
|
|
||||||
|
inline MatchCase(
|
||||||
|
class Pattern* Pattern,
|
||||||
|
class RArrowAlt* RArrowAlt,
|
||||||
|
class Expression* Expression
|
||||||
|
): Node(NodeKind::MatchCase),
|
||||||
|
Pattern(Pattern),
|
||||||
|
RArrowAlt(RArrowAlt),
|
||||||
|
Expression(Expression) {}
|
||||||
|
|
||||||
|
Token* getFirstToken() override;
|
||||||
|
Token* getLastToken() override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MatchExpression : public Expression {
|
||||||
|
public:
|
||||||
|
|
||||||
|
class MatchKeyword* MatchKeyword;
|
||||||
|
Expression* Value;
|
||||||
|
class BlockStart* BlockStart;
|
||||||
|
std::vector<MatchCase*> Cases;
|
||||||
|
|
||||||
|
inline MatchExpression(
|
||||||
|
class MatchKeyword* MatchKeyword,
|
||||||
|
Expression* Value,
|
||||||
|
class BlockStart* BlockStart,
|
||||||
|
std::vector<MatchCase*> Cases
|
||||||
|
): Expression(NodeKind::MatchExpression),
|
||||||
|
MatchKeyword(MatchKeyword),
|
||||||
|
Value(Value),
|
||||||
|
BlockStart(BlockStart),
|
||||||
|
Cases(Cases) {}
|
||||||
|
|
||||||
|
Token* getFirstToken() override;
|
||||||
|
Token* getLastToken() override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class NestedExpression : public Expression {
|
class NestedExpression : public Expression {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,8 @@ namespace bolt {
|
||||||
return static_cast<D*>(this)->visitIfKeyword(static_cast<IfKeyword*>(N));
|
return static_cast<D*>(this)->visitIfKeyword(static_cast<IfKeyword*>(N));
|
||||||
case NodeKind::ElseKeyword:
|
case NodeKind::ElseKeyword:
|
||||||
return static_cast<D*>(this)->visitElseKeyword(static_cast<ElseKeyword*>(N));
|
return static_cast<D*>(this)->visitElseKeyword(static_cast<ElseKeyword*>(N));
|
||||||
|
case NodeKind::MatchKeyword:
|
||||||
|
return static_cast<D*>(this)->visitMatchKeyword(static_cast<MatchKeyword*>(N));
|
||||||
case NodeKind::Invalid:
|
case NodeKind::Invalid:
|
||||||
return static_cast<D*>(this)->visitInvalid(static_cast<Invalid*>(N));
|
return static_cast<D*>(this)->visitInvalid(static_cast<Invalid*>(N));
|
||||||
case NodeKind::EndOfFile:
|
case NodeKind::EndOfFile:
|
||||||
|
@ -101,6 +103,10 @@ namespace bolt {
|
||||||
return static_cast<D*>(this)->visitBindPattern(static_cast<BindPattern*>(N));
|
return static_cast<D*>(this)->visitBindPattern(static_cast<BindPattern*>(N));
|
||||||
case NodeKind::ReferenceExpression:
|
case NodeKind::ReferenceExpression:
|
||||||
return static_cast<D*>(this)->visitReferenceExpression(static_cast<ReferenceExpression*>(N));
|
return static_cast<D*>(this)->visitReferenceExpression(static_cast<ReferenceExpression*>(N));
|
||||||
|
case NodeKind::MatchCase:
|
||||||
|
return static_cast<D*>(this)->visitMatchCase(static_cast<MatchCase*>(N));
|
||||||
|
case NodeKind::MatchExpression:
|
||||||
|
return static_cast<D*>(this)->visitMatchExpression(static_cast<MatchExpression*>(N));
|
||||||
case NodeKind::NestedExpression:
|
case NodeKind::NestedExpression:
|
||||||
return static_cast<D*>(this)->visitNestedExpression(static_cast<NestedExpression*>(N));
|
return static_cast<D*>(this)->visitNestedExpression(static_cast<NestedExpression*>(N));
|
||||||
case NodeKind::ConstantExpression:
|
case NodeKind::ConstantExpression:
|
||||||
|
@ -256,6 +262,10 @@ namespace bolt {
|
||||||
visitToken(N);
|
visitToken(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitMatchKeyword(MatchKeyword* N) {
|
||||||
|
visitToken(N);
|
||||||
|
}
|
||||||
|
|
||||||
void visitInvalid(Invalid* N) {
|
void visitInvalid(Invalid* N) {
|
||||||
visitToken(N);
|
visitToken(N);
|
||||||
}
|
}
|
||||||
|
@ -348,6 +358,14 @@ namespace bolt {
|
||||||
visitExpression(N);
|
visitExpression(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitMatchCase(MatchCase* N) {
|
||||||
|
visitNode(N);
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitMatchExpression(MatchExpression* N) {
|
||||||
|
visitExpression(N);
|
||||||
|
}
|
||||||
|
|
||||||
void visitNestedExpression(NestedExpression* N) {
|
void visitNestedExpression(NestedExpression* N) {
|
||||||
visitExpression(N);
|
visitExpression(N);
|
||||||
}
|
}
|
||||||
|
@ -514,6 +532,9 @@ namespace bolt {
|
||||||
case NodeKind::ElseKeyword:
|
case NodeKind::ElseKeyword:
|
||||||
visitEachChild(static_cast<ElseKeyword*>(N));
|
visitEachChild(static_cast<ElseKeyword*>(N));
|
||||||
break;
|
break;
|
||||||
|
case NodeKind::MatchKeyword:
|
||||||
|
visitEachChild(static_cast<MatchKeyword*>(N));
|
||||||
|
break;
|
||||||
case NodeKind::Invalid:
|
case NodeKind::Invalid:
|
||||||
visitEachChild(static_cast<Invalid*>(N));
|
visitEachChild(static_cast<Invalid*>(N));
|
||||||
break;
|
break;
|
||||||
|
@ -571,6 +592,12 @@ namespace bolt {
|
||||||
case NodeKind::ReferenceExpression:
|
case NodeKind::ReferenceExpression:
|
||||||
visitEachChild(static_cast<ReferenceExpression*>(N));
|
visitEachChild(static_cast<ReferenceExpression*>(N));
|
||||||
break;
|
break;
|
||||||
|
case NodeKind::MatchCase:
|
||||||
|
visitEachChild(static_cast<MatchCase*>(N));
|
||||||
|
break;
|
||||||
|
case NodeKind::MatchExpression:
|
||||||
|
visitEachChild(static_cast<MatchExpression*>(N));
|
||||||
|
break;
|
||||||
case NodeKind::NestedExpression:
|
case NodeKind::NestedExpression:
|
||||||
visitEachChild(static_cast<NestedExpression*>(N));
|
visitEachChild(static_cast<NestedExpression*>(N));
|
||||||
break;
|
break;
|
||||||
|
@ -713,6 +740,9 @@ namespace bolt {
|
||||||
void visitEachChild(ElseKeyword* N) {
|
void visitEachChild(ElseKeyword* N) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitEachChild(MatchKeyword* N) {
|
||||||
|
}
|
||||||
|
|
||||||
void visitEachChild(Invalid* N) {
|
void visitEachChild(Invalid* N) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,6 +831,23 @@ namespace bolt {
|
||||||
BOLT_VISIT(N->Name);
|
BOLT_VISIT(N->Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitEachChild(MatchCase* N) {
|
||||||
|
BOLT_VISIT(N->Pattern);
|
||||||
|
BOLT_VISIT(N->RArrowAlt);
|
||||||
|
BOLT_VISIT(N->Expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitEachChild(MatchExpression* N) {
|
||||||
|
BOLT_VISIT(N->MatchKeyword);
|
||||||
|
if (N->Value) {
|
||||||
|
BOLT_VISIT(N->Value);
|
||||||
|
}
|
||||||
|
BOLT_VISIT(N->BlockStart);
|
||||||
|
for (auto Case: N->Cases) {
|
||||||
|
BOLT_VISIT(Case);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void visitEachChild(NestedExpression* N) {
|
void visitEachChild(NestedExpression* N) {
|
||||||
BOLT_VISIT(N->LParen);
|
BOLT_VISIT(N->LParen);
|
||||||
BOLT_VISIT(N->Inner);
|
BOLT_VISIT(N->Inner);
|
||||||
|
|
23
src/CST.cc
23
src/CST.cc
|
@ -232,6 +232,25 @@ namespace bolt {
|
||||||
return Name;
|
return Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token* MatchCase::getFirstToken() {
|
||||||
|
return Pattern->getFirstToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* MatchCase::getLastToken() {
|
||||||
|
return Expression->getLastToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* MatchExpression::getFirstToken() {
|
||||||
|
return MatchKeyword;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* MatchExpression::getLastToken() {
|
||||||
|
if (!Cases.empty()) {
|
||||||
|
return Cases.back()->getLastToken();
|
||||||
|
}
|
||||||
|
return BlockStart;
|
||||||
|
}
|
||||||
|
|
||||||
Token* NestedExpression::getFirstToken() {
|
Token* NestedExpression::getFirstToken() {
|
||||||
return LParen;
|
return LParen;
|
||||||
}
|
}
|
||||||
|
@ -514,6 +533,10 @@ namespace bolt {
|
||||||
return "elif";
|
return "elif";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string MatchKeyword::getText() const {
|
||||||
|
return "match";
|
||||||
|
}
|
||||||
|
|
||||||
std::string ModKeyword::getText() const {
|
std::string ModKeyword::getText() const {
|
||||||
return "mod";
|
return "mod";
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,6 +231,33 @@ after_constraints:
|
||||||
auto T2 = static_cast<RParen*>(expectToken(NodeKind::RParen));
|
auto T2 = static_cast<RParen*>(expectToken(NodeKind::RParen));
|
||||||
return new NestedExpression(static_cast<LParen*>(T0), E, T2);
|
return new NestedExpression(static_cast<LParen*>(T0), E, T2);
|
||||||
}
|
}
|
||||||
|
case NodeKind::MatchKeyword:
|
||||||
|
{
|
||||||
|
Tokens.get();
|
||||||
|
auto T1 = Tokens.peek();
|
||||||
|
Expression* Value = nullptr;
|
||||||
|
BlockStart* BlockStart;
|
||||||
|
if (llvm::isa<class BlockStart>(T1)) {
|
||||||
|
BlockStart = static_cast<class BlockStart*>(T1);
|
||||||
|
} else {
|
||||||
|
Value = parseExpression();
|
||||||
|
BlockStart = expectToken<class BlockStart>();
|
||||||
|
}
|
||||||
|
std::vector<MatchCase*> Cases;
|
||||||
|
for (;;) {
|
||||||
|
auto T2 = Tokens.peek();
|
||||||
|
if (llvm::isa<BlockEnd>(T2)) {
|
||||||
|
Tokens.get();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto Pattern = parsePattern();
|
||||||
|
auto RArrowAlt = expectToken<class RArrowAlt>();
|
||||||
|
auto Expression = parseExpression();
|
||||||
|
expectToken<LineFoldEnd>();
|
||||||
|
Cases.push_back(new MatchCase { Pattern, RArrowAlt, Expression });
|
||||||
|
}
|
||||||
|
return new MatchExpression(static_cast<MatchKeyword*>(T0), Value, BlockStart, Cases);
|
||||||
|
}
|
||||||
case NodeKind::IntegerLiteral:
|
case NodeKind::IntegerLiteral:
|
||||||
case NodeKind::StringLiteral:
|
case NodeKind::StringLiteral:
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
|
|
|
@ -69,6 +69,7 @@ namespace bolt {
|
||||||
{ "if", NodeKind::IfKeyword },
|
{ "if", NodeKind::IfKeyword },
|
||||||
{ "else", NodeKind::ElseKeyword },
|
{ "else", NodeKind::ElseKeyword },
|
||||||
{ "elif", NodeKind::ElifKeyword },
|
{ "elif", NodeKind::ElifKeyword },
|
||||||
|
{ "match", NodeKind::MatchKeyword },
|
||||||
{ "class", NodeKind::ClassKeyword },
|
{ "class", NodeKind::ClassKeyword },
|
||||||
{ "instance", NodeKind::InstanceKeyword },
|
{ "instance", NodeKind::InstanceKeyword },
|
||||||
};
|
};
|
||||||
|
@ -235,6 +236,8 @@ digit_finish:
|
||||||
return new ElifKeyword(StartLoc);
|
return new ElifKeyword(StartLoc);
|
||||||
case NodeKind::ElseKeyword:
|
case NodeKind::ElseKeyword:
|
||||||
return new ElseKeyword(StartLoc);
|
return new ElseKeyword(StartLoc);
|
||||||
|
case NodeKind::MatchKeyword:
|
||||||
|
return new MatchKeyword(StartLoc);
|
||||||
case NodeKind::ClassKeyword:
|
case NodeKind::ClassKeyword:
|
||||||
return new ClassKeyword(StartLoc);
|
return new ClassKeyword(StartLoc);
|
||||||
case NodeKind::InstanceKeyword:
|
case NodeKind::InstanceKeyword:
|
||||||
|
|
Loading…
Reference in a new issue