Add support for parsing more nodes and small fixes
- AppTypeExpression, NestedPattern, NamedPattern and VariantDeclaration can now be parsed. - Fixed some memory leaks when a parse error is encountered
This commit is contained in:
parent
ad460bc4a2
commit
dfaa91c9b6
6 changed files with 622 additions and 59 deletions
|
@ -108,6 +108,7 @@ namespace bolt {
|
|||
ReturnKeyword,
|
||||
ModKeyword,
|
||||
StructKeyword,
|
||||
EnumKeyword,
|
||||
ClassKeyword,
|
||||
InstanceKeyword,
|
||||
ElifKeyword,
|
||||
|
@ -130,11 +131,14 @@ namespace bolt {
|
|||
QualifiedTypeExpression,
|
||||
ReferenceTypeExpression,
|
||||
ArrowTypeExpression,
|
||||
AppTypeExpression,
|
||||
VarTypeExpression,
|
||||
NestedTypeExpression,
|
||||
TupleTypeExpression,
|
||||
BindPattern,
|
||||
LiteralPattern,
|
||||
NamedPattern,
|
||||
NestedPattern,
|
||||
ReferenceExpression,
|
||||
MatchCase,
|
||||
MatchExpression,
|
||||
|
@ -158,6 +162,9 @@ namespace bolt {
|
|||
LetDeclaration,
|
||||
RecordDeclarationField,
|
||||
RecordDeclaration,
|
||||
VariantDeclaration,
|
||||
TupleVariantDeclarationMember,
|
||||
RecordVariantDeclarationMember,
|
||||
ClassDeclaration,
|
||||
InstanceDeclaration,
|
||||
SourceFile,
|
||||
|
@ -252,9 +259,11 @@ namespace bolt {
|
|||
Node* Source;
|
||||
std::unordered_multimap<ByteString, std::tuple<Node*, SymbolKind>> Mapping;
|
||||
|
||||
void addSymbol(ByteString Name, Node* Decl, SymbolKind Kind);
|
||||
|
||||
void scan(Node* X);
|
||||
|
||||
void addBindings(Pattern* P, Node* ToInsert);
|
||||
void visitPattern(Pattern* P, Node* ToInsert);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -622,6 +631,20 @@ namespace bolt {
|
|||
|
||||
};
|
||||
|
||||
class EnumKeyword : public Token {
|
||||
public:
|
||||
|
||||
inline EnumKeyword(TextLoc StartLoc):
|
||||
Token(NodeKind::EnumKeyword, StartLoc) {}
|
||||
|
||||
std::string getText() const override;
|
||||
|
||||
static bool classof(const Node* N) {
|
||||
return N->getKind() == NodeKind::EnumKeyword;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class ClassKeyword : public Token {
|
||||
public:
|
||||
|
||||
|
@ -1067,6 +1090,24 @@ namespace bolt {
|
|||
|
||||
};
|
||||
|
||||
class AppTypeExpression : public TypeExpression {
|
||||
public:
|
||||
|
||||
TypeExpression* Op;
|
||||
std::vector<TypeExpression*> Args;
|
||||
|
||||
inline AppTypeExpression(
|
||||
TypeExpression* Op,
|
||||
std::vector<TypeExpression*> Args
|
||||
): TypeExpression(NodeKind::AppTypeExpression),
|
||||
Op(Op),
|
||||
Args(Args) {}
|
||||
|
||||
Token* getFirstToken() const override;
|
||||
Token* getLastToken() const override;
|
||||
|
||||
};
|
||||
|
||||
class VarTypeExpression : public TypeExpression {
|
||||
public:
|
||||
|
||||
|
@ -1167,6 +1208,45 @@ namespace bolt {
|
|||
|
||||
};
|
||||
|
||||
class NamedPattern : public Pattern {
|
||||
public:
|
||||
|
||||
IdentifierAlt* Name;
|
||||
std::vector<Pattern*> Patterns;
|
||||
|
||||
inline NamedPattern(
|
||||
IdentifierAlt* Name,
|
||||
std::vector<Pattern*> Patterns
|
||||
): Pattern(NodeKind::NamedPattern),
|
||||
Name(Name),
|
||||
Patterns(Patterns) {}
|
||||
|
||||
Token* getFirstToken() const override;
|
||||
Token* getLastToken() const override;
|
||||
|
||||
};
|
||||
|
||||
class NestedPattern : public Pattern {
|
||||
public:
|
||||
|
||||
class LParen* LParen;
|
||||
Pattern* P;
|
||||
class RParen* RParen;
|
||||
|
||||
inline NestedPattern(
|
||||
class LParen* LParen,
|
||||
Pattern* P,
|
||||
class RParen* RParen
|
||||
): Pattern(NodeKind::NestedPattern),
|
||||
LParen(LParen),
|
||||
P(P),
|
||||
RParen(RParen) {}
|
||||
|
||||
Token* getFirstToken() const override;
|
||||
Token* getLastToken() const override;
|
||||
|
||||
};
|
||||
|
||||
class Expression : public TypedNode {
|
||||
protected:
|
||||
|
||||
|
@ -1741,6 +1821,83 @@ namespace bolt {
|
|||
|
||||
};
|
||||
|
||||
class VariantDeclarationMember : public Node {
|
||||
public:
|
||||
|
||||
inline VariantDeclarationMember(NodeKind Kind):
|
||||
Node(Kind) {}
|
||||
|
||||
};
|
||||
|
||||
class TupleVariantDeclarationMember : public VariantDeclarationMember {
|
||||
public:
|
||||
|
||||
IdentifierAlt* Name;
|
||||
std::vector<TypeExpression*> Elements;
|
||||
|
||||
inline TupleVariantDeclarationMember(
|
||||
IdentifierAlt* Name,
|
||||
std::vector<TypeExpression*> Elements
|
||||
): VariantDeclarationMember(NodeKind::TupleVariantDeclarationMember),
|
||||
Name(Name),
|
||||
Elements(Elements) {}
|
||||
|
||||
Token* getFirstToken() const override;
|
||||
Token* getLastToken() const override;
|
||||
|
||||
};
|
||||
|
||||
class RecordVariantDeclarationMember : public VariantDeclarationMember {
|
||||
public:
|
||||
|
||||
IdentifierAlt* Name;
|
||||
BlockStart* BlockStart;
|
||||
std::vector<RecordDeclarationField*> Fields;
|
||||
|
||||
inline RecordVariantDeclarationMember(
|
||||
IdentifierAlt* Name,
|
||||
class BlockStart* BlockStart,
|
||||
std::vector<RecordDeclarationField*> Fields
|
||||
): VariantDeclarationMember(NodeKind::RecordVariantDeclarationMember),
|
||||
Name(Name),
|
||||
BlockStart(BlockStart),
|
||||
Fields(Fields) {}
|
||||
|
||||
Token* getFirstToken() const override;
|
||||
Token* getLastToken() const override;
|
||||
|
||||
};
|
||||
|
||||
class VariantDeclaration : public Node {
|
||||
public:
|
||||
|
||||
class PubKeyword* PubKeyword;
|
||||
class EnumKeyword* EnumKeyword;
|
||||
class IdentifierAlt* Name;
|
||||
std::vector<VarTypeExpression*> TVs;
|
||||
class BlockStart* BlockStart;
|
||||
std::vector<VariantDeclarationMember*> Members;
|
||||
|
||||
inline VariantDeclaration(
|
||||
class PubKeyword* PubKeyword,
|
||||
class EnumKeyword* EnumKeyword,
|
||||
class IdentifierAlt* Name,
|
||||
std::vector<VarTypeExpression*> TVs,
|
||||
class BlockStart* BlockStart,
|
||||
std::vector<VariantDeclarationMember*> Members
|
||||
): Node(NodeKind::VariantDeclaration),
|
||||
PubKeyword(PubKeyword),
|
||||
EnumKeyword(EnumKeyword),
|
||||
Name(Name),
|
||||
TVs(TVs),
|
||||
BlockStart(BlockStart),
|
||||
Members(Members) {}
|
||||
|
||||
Token* getFirstToken() const override;
|
||||
Token* getLastToken() const override;
|
||||
|
||||
};
|
||||
|
||||
class SourceFile : public Node {
|
||||
|
||||
Scope* TheScope = nullptr;
|
||||
|
@ -1798,6 +1955,7 @@ namespace bolt {
|
|||
template<> inline NodeKind getNodeType<ReturnKeyword>() { return NodeKind::ReturnKeyword; }
|
||||
template<> inline NodeKind getNodeType<ModKeyword>() { return NodeKind::ModKeyword; }
|
||||
template<> inline NodeKind getNodeType<StructKeyword>() { return NodeKind::StructKeyword; }
|
||||
template<> inline NodeKind getNodeType<EnumKeyword>() { return NodeKind::EnumKeyword; }
|
||||
template<> inline NodeKind getNodeType<ClassKeyword>() { return NodeKind::ClassKeyword; }
|
||||
template<> inline NodeKind getNodeType<InstanceKeyword>() { return NodeKind::InstanceKeyword; }
|
||||
template<> inline NodeKind getNodeType<ElifKeyword>() { return NodeKind::ElifKeyword; }
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "zen/config.hpp"
|
||||
|
||||
#include "bolt/CST.hpp"
|
||||
|
||||
namespace bolt {
|
||||
|
@ -53,6 +55,8 @@ namespace bolt {
|
|||
return static_cast<D*>(this)->visitModKeyword(static_cast<ModKeyword*>(N));
|
||||
case NodeKind::StructKeyword:
|
||||
return static_cast<D*>(this)->visitStructKeyword(static_cast<StructKeyword*>(N));
|
||||
case NodeKind::EnumKeyword:
|
||||
return static_cast<D*>(this)->visitEnumKeyword(static_cast<EnumKeyword*>(N));
|
||||
case NodeKind::ClassKeyword:
|
||||
return static_cast<D*>(this)->visitClassKeyword(static_cast<ClassKeyword*>(N));
|
||||
case NodeKind::InstanceKeyword:
|
||||
|
@ -97,6 +101,8 @@ namespace bolt {
|
|||
return static_cast<D*>(this)->visitReferenceTypeExpression(static_cast<ReferenceTypeExpression*>(N));
|
||||
case NodeKind::ArrowTypeExpression:
|
||||
return static_cast<D*>(this)->visitArrowTypeExpression(static_cast<ArrowTypeExpression*>(N));
|
||||
case NodeKind::AppTypeExpression:
|
||||
return static_cast<D*>(this)->visitAppTypeExpression(static_cast<AppTypeExpression*>(N));
|
||||
case NodeKind::VarTypeExpression:
|
||||
return static_cast<D*>(this)->visitVarTypeExpression(static_cast<VarTypeExpression*>(N));
|
||||
case NodeKind::NestedTypeExpression:
|
||||
|
@ -107,6 +113,10 @@ namespace bolt {
|
|||
return static_cast<D*>(this)->visitBindPattern(static_cast<BindPattern*>(N));
|
||||
case NodeKind::LiteralPattern:
|
||||
return static_cast<D*>(this)->visitLiteralPattern(static_cast<LiteralPattern*>(N));
|
||||
case NodeKind::NamedPattern:
|
||||
return static_cast<D*>(this)->visitNamedPattern(static_cast<NamedPattern*>(N));
|
||||
case NodeKind::NestedPattern:
|
||||
return static_cast<D*>(this)->visitNestedPattern(static_cast<NestedPattern*>(N));
|
||||
case NodeKind::ReferenceExpression:
|
||||
return static_cast<D*>(this)->visitReferenceExpression(static_cast<ReferenceExpression*>(N));
|
||||
case NodeKind::MatchCase:
|
||||
|
@ -153,6 +163,12 @@ namespace bolt {
|
|||
return static_cast<D*>(this)->visitStructDeclarationField(static_cast<RecordDeclarationField*>(N));
|
||||
case NodeKind::RecordDeclaration:
|
||||
return static_cast<D*>(this)->visitStructDeclaration(static_cast<RecordDeclaration*>(N));
|
||||
case NodeKind::VariantDeclaration:
|
||||
return static_cast<D*>(this)->visitVariantDeclaration(static_cast<VariantDeclaration*>(N));
|
||||
case NodeKind::TupleVariantDeclarationMember:
|
||||
return static_cast<D*>(this)->visitTupleVariantDeclarationMember(static_cast<TupleVariantDeclarationMember*>(N));
|
||||
case NodeKind::RecordVariantDeclarationMember:
|
||||
return static_cast<D*>(this)->visitRecordVariantDeclarationMember(static_cast<RecordVariantDeclarationMember*>(N));
|
||||
case NodeKind::ClassDeclaration:
|
||||
return static_cast<D*>(this)->visitClassDeclaration(static_cast<ClassDeclaration*>(N));
|
||||
case NodeKind::InstanceDeclaration:
|
||||
|
@ -256,6 +272,10 @@ namespace bolt {
|
|||
visitToken(N);
|
||||
}
|
||||
|
||||
void visitEnumKeyword(EnumKeyword* N) {
|
||||
visitToken(N);
|
||||
}
|
||||
|
||||
void visitClassKeyword(ClassKeyword* N) {
|
||||
visitToken(N);
|
||||
}
|
||||
|
@ -352,6 +372,10 @@ namespace bolt {
|
|||
visitTypeExpression(N);
|
||||
}
|
||||
|
||||
void visitAppTypeExpression(AppTypeExpression* N) {
|
||||
visitTypeExpression(N);
|
||||
}
|
||||
|
||||
void visitVarTypeExpression(VarTypeExpression* N) {
|
||||
visitTypeExpression(N);
|
||||
}
|
||||
|
@ -376,6 +400,14 @@ namespace bolt {
|
|||
visitPattern(N);
|
||||
}
|
||||
|
||||
void visitNamedPattern(NamedPattern* N) {
|
||||
visitPattern(N);
|
||||
}
|
||||
|
||||
void visitNestedPattern(NestedPattern* N) {
|
||||
visitPattern(N);
|
||||
}
|
||||
|
||||
void visitExpression(Expression* N) {
|
||||
visitNode(N);
|
||||
}
|
||||
|
@ -480,6 +512,22 @@ namespace bolt {
|
|||
visitNode(N);
|
||||
}
|
||||
|
||||
void visitVariantDeclaration(VariantDeclaration* N) {
|
||||
visitNode(N);
|
||||
}
|
||||
|
||||
void visitVariantDeclarationMember(VariantDeclarationMember* N) {
|
||||
visitNode(N);
|
||||
}
|
||||
|
||||
void visitTupleVariantDeclarationMember(TupleVariantDeclarationMember* N) {
|
||||
visitVariantDeclarationMember(N);
|
||||
}
|
||||
|
||||
void visitRecordVariantDeclarationMember(RecordVariantDeclarationMember* N) {
|
||||
visitVariantDeclarationMember(N);
|
||||
}
|
||||
|
||||
void visitClassDeclaration(ClassDeclaration* N) {
|
||||
visitNode(N);
|
||||
}
|
||||
|
@ -559,6 +607,9 @@ namespace bolt {
|
|||
case NodeKind::StructKeyword:
|
||||
visitEachChild(static_cast<StructKeyword*>(N));
|
||||
break;
|
||||
case NodeKind::EnumKeyword:
|
||||
visitEachChild(static_cast<EnumKeyword*>(N));
|
||||
break;
|
||||
case NodeKind::ClassKeyword:
|
||||
visitEachChild(static_cast<ClassKeyword*>(N));
|
||||
break;
|
||||
|
@ -625,6 +676,9 @@ namespace bolt {
|
|||
case NodeKind::ArrowTypeExpression:
|
||||
visitEachChild(static_cast<ArrowTypeExpression*>(N));
|
||||
break;
|
||||
case NodeKind::AppTypeExpression:
|
||||
visitEachChild(static_cast<AppTypeExpression*>(N));
|
||||
break;
|
||||
case NodeKind::VarTypeExpression:
|
||||
visitEachChild(static_cast<VarTypeExpression*>(N));
|
||||
break;
|
||||
|
@ -640,6 +694,12 @@ namespace bolt {
|
|||
case NodeKind::LiteralPattern:
|
||||
visitEachChild(static_cast<LiteralPattern*>(N));
|
||||
break;
|
||||
case NodeKind::NamedPattern:
|
||||
visitEachChild(static_cast<NamedPattern*>(N));
|
||||
break;
|
||||
case NodeKind::NestedPattern:
|
||||
visitEachChild(static_cast<NestedPattern*>(N));
|
||||
break;
|
||||
case NodeKind::ReferenceExpression:
|
||||
visitEachChild(static_cast<ReferenceExpression*>(N));
|
||||
break;
|
||||
|
@ -709,6 +769,15 @@ namespace bolt {
|
|||
case NodeKind::RecordDeclarationField:
|
||||
visitEachChild(static_cast<RecordDeclarationField*>(N));
|
||||
break;
|
||||
case NodeKind::VariantDeclaration:
|
||||
visitEachChild(static_cast<VariantDeclaration*>(N));
|
||||
break;
|
||||
case NodeKind::TupleVariantDeclarationMember:
|
||||
visitEachChild(static_cast<TupleVariantDeclarationMember*>(N));
|
||||
break;
|
||||
case NodeKind::RecordVariantDeclarationMember:
|
||||
visitEachChild(static_cast<RecordVariantDeclarationMember*>(N));
|
||||
break;
|
||||
case NodeKind::ClassDeclaration:
|
||||
visitEachChild(static_cast<ClassDeclaration*>(N));
|
||||
break;
|
||||
|
@ -788,6 +857,9 @@ namespace bolt {
|
|||
void visitEachChild(StructKeyword* N) {
|
||||
}
|
||||
|
||||
void visitEachChild(EnumKeyword* N) {
|
||||
}
|
||||
|
||||
void visitEachChild(ClassKeyword* N) {
|
||||
}
|
||||
|
||||
|
@ -878,6 +950,13 @@ namespace bolt {
|
|||
BOLT_VISIT(N->ReturnType);
|
||||
}
|
||||
|
||||
void visitEachChild(AppTypeExpression* N) {
|
||||
BOLT_VISIT(N->Op);
|
||||
for (auto Arg: N->Args) {
|
||||
BOLT_VISIT(Arg);
|
||||
}
|
||||
}
|
||||
|
||||
void visitEachChild(VarTypeExpression* N) {
|
||||
BOLT_VISIT(N->Name);
|
||||
}
|
||||
|
@ -907,6 +986,19 @@ namespace bolt {
|
|||
BOLT_VISIT(N->Literal);
|
||||
}
|
||||
|
||||
void visitEachChild(NamedPattern* N) {
|
||||
BOLT_VISIT(N->Name);
|
||||
for (auto P: N->Patterns) {
|
||||
BOLT_VISIT(P);
|
||||
}
|
||||
}
|
||||
|
||||
void visitEachChild(NestedPattern* N) {
|
||||
BOLT_VISIT(N->LParen);
|
||||
BOLT_VISIT(N->P);
|
||||
BOLT_VISIT(N->RParen);
|
||||
}
|
||||
|
||||
void visitEachChild(ReferenceExpression* N) {
|
||||
for (auto [Name, Dot]: N->ModulePath) {
|
||||
BOLT_VISIT(Name);
|
||||
|
@ -1082,6 +1174,36 @@ namespace bolt {
|
|||
}
|
||||
}
|
||||
|
||||
void visitEachChild(VariantDeclaration* N) {
|
||||
if (N->PubKeyword) {
|
||||
BOLT_VISIT(N->PubKeyword);
|
||||
}
|
||||
BOLT_VISIT(N->EnumKeyword);
|
||||
BOLT_VISIT(N->Name);
|
||||
for (auto TV: N->TVs) {
|
||||
BOLT_VISIT(TV);
|
||||
}
|
||||
BOLT_VISIT(N->BlockStart);
|
||||
for (auto Member: N->Members) {
|
||||
BOLT_VISIT(Member);
|
||||
}
|
||||
}
|
||||
|
||||
void visitEachChild(TupleVariantDeclarationMember* N) {
|
||||
BOLT_VISIT(N->Name);
|
||||
for (auto Element: N->Elements) {
|
||||
BOLT_VISIT(Element);
|
||||
}
|
||||
}
|
||||
|
||||
void visitEachChild(RecordVariantDeclarationMember* N) {
|
||||
BOLT_VISIT(N->Name);
|
||||
BOLT_VISIT(N->BlockStart);
|
||||
for (auto Field: N->Fields) {
|
||||
BOLT_VISIT(Field);
|
||||
}
|
||||
}
|
||||
|
||||
void visitEachChild(ClassDeclaration* N) {
|
||||
if (N->PubKeyword) {
|
||||
BOLT_VISIT(N->PubKeyword);
|
||||
|
|
|
@ -53,9 +53,7 @@ namespace bolt {
|
|||
std::optional<OperatorInfo> getInfix(Token* T);
|
||||
|
||||
bool isInfix(Token* T);
|
||||
|
||||
bool isPrefix(Token* T);
|
||||
|
||||
bool isSuffix(Token* T);
|
||||
|
||||
};
|
||||
|
@ -73,6 +71,8 @@ namespace bolt {
|
|||
|
||||
Token* expectToken(NodeKind Ty);
|
||||
|
||||
std::vector<RecordDeclarationField*> parseRecordFields();
|
||||
|
||||
template<typename T>
|
||||
T* expectToken() {
|
||||
return static_cast<T*>(expectToken(getNodeType<T>()));
|
||||
|
@ -86,6 +86,7 @@ namespace bolt {
|
|||
|
||||
ConstraintExpression* parseConstraintExpression();
|
||||
|
||||
TypeExpression* parseAppTypeExpression();
|
||||
TypeExpression* parsePrimitiveTypeExpression();
|
||||
TypeExpression* parseQualifiedTypeExpression();
|
||||
TypeExpression* parseArrowTypeExpression();
|
||||
|
@ -101,6 +102,7 @@ namespace bolt {
|
|||
|
||||
TypeExpression* parseTypeExpression();
|
||||
|
||||
Pattern* parsePrimitivePattern();
|
||||
Pattern* parsePattern();
|
||||
|
||||
Parameter* parseParam();
|
||||
|
@ -131,6 +133,8 @@ namespace bolt {
|
|||
|
||||
RecordDeclaration* parseRecordDeclaration();
|
||||
|
||||
VariantDeclaration* parseVariantDeclaration();
|
||||
|
||||
Node* parseSourceElement();
|
||||
|
||||
SourceFile* parseSourceFile();
|
||||
|
|
110
src/CST.cc
110
src/CST.cc
|
@ -55,6 +55,10 @@ namespace bolt {
|
|||
scan(Source);
|
||||
}
|
||||
|
||||
void Scope::addSymbol(ByteString Name, Node* Decl, SymbolKind Kind) {
|
||||
Mapping.emplace(Name, std::make_tuple(Decl, Kind));
|
||||
}
|
||||
|
||||
void Scope::scan(Node* X) {
|
||||
switch (X->getKind()) {
|
||||
case NodeKind::ExpressionStatement:
|
||||
|
@ -72,7 +76,7 @@ namespace bolt {
|
|||
case NodeKind::ClassDeclaration:
|
||||
{
|
||||
auto Decl = static_cast<ClassDeclaration*>(X);
|
||||
Mapping.emplace(Decl->Name->getCanonicalText(), std::make_tuple(Decl, SymbolKind::Class));
|
||||
addSymbol(Decl->Name->getCanonicalText(), Decl, SymbolKind::Class);
|
||||
for (auto Element: Decl->Elements) {
|
||||
scan(Element);
|
||||
}
|
||||
|
@ -84,7 +88,19 @@ namespace bolt {
|
|||
case NodeKind::LetDeclaration:
|
||||
{
|
||||
auto Decl = static_cast<LetDeclaration*>(X);
|
||||
addBindings(Decl->Pattern, Decl);
|
||||
visitPattern(Decl->Pattern, Decl);
|
||||
break;
|
||||
}
|
||||
case NodeKind::RecordDeclaration:
|
||||
{
|
||||
auto Decl = static_cast<RecordDeclaration*>(X);
|
||||
addSymbol(Decl->Name->getCanonicalText(), Decl, SymbolKind::Type);
|
||||
break;
|
||||
}
|
||||
case NodeKind::VariantDeclaration:
|
||||
{
|
||||
auto Decl = static_cast<VariantDeclaration*>(X);
|
||||
addSymbol(Decl->Name->getCanonicalText(), Decl, SymbolKind::Type);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -92,12 +108,26 @@ namespace bolt {
|
|||
}
|
||||
}
|
||||
|
||||
void Scope::addBindings(Pattern* X, Node* ToInsert) {
|
||||
void Scope::visitPattern(Pattern* X, Node* Decl) {
|
||||
switch (X->getKind()) {
|
||||
case NodeKind::BindPattern:
|
||||
{
|
||||
auto Y = static_cast<BindPattern*>(X);
|
||||
Mapping.emplace(Y->Name->Text, std::make_tuple(ToInsert, SymbolKind::Var));
|
||||
addSymbol(Y->Name->Text, Decl, SymbolKind::Var);
|
||||
break;
|
||||
}
|
||||
case NodeKind::NamedPattern:
|
||||
{
|
||||
auto Y = static_cast<NamedPattern*>(X);
|
||||
for (auto P: Y->Patterns) {
|
||||
visitPattern(P, Decl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeKind::NestedPattern:
|
||||
{
|
||||
auto Y = static_cast<NestedPattern*>(X);
|
||||
visitPattern(Y->P, Decl);
|
||||
break;
|
||||
}
|
||||
case NodeKind::LiteralPattern:
|
||||
|
@ -287,6 +317,17 @@ namespace bolt {
|
|||
return ReturnType->getLastToken();
|
||||
}
|
||||
|
||||
Token* AppTypeExpression::getFirstToken() const {
|
||||
return Op->getFirstToken();
|
||||
}
|
||||
|
||||
Token* AppTypeExpression::getLastToken() const {
|
||||
if (Args.size()) {
|
||||
return Args.back()->getLastToken();
|
||||
}
|
||||
return Op->getLastToken();
|
||||
}
|
||||
|
||||
Token* VarTypeExpression::getLastToken() const {
|
||||
return Name;
|
||||
}
|
||||
|
@ -327,6 +368,25 @@ namespace bolt {
|
|||
return Literal;
|
||||
}
|
||||
|
||||
Token* NamedPattern::getFirstToken() const {
|
||||
return Name;
|
||||
}
|
||||
|
||||
Token* NamedPattern::getLastToken() const {
|
||||
if (Patterns.size()) {
|
||||
return Patterns.back()->getLastToken();
|
||||
}
|
||||
return Name;
|
||||
}
|
||||
|
||||
Token* NestedPattern::getFirstToken() const {
|
||||
return LParen;
|
||||
}
|
||||
|
||||
Token* NestedPattern::getLastToken() const {
|
||||
return RParen;
|
||||
}
|
||||
|
||||
Token* ReferenceExpression::getFirstToken() const {
|
||||
if (!ModulePath.empty()) {
|
||||
return std::get<0>(ModulePath.front());
|
||||
|
@ -531,7 +591,43 @@ namespace bolt {
|
|||
|
||||
Token* RecordDeclaration::getLastToken() const {
|
||||
if (Fields.size()) {
|
||||
Fields.back()->getLastToken();
|
||||
return Fields.back()->getLastToken();
|
||||
}
|
||||
return BlockStart;
|
||||
}
|
||||
|
||||
Token* VariantDeclaration::getFirstToken() const {
|
||||
if (PubKeyword) {
|
||||
return PubKeyword;
|
||||
}
|
||||
return EnumKeyword;
|
||||
}
|
||||
|
||||
Token* VariantDeclaration::getLastToken() const {
|
||||
if (Members.size()) {
|
||||
return Members.back()->getLastToken();
|
||||
}
|
||||
return BlockStart;
|
||||
}
|
||||
|
||||
Token* TupleVariantDeclarationMember::getFirstToken() const {
|
||||
return Name;
|
||||
}
|
||||
|
||||
Token* TupleVariantDeclarationMember::getLastToken() const {
|
||||
if (Elements.size()) {
|
||||
return Elements.back()->getLastToken();
|
||||
}
|
||||
return Name;
|
||||
}
|
||||
|
||||
Token* RecordVariantDeclarationMember::getFirstToken() const {
|
||||
return Name;
|
||||
}
|
||||
|
||||
Token* RecordVariantDeclarationMember::getLastToken() const {
|
||||
if (Fields.size()) {
|
||||
return Fields.back()->getLastToken();
|
||||
}
|
||||
return BlockStart;
|
||||
}
|
||||
|
@ -667,6 +763,10 @@ namespace bolt {
|
|||
return "struct";
|
||||
}
|
||||
|
||||
std::string EnumKeyword::getText() const {
|
||||
return "enum";
|
||||
}
|
||||
|
||||
std::string Invalid::getText() const {
|
||||
return "";
|
||||
}
|
||||
|
|
278
src/Parser.cc
278
src/Parser.cc
|
@ -26,8 +26,10 @@
|
|||
// includes tokens. This avoids memory leaks. And yes, they matter when the
|
||||
// compiler is permanently on such as in a language server.
|
||||
//
|
||||
// 5. Always unref() a LineFoldEnd obtained via Tokens.get(), since it will
|
||||
// never be stored somewhere
|
||||
// 5. Always unref() a LineFoldEnd or BlockEnd obtained via Tokens.get(), since
|
||||
// it will never be stored somewhere
|
||||
//
|
||||
// 6. Maintain the invariant that a wrong parse will never advance the input stream.
|
||||
|
||||
namespace bolt {
|
||||
|
||||
|
@ -100,7 +102,7 @@ namespace bolt {
|
|||
return T;
|
||||
}
|
||||
|
||||
Pattern* Parser::parsePattern() {
|
||||
Pattern* Parser::parsePrimitivePattern() {
|
||||
auto T0 = Tokens.peek();
|
||||
switch (T0->getKind()) {
|
||||
case NodeKind::StringLiteral:
|
||||
|
@ -110,6 +112,52 @@ namespace bolt {
|
|||
case NodeKind::Identifier:
|
||||
Tokens.get();
|
||||
return new BindPattern(static_cast<Identifier*>(T0));
|
||||
case NodeKind::IdentifierAlt:
|
||||
Tokens.get();
|
||||
return new NamedPattern(static_cast<IdentifierAlt*>(T0), {});
|
||||
case NodeKind::LParen:
|
||||
{
|
||||
Tokens.get();
|
||||
auto LParen = static_cast<class LParen*>(T0);
|
||||
auto T1 = Tokens.peek();
|
||||
RParen* RParen;
|
||||
if (T1->getKind() == NodeKind::IdentifierAlt) {
|
||||
Tokens.get();
|
||||
auto Name = static_cast<IdentifierAlt*>(T1);
|
||||
std::vector<Pattern*> Patterns;
|
||||
for (;;) {
|
||||
auto T2 = Tokens.peek();
|
||||
if (T2->getKind() == NodeKind::RParen) {
|
||||
Tokens.get();
|
||||
RParen = static_cast<class RParen*>(T2);
|
||||
break;
|
||||
}
|
||||
auto P = parsePrimitivePattern();
|
||||
if (!P) {
|
||||
LParen->unref();
|
||||
for (auto P: Patterns) {
|
||||
P->unref();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
Patterns.push_back(P);
|
||||
}
|
||||
return new NestedPattern { LParen, new NamedPattern { Name, Patterns }, RParen };
|
||||
} else {
|
||||
auto P = parsePattern();
|
||||
if (!P) {
|
||||
LParen->unref();
|
||||
return nullptr;
|
||||
}
|
||||
auto RParen = expectToken<class RParen>();
|
||||
if (!RParen) {
|
||||
LParen->unref();
|
||||
P->unref();
|
||||
return nullptr;
|
||||
}
|
||||
return new NestedPattern { LParen, P, RParen };
|
||||
}
|
||||
}
|
||||
default:
|
||||
// Tokens.get();
|
||||
DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector { NodeKind::Identifier, NodeKind::StringLiteral, NodeKind::IntegerLiteral });
|
||||
|
@ -117,6 +165,10 @@ namespace bolt {
|
|||
}
|
||||
}
|
||||
|
||||
Pattern* Parser::parsePattern() {
|
||||
return parsePrimitivePattern();
|
||||
}
|
||||
|
||||
TypeExpression* Parser::parseTypeExpression() {
|
||||
return parseQualifiedTypeExpression();
|
||||
}
|
||||
|
@ -292,8 +344,39 @@ after_tuple_element:
|
|||
return new ReferenceTypeExpression(ModulePath, static_cast<IdentifierAlt*>(Name));
|
||||
}
|
||||
|
||||
TypeExpression* Parser::parseAppTypeExpression() {
|
||||
auto OpTy = parsePrimitiveTypeExpression();
|
||||
if (!OpTy) {
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<TypeExpression*> ArgTys;
|
||||
for (;;) {
|
||||
auto T1 = Tokens.peek();
|
||||
auto Kind = T1->getKind();
|
||||
if (Kind == NodeKind::RArrow || Kind == NodeKind::Equals || Kind == NodeKind::BlockStart || Kind == NodeKind::LineFoldEnd || Kind == NodeKind::EndOfFile || Kind == NodeKind::RParen) {
|
||||
break;
|
||||
}
|
||||
auto TE = parsePrimitiveTypeExpression();
|
||||
if (!TE) {
|
||||
OpTy->unref();
|
||||
for (auto Arg: ArgTys) {
|
||||
Arg->unref();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
ArgTys.push_back(TE);
|
||||
}
|
||||
if (ArgTys.empty()) {
|
||||
return OpTy;
|
||||
}
|
||||
return new AppTypeExpression { OpTy, ArgTys };
|
||||
}
|
||||
|
||||
TypeExpression* Parser::parseArrowTypeExpression() {
|
||||
auto RetType = parsePrimitiveTypeExpression();
|
||||
auto RetType = parseAppTypeExpression();
|
||||
if (RetType == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<TypeExpression*> ParamTypes;
|
||||
for (;;) {
|
||||
auto T1 = Tokens.peek();
|
||||
|
@ -302,7 +385,7 @@ after_tuple_element:
|
|||
}
|
||||
Tokens.get();
|
||||
ParamTypes.push_back(RetType);
|
||||
RetType = parsePrimitiveTypeExpression();
|
||||
RetType = parseAppTypeExpression();
|
||||
if (!RetType) {
|
||||
for (auto ParamType: ParamTypes) {
|
||||
ParamType->unref();
|
||||
|
@ -321,7 +404,6 @@ after_tuple_element:
|
|||
if (!T0) {
|
||||
return nullptr;
|
||||
}
|
||||
Tokens.get();
|
||||
auto T1 = Tokens.peek();
|
||||
Expression* Value;
|
||||
BlockStart* BlockStart;
|
||||
|
@ -346,7 +428,7 @@ after_tuple_element:
|
|||
for (;;) {
|
||||
auto T2 = Tokens.peek();
|
||||
if (llvm::isa<BlockEnd>(T2)) {
|
||||
Tokens.get();
|
||||
Tokens.get()->unref();
|
||||
break;
|
||||
}
|
||||
auto Pattern = parsePattern();
|
||||
|
@ -657,7 +739,7 @@ finish:
|
|||
for (;;) {
|
||||
auto T2 = Tokens.peek();
|
||||
if (T2->getKind() == NodeKind::BlockEnd) {
|
||||
Tokens.get();
|
||||
Tokens.get()->unref();
|
||||
break;
|
||||
}
|
||||
auto Element = parseLetBodyElement();
|
||||
|
@ -681,7 +763,7 @@ finish:
|
|||
for (;;) {
|
||||
auto T5 = Tokens.peek();
|
||||
if (T5->getKind() == NodeKind::BlockEnd) {
|
||||
Tokens.get();
|
||||
Tokens.get()->unref();
|
||||
break;
|
||||
}
|
||||
auto Element = parseLetBodyElement();
|
||||
|
@ -784,7 +866,7 @@ after_params:
|
|||
Elements.push_back(Element);
|
||||
}
|
||||
}
|
||||
Tokens.get();
|
||||
Tokens.get()->unref(); // Always a BlockEnd
|
||||
Body = new LetBlockBody(static_cast<BlockStart*>(T2), Elements);
|
||||
break;
|
||||
}
|
||||
|
@ -966,7 +1048,7 @@ after_vars:
|
|||
for (;;) {
|
||||
auto T2 = Tokens.peek();
|
||||
if (T2->is<BlockEnd>()) {
|
||||
Tokens.get();
|
||||
Tokens.get()->unref();
|
||||
break;
|
||||
}
|
||||
auto Element = parseClassElement();
|
||||
|
@ -1044,7 +1126,7 @@ after_vars:
|
|||
for (;;) {
|
||||
auto T2 = Tokens.peek();
|
||||
if (T2->is<BlockEnd>()) {
|
||||
Tokens.get();
|
||||
Tokens.get()->unref();
|
||||
break;
|
||||
}
|
||||
auto Element = parseClassElement();
|
||||
|
@ -1063,6 +1145,38 @@ after_vars:
|
|||
);
|
||||
}
|
||||
|
||||
std::vector<RecordDeclarationField*> Parser::parseRecordFields() {
|
||||
std::vector<RecordDeclarationField*> Fields;
|
||||
for (;;) {
|
||||
auto T1 = Tokens.peek();
|
||||
if (T1->getKind() == NodeKind::BlockEnd) {
|
||||
Tokens.get()->unref();
|
||||
break;
|
||||
}
|
||||
auto Name = expectToken<Identifier>();
|
||||
if (!Name) {
|
||||
skipToLineFoldEnd();
|
||||
continue;
|
||||
}
|
||||
auto Colon = expectToken<class Colon>();
|
||||
if (!Colon) {
|
||||
Name->unref();
|
||||
skipToLineFoldEnd();
|
||||
continue;
|
||||
}
|
||||
auto TE = parseTypeExpression();
|
||||
if (!TE) {
|
||||
Name->unref();
|
||||
Colon->unref();
|
||||
skipToLineFoldEnd();
|
||||
continue;
|
||||
}
|
||||
checkLineFoldEnd();
|
||||
Fields.push_back(new RecordDeclarationField { Name, Colon, TE });
|
||||
}
|
||||
return Fields;
|
||||
}
|
||||
|
||||
RecordDeclaration* Parser::parseRecordDeclaration() {
|
||||
auto T0 = Tokens.peek();
|
||||
PubKeyword* Pub = nullptr;
|
||||
|
@ -1087,6 +1201,17 @@ after_vars:
|
|||
skipToLineFoldEnd();
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<VarTypeExpression*> Vars;
|
||||
for (;;) {
|
||||
auto T1 = Tokens.peek();
|
||||
if (T1->getKind() == NodeKind::BlockStart) {
|
||||
break;
|
||||
}
|
||||
auto Var = parseVarTypeExpression();
|
||||
if (Var) {
|
||||
Vars.push_back(Var);
|
||||
}
|
||||
}
|
||||
auto BS = expectToken<BlockStart>();
|
||||
if (!BS) {
|
||||
if (Pub) {
|
||||
|
@ -1097,50 +1222,99 @@ after_vars:
|
|||
skipToLineFoldEnd();
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<RecordDeclarationField*> Fields;
|
||||
auto Fields = parseRecordFields();
|
||||
Tokens.get()->unref(); // Always a LineFoldEnd
|
||||
return new RecordDeclaration { Pub, Struct, Name, Vars, BS, Fields };
|
||||
}
|
||||
|
||||
VariantDeclaration* Parser::parseVariantDeclaration() {
|
||||
auto T0 = Tokens.peek();
|
||||
PubKeyword* Pub = nullptr;
|
||||
if (T0->getKind() == NodeKind::MutKeyword) {
|
||||
Tokens.get();
|
||||
Pub = static_cast<PubKeyword*>(T0);
|
||||
}
|
||||
auto Enum = expectToken<EnumKeyword>();
|
||||
if (!Enum) {
|
||||
if (Pub) {
|
||||
Pub->unref();
|
||||
}
|
||||
skipToLineFoldEnd();
|
||||
return nullptr;
|
||||
}
|
||||
auto Name = expectToken<IdentifierAlt>();
|
||||
if (!Name) {
|
||||
if (Pub) {
|
||||
Pub->unref();
|
||||
}
|
||||
Enum->unref();
|
||||
skipToLineFoldEnd();
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<VarTypeExpression*> TVs;
|
||||
for (;;) {
|
||||
auto T1 = Tokens.get();
|
||||
if (T1->getKind() == NodeKind::BlockEnd) {
|
||||
auto T0 = Tokens.peek();
|
||||
if (T0->getKind() == NodeKind::BlockStart) {
|
||||
break;
|
||||
}
|
||||
if (T1->getKind() != NodeKind::Identifier) {
|
||||
DE.add<UnexpectedTokenDiagnostic>(File, T1, std::vector { NodeKind::Identifier });
|
||||
if (Pub) {
|
||||
Pub->unref();
|
||||
}
|
||||
Struct->unref();
|
||||
Name->unref();
|
||||
T1->unref();
|
||||
skipToLineFoldEnd();
|
||||
return nullptr;
|
||||
auto Var = parseVarTypeExpression();
|
||||
if (Var) {
|
||||
TVs.push_back(Var);
|
||||
}
|
||||
auto Colon = expectToken<class Colon>();
|
||||
if (!Colon) {
|
||||
if (Pub) {
|
||||
Pub->unref();
|
||||
}
|
||||
Struct->unref();
|
||||
Name->unref();
|
||||
T1->unref();
|
||||
skipToLineFoldEnd();
|
||||
return nullptr;
|
||||
}
|
||||
auto TE = parseTypeExpression();
|
||||
if (!TE) {
|
||||
if (Pub) {
|
||||
Pub->unref();
|
||||
}
|
||||
Struct->unref();
|
||||
Name->unref();
|
||||
T1->unref();
|
||||
Colon->unref();
|
||||
skipToLineFoldEnd();
|
||||
return nullptr;
|
||||
}
|
||||
checkLineFoldEnd();
|
||||
}
|
||||
Tokens.get(); // Always a LineFoldEnd
|
||||
return new RecordDeclaration { Pub, Struct, Name, BS, Fields };
|
||||
auto BS = expectToken<BlockStart>();
|
||||
if (!BS) {
|
||||
if (Pub) {
|
||||
Pub->unref();
|
||||
}
|
||||
Enum->unref();
|
||||
Name->unref();
|
||||
skipToLineFoldEnd();
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<VariantDeclarationMember*> Members;
|
||||
for (;;) {
|
||||
next_member:
|
||||
auto T0 = Tokens.peek();
|
||||
if (T0->getKind() == NodeKind::BlockEnd) {
|
||||
Tokens.get()->unref();
|
||||
break;
|
||||
}
|
||||
auto Name = expectToken<IdentifierAlt>();
|
||||
if (!Name) {
|
||||
skipToLineFoldEnd();
|
||||
continue;
|
||||
}
|
||||
auto T1 = Tokens.peek();
|
||||
if (T1->getKind() == NodeKind::BlockStart) {
|
||||
Tokens.get();
|
||||
auto BS = static_cast<BlockStart*>(T1);
|
||||
auto Fields = parseRecordFields();
|
||||
// TODO continue; on error in Fields
|
||||
Members.push_back(new RecordVariantDeclarationMember { Name, BS, Fields });
|
||||
} else {
|
||||
std::vector<TypeExpression*> Elements;
|
||||
for (;;) {
|
||||
auto T2 = Tokens.peek();
|
||||
if (T2->getKind() == NodeKind::LineFoldEnd) {
|
||||
Tokens.get()->unref();
|
||||
break;
|
||||
}
|
||||
auto TE = parsePrimitiveTypeExpression();
|
||||
if (!TE) {
|
||||
Name->unref();
|
||||
for (auto El: Elements) {
|
||||
El->unref();
|
||||
}
|
||||
goto next_member;
|
||||
}
|
||||
Elements.push_back(TE);
|
||||
}
|
||||
Members.push_back(new TupleVariantDeclarationMember { Name, Elements });
|
||||
}
|
||||
}
|
||||
checkLineFoldEnd();
|
||||
return new VariantDeclaration { Pub, Enum, Name, TVs, BS, Members };
|
||||
}
|
||||
|
||||
Node* Parser::parseClassElement() {
|
||||
|
@ -1170,6 +1344,8 @@ after_vars:
|
|||
return parseInstanceDeclaration();
|
||||
case NodeKind::StructKeyword:
|
||||
return parseRecordDeclaration();
|
||||
case NodeKind::EnumKeyword:
|
||||
return parseVariantDeclaration();
|
||||
default:
|
||||
return parseExpressionStatement();
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ namespace bolt {
|
|||
{ "class", NodeKind::ClassKeyword },
|
||||
{ "instance", NodeKind::InstanceKeyword },
|
||||
{ "struct", NodeKind::StructKeyword },
|
||||
{ "enum", NodeKind::EnumKeyword },
|
||||
};
|
||||
|
||||
Scanner::Scanner(TextFile& File, Stream<Char>& Chars):
|
||||
|
@ -245,6 +246,8 @@ digit_finish:
|
|||
return new InstanceKeyword(StartLoc);
|
||||
case NodeKind::StructKeyword:
|
||||
return new StructKeyword(StartLoc);
|
||||
case NodeKind::EnumKeyword:
|
||||
return new EnumKeyword(StartLoc);
|
||||
default:
|
||||
ZEN_UNREACHABLE
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue