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:
Sam Vervaeck 2023-05-28 19:07:52 +02:00
parent ad460bc4a2
commit dfaa91c9b6
Signed by: samvv
SSH key fingerprint: SHA256:dIg0ywU1OP+ZYifrYxy8c5esO72cIKB+4/9wkZj1VaY
6 changed files with 622 additions and 59 deletions

View file

@ -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; }

View file

@ -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);

View file

@ -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();

View file

@ -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 "";
}

View file

@ -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();
}

View file

@ -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
}