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,
|
||||
IfKeyword,
|
||||
ElseKeyword,
|
||||
MatchKeyword,
|
||||
Invalid,
|
||||
EndOfFile,
|
||||
BlockStart,
|
||||
|
@ -70,6 +71,8 @@ namespace bolt {
|
|||
VarTypeExpression,
|
||||
BindPattern,
|
||||
ReferenceExpression,
|
||||
MatchCase,
|
||||
MatchExpression,
|
||||
NestedExpression,
|
||||
ConstantExpression,
|
||||
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 {
|
||||
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 {
|
||||
public:
|
||||
|
||||
|
|
|
@ -63,6 +63,8 @@ namespace bolt {
|
|||
return static_cast<D*>(this)->visitIfKeyword(static_cast<IfKeyword*>(N));
|
||||
case NodeKind::ElseKeyword:
|
||||
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:
|
||||
return static_cast<D*>(this)->visitInvalid(static_cast<Invalid*>(N));
|
||||
case NodeKind::EndOfFile:
|
||||
|
@ -101,6 +103,10 @@ namespace bolt {
|
|||
return static_cast<D*>(this)->visitBindPattern(static_cast<BindPattern*>(N));
|
||||
case NodeKind::ReferenceExpression:
|
||||
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:
|
||||
return static_cast<D*>(this)->visitNestedExpression(static_cast<NestedExpression*>(N));
|
||||
case NodeKind::ConstantExpression:
|
||||
|
@ -256,6 +262,10 @@ namespace bolt {
|
|||
visitToken(N);
|
||||
}
|
||||
|
||||
void visitMatchKeyword(MatchKeyword* N) {
|
||||
visitToken(N);
|
||||
}
|
||||
|
||||
void visitInvalid(Invalid* N) {
|
||||
visitToken(N);
|
||||
}
|
||||
|
@ -348,6 +358,14 @@ namespace bolt {
|
|||
visitExpression(N);
|
||||
}
|
||||
|
||||
void visitMatchCase(MatchCase* N) {
|
||||
visitNode(N);
|
||||
}
|
||||
|
||||
void visitMatchExpression(MatchExpression* N) {
|
||||
visitExpression(N);
|
||||
}
|
||||
|
||||
void visitNestedExpression(NestedExpression* N) {
|
||||
visitExpression(N);
|
||||
}
|
||||
|
@ -514,6 +532,9 @@ namespace bolt {
|
|||
case NodeKind::ElseKeyword:
|
||||
visitEachChild(static_cast<ElseKeyword*>(N));
|
||||
break;
|
||||
case NodeKind::MatchKeyword:
|
||||
visitEachChild(static_cast<MatchKeyword*>(N));
|
||||
break;
|
||||
case NodeKind::Invalid:
|
||||
visitEachChild(static_cast<Invalid*>(N));
|
||||
break;
|
||||
|
@ -571,6 +592,12 @@ namespace bolt {
|
|||
case NodeKind::ReferenceExpression:
|
||||
visitEachChild(static_cast<ReferenceExpression*>(N));
|
||||
break;
|
||||
case NodeKind::MatchCase:
|
||||
visitEachChild(static_cast<MatchCase*>(N));
|
||||
break;
|
||||
case NodeKind::MatchExpression:
|
||||
visitEachChild(static_cast<MatchExpression*>(N));
|
||||
break;
|
||||
case NodeKind::NestedExpression:
|
||||
visitEachChild(static_cast<NestedExpression*>(N));
|
||||
break;
|
||||
|
@ -713,6 +740,9 @@ namespace bolt {
|
|||
void visitEachChild(ElseKeyword* N) {
|
||||
}
|
||||
|
||||
void visitEachChild(MatchKeyword* N) {
|
||||
}
|
||||
|
||||
void visitEachChild(Invalid* N) {
|
||||
}
|
||||
|
||||
|
@ -801,6 +831,23 @@ namespace bolt {
|
|||
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) {
|
||||
BOLT_VISIT(N->LParen);
|
||||
BOLT_VISIT(N->Inner);
|
||||
|
|
23
src/CST.cc
23
src/CST.cc
|
@ -232,6 +232,25 @@ namespace bolt {
|
|||
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() {
|
||||
return LParen;
|
||||
}
|
||||
|
@ -514,6 +533,10 @@ namespace bolt {
|
|||
return "elif";
|
||||
}
|
||||
|
||||
std::string MatchKeyword::getText() const {
|
||||
return "match";
|
||||
}
|
||||
|
||||
std::string ModKeyword::getText() const {
|
||||
return "mod";
|
||||
}
|
||||
|
|
|
@ -231,6 +231,33 @@ after_constraints:
|
|||
auto T2 = static_cast<RParen*>(expectToken(NodeKind::RParen));
|
||||
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::StringLiteral:
|
||||
Tokens.get();
|
||||
|
|
|
@ -69,6 +69,7 @@ namespace bolt {
|
|||
{ "if", NodeKind::IfKeyword },
|
||||
{ "else", NodeKind::ElseKeyword },
|
||||
{ "elif", NodeKind::ElifKeyword },
|
||||
{ "match", NodeKind::MatchKeyword },
|
||||
{ "class", NodeKind::ClassKeyword },
|
||||
{ "instance", NodeKind::InstanceKeyword },
|
||||
};
|
||||
|
@ -235,6 +236,8 @@ digit_finish:
|
|||
return new ElifKeyword(StartLoc);
|
||||
case NodeKind::ElseKeyword:
|
||||
return new ElseKeyword(StartLoc);
|
||||
case NodeKind::MatchKeyword:
|
||||
return new MatchKeyword(StartLoc);
|
||||
case NodeKind::ClassKeyword:
|
||||
return new ClassKeyword(StartLoc);
|
||||
case NodeKind::InstanceKeyword:
|
||||
|
|
Loading…
Reference in a new issue