Add NamedRecordPattern and rename NamedPattern to NamedTuplePattern
This commit is contained in:
parent
7ac3c39164
commit
1b5c32fe29
7 changed files with 353 additions and 63 deletions
|
@ -141,7 +141,9 @@ namespace bolt {
|
||||||
TupleTypeExpression,
|
TupleTypeExpression,
|
||||||
BindPattern,
|
BindPattern,
|
||||||
LiteralPattern,
|
LiteralPattern,
|
||||||
NamedPattern,
|
RecordPatternField,
|
||||||
|
NamedRecordPattern,
|
||||||
|
NamedTuplePattern,
|
||||||
TuplePattern,
|
TuplePattern,
|
||||||
NestedPattern,
|
NestedPattern,
|
||||||
ListPattern,
|
ListPattern,
|
||||||
|
@ -1313,16 +1315,68 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NamedPattern : public Pattern {
|
class RecordPatternField : public Node {
|
||||||
|
public:
|
||||||
|
|
||||||
|
Identifier* Name;
|
||||||
|
Equals* Equals;
|
||||||
|
Pattern* Pattern;
|
||||||
|
|
||||||
|
inline RecordPatternField(
|
||||||
|
Identifier* Name,
|
||||||
|
class Equals* Equals,
|
||||||
|
class Pattern* Pattern
|
||||||
|
): Node(NodeKind::RecordPatternField),
|
||||||
|
Name(Name),
|
||||||
|
Equals(Equals),
|
||||||
|
Pattern(Pattern) {}
|
||||||
|
|
||||||
|
inline RecordPatternField(
|
||||||
|
Identifier* Name
|
||||||
|
): RecordPatternField(Name, nullptr, nullptr) {}
|
||||||
|
|
||||||
|
Token* getFirstToken() const override;
|
||||||
|
Token* getLastToken() const override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class NamedRecordPattern : public Pattern {
|
||||||
|
public:
|
||||||
|
|
||||||
|
std::vector<std::tuple<IdentifierAlt*, Dot*>> ModulePath;
|
||||||
|
IdentifierAlt* Name;
|
||||||
|
LBrace* LBrace;
|
||||||
|
std::vector<std::tuple<RecordPatternField*, Comma*>> Fields;
|
||||||
|
RBrace* RBrace;
|
||||||
|
|
||||||
|
inline NamedRecordPattern(
|
||||||
|
std::vector<std::tuple<IdentifierAlt*, Dot*>> ModulePath,
|
||||||
|
IdentifierAlt* Name,
|
||||||
|
class LBrace* LBrace,
|
||||||
|
std::vector<std::tuple<RecordPatternField*, Comma*>> Fields,
|
||||||
|
class RBrace* RBrace
|
||||||
|
): Pattern(NodeKind::NamedRecordPattern),
|
||||||
|
ModulePath(ModulePath),
|
||||||
|
Name(Name),
|
||||||
|
LBrace(LBrace),
|
||||||
|
Fields(Fields),
|
||||||
|
RBrace(RBrace) {}
|
||||||
|
|
||||||
|
Token* getFirstToken() const override;
|
||||||
|
Token* getLastToken() const override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class NamedTuplePattern : public Pattern {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
IdentifierAlt* Name;
|
IdentifierAlt* Name;
|
||||||
std::vector<Pattern*> Patterns;
|
std::vector<Pattern*> Patterns;
|
||||||
|
|
||||||
inline NamedPattern(
|
inline NamedTuplePattern(
|
||||||
IdentifierAlt* Name,
|
IdentifierAlt* Name,
|
||||||
std::vector<Pattern*> Patterns
|
std::vector<Pattern*> Patterns
|
||||||
): Pattern(NodeKind::NamedPattern),
|
): Pattern(NodeKind::NamedTuplePattern),
|
||||||
Name(Name),
|
Name(Name),
|
||||||
Patterns(Patterns) {}
|
Patterns(Patterns) {}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,9 @@ namespace bolt {
|
||||||
BOLT_GEN_CASE(TupleTypeExpression)
|
BOLT_GEN_CASE(TupleTypeExpression)
|
||||||
BOLT_GEN_CASE(BindPattern)
|
BOLT_GEN_CASE(BindPattern)
|
||||||
BOLT_GEN_CASE(LiteralPattern)
|
BOLT_GEN_CASE(LiteralPattern)
|
||||||
BOLT_GEN_CASE(NamedPattern)
|
BOLT_GEN_CASE(RecordPatternField)
|
||||||
|
BOLT_GEN_CASE(NamedRecordPattern)
|
||||||
|
BOLT_GEN_CASE(NamedTuplePattern)
|
||||||
BOLT_GEN_CASE(TuplePattern)
|
BOLT_GEN_CASE(TuplePattern)
|
||||||
BOLT_GEN_CASE(NestedPattern)
|
BOLT_GEN_CASE(NestedPattern)
|
||||||
BOLT_GEN_CASE(ListPattern)
|
BOLT_GEN_CASE(ListPattern)
|
||||||
|
@ -351,7 +353,15 @@ namespace bolt {
|
||||||
static_cast<D*>(this)->visitPattern(N);
|
static_cast<D*>(this)->visitPattern(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNamedPattern(NamedPattern* N) {
|
void visitRecordPatternField(RecordPatternField* N) {
|
||||||
|
static_cast<D*>(this)->visitNode(N);
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitNamedRecordPattern(NamedRecordPattern* N) {
|
||||||
|
static_cast<D*>(this)->visitPattern(N);
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitNamedTuplePattern(NamedTuplePattern* N) {
|
||||||
static_cast<D*>(this)->visitPattern(N);
|
static_cast<D*>(this)->visitPattern(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,7 +573,9 @@ namespace bolt {
|
||||||
BOLT_GEN_CHILD_CASE(TupleTypeExpression)
|
BOLT_GEN_CHILD_CASE(TupleTypeExpression)
|
||||||
BOLT_GEN_CHILD_CASE(BindPattern)
|
BOLT_GEN_CHILD_CASE(BindPattern)
|
||||||
BOLT_GEN_CHILD_CASE(LiteralPattern)
|
BOLT_GEN_CHILD_CASE(LiteralPattern)
|
||||||
BOLT_GEN_CHILD_CASE(NamedPattern)
|
BOLT_GEN_CHILD_CASE(RecordPatternField)
|
||||||
|
BOLT_GEN_CHILD_CASE(NamedRecordPattern)
|
||||||
|
BOLT_GEN_CHILD_CASE(NamedTuplePattern)
|
||||||
BOLT_GEN_CHILD_CASE(TuplePattern)
|
BOLT_GEN_CHILD_CASE(TuplePattern)
|
||||||
BOLT_GEN_CHILD_CASE(NestedPattern)
|
BOLT_GEN_CHILD_CASE(NestedPattern)
|
||||||
BOLT_GEN_CHILD_CASE(ListPattern)
|
BOLT_GEN_CHILD_CASE(ListPattern)
|
||||||
|
@ -810,7 +822,36 @@ namespace bolt {
|
||||||
BOLT_VISIT(N->Literal);
|
BOLT_VISIT(N->Literal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitEachChild(NamedPattern* N) {
|
void visitEachChild(RecordPatternField* N) {
|
||||||
|
BOLT_VISIT(N->Name);
|
||||||
|
if (N->Equals) {
|
||||||
|
BOLT_VISIT(N->Equals);
|
||||||
|
}
|
||||||
|
if (N->Pattern) {
|
||||||
|
BOLT_VISIT(N->Pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitEachChild(NamedRecordPattern* N) {
|
||||||
|
for (auto [Name, Dot]: N->ModulePath) {
|
||||||
|
BOLT_VISIT(Name);
|
||||||
|
if (Dot) {
|
||||||
|
BOLT_VISIT(Dot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOLT_VISIT(N->Name);
|
||||||
|
BOLT_VISIT(N->LBrace);
|
||||||
|
for (auto [Field, Comma]: N->Fields) {
|
||||||
|
BOLT_VISIT(Field);
|
||||||
|
if (Comma) {
|
||||||
|
BOLT_VISIT(Comma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOLT_VISIT(N->LBrace);
|
||||||
|
BOLT_VISIT(N->RBrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitEachChild(NamedTuplePattern* N) {
|
||||||
BOLT_VISIT(N->Name);
|
BOLT_VISIT(N->Name);
|
||||||
for (auto P: N->Patterns) {
|
for (auto P: N->Patterns) {
|
||||||
BOLT_VISIT(P);
|
BOLT_VISIT(P);
|
||||||
|
|
|
@ -71,7 +71,8 @@ namespace bolt {
|
||||||
|
|
||||||
Token* expectToken(NodeKind Ty);
|
Token* expectToken(NodeKind Ty);
|
||||||
|
|
||||||
std::vector<RecordDeclarationField*> parseRecordFields();
|
std::vector<RecordDeclarationField*> parseRecordDeclarationFields();
|
||||||
|
std::optional<std::vector<std::tuple<RecordPatternField*, Comma*>>> parseRecordPatternFields();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* expectToken() {
|
T* expectToken() {
|
||||||
|
@ -97,7 +98,8 @@ namespace bolt {
|
||||||
std::vector<Annotation*> parseAnnotations();
|
std::vector<Annotation*> parseAnnotations();
|
||||||
|
|
||||||
void checkLineFoldEnd();
|
void checkLineFoldEnd();
|
||||||
void skipToLineFoldEnd();
|
void skipPastLineFoldEnd();
|
||||||
|
void skipToRBrace();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "bolt/CST.hpp"
|
#include "bolt/CST.hpp"
|
||||||
#include "bolt/CSTVisitor.hpp"
|
#include "bolt/CSTVisitor.hpp"
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
namespace bolt {
|
namespace bolt {
|
||||||
|
|
||||||
|
@ -173,9 +174,21 @@ namespace bolt {
|
||||||
addSymbol(Y->Name->Text, Decl, SymbolKind::Var);
|
addSymbol(Y->Name->Text, Decl, SymbolKind::Var);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind::NamedPattern:
|
case NodeKind::NamedRecordPattern:
|
||||||
{
|
{
|
||||||
auto Y = static_cast<NamedPattern*>(X);
|
auto Y = static_cast<NamedRecordPattern*>(X);
|
||||||
|
for (auto [Field, Comma]: Y->Fields) {
|
||||||
|
if (Field->Pattern) {
|
||||||
|
visitPattern(Field->Pattern, Decl);
|
||||||
|
} else {
|
||||||
|
addSymbol(Field->Name->Text, Decl, SymbolKind::Var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NodeKind::NamedTuplePattern:
|
||||||
|
{
|
||||||
|
auto Y = static_cast<NamedTuplePattern*>(X);
|
||||||
for (auto P: Y->Patterns) {
|
for (auto P: Y->Patterns) {
|
||||||
visitPattern(P, Decl);
|
visitPattern(P, Decl);
|
||||||
}
|
}
|
||||||
|
@ -464,11 +477,36 @@ namespace bolt {
|
||||||
return Literal;
|
return Literal;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* NamedPattern::getFirstToken() const {
|
Token* RecordPatternField::getFirstToken() const {
|
||||||
return Name;
|
return Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* NamedPattern::getLastToken() const {
|
Token* RecordPatternField::getLastToken() const {
|
||||||
|
if (Pattern) {
|
||||||
|
return Pattern->getLastToken();
|
||||||
|
}
|
||||||
|
if (Equals) {
|
||||||
|
return Equals;
|
||||||
|
}
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* NamedRecordPattern::getFirstToken() const {
|
||||||
|
if (!ModulePath.empty()) {
|
||||||
|
return std::get<0>(ModulePath.back());
|
||||||
|
}
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* NamedRecordPattern::getLastToken() const {
|
||||||
|
return RBrace;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* NamedTuplePattern::getFirstToken() const {
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* NamedTuplePattern::getLastToken() const {
|
||||||
if (Patterns.size()) {
|
if (Patterns.size()) {
|
||||||
return Patterns.back()->getLastToken();
|
return Patterns.back()->getLastToken();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1113,13 +1113,13 @@ namespace bolt {
|
||||||
return Ty;
|
return Ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
case NodeKind::NamedPattern:
|
case NodeKind::NamedTuplePattern:
|
||||||
{
|
{
|
||||||
auto P = static_cast<NamedPattern*>(Pattern);
|
auto P = static_cast<NamedTuplePattern*>(Pattern);
|
||||||
auto Scm = lookup(P->Name->getCanonicalText(), SymKind::Var);
|
auto Scm = lookup(P->Name->getCanonicalText(), SymKind::Var);
|
||||||
std::vector<Type*> ParamTypes;
|
std::vector<Type*> ElementTypes;
|
||||||
for (auto P2: P->Patterns) {
|
for (auto P2: P->Patterns) {
|
||||||
ParamTypes.push_back(inferPattern(P2, Constraints, TVs));
|
ElementTypes.push_back(inferPattern(P2, Constraints, TVs));
|
||||||
}
|
}
|
||||||
if (!Scm) {
|
if (!Scm) {
|
||||||
DE.add<BindingNotFoundDiagnostic>(P->Name->getCanonicalText(), P->Name);
|
DE.add<BindingNotFoundDiagnostic>(P->Name->getCanonicalText(), P->Name);
|
||||||
|
@ -1127,7 +1127,32 @@ namespace bolt {
|
||||||
}
|
}
|
||||||
auto Ty = instantiate(Scm, P);
|
auto Ty = instantiate(Scm, P);
|
||||||
auto RetTy = createTypeVar();
|
auto RetTy = createTypeVar();
|
||||||
makeEqual(Ty, Type::buildArrow(ParamTypes, RetTy), P);
|
makeEqual(Ty, Type::buildArrow(ElementTypes, RetTy), P);
|
||||||
|
return RetTy;
|
||||||
|
}
|
||||||
|
|
||||||
|
case NodeKind::NamedRecordPattern:
|
||||||
|
{
|
||||||
|
auto P = static_cast<NamedRecordPattern*>(Pattern);
|
||||||
|
auto Scm = lookup(P->Name->getCanonicalText(), SymKind::Var);
|
||||||
|
if (Scm == nullptr) {
|
||||||
|
DE.add<BindingNotFoundDiagnostic>(P->Name->getCanonicalText(), P->Name);
|
||||||
|
return createTypeVar();
|
||||||
|
}
|
||||||
|
auto RecordTy = new Type(TNil());
|
||||||
|
for (auto [Field, Comma]: P->Fields) {
|
||||||
|
Type* FieldTy;
|
||||||
|
if (Field->Pattern) {
|
||||||
|
FieldTy = inferPattern(Field->Pattern, Constraints, TVs);
|
||||||
|
} else {
|
||||||
|
FieldTy = createTypeVar();
|
||||||
|
addBinding(Field->Name->getCanonicalText(), new Forall(TVs, Constraints, FieldTy), SymKind::Var);
|
||||||
|
}
|
||||||
|
RecordTy = new Type(TField(Field->Name->getCanonicalText(), new Type(TPresent(FieldTy)), RecordTy));
|
||||||
|
}
|
||||||
|
auto Ty = instantiate(Scm, P);
|
||||||
|
auto RetTy = createTypeVar();
|
||||||
|
makeEqual(Ty, new Type(TArrow(RecordTy, RetTy)), P);
|
||||||
return RetTy;
|
return RetTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ namespace bolt {
|
||||||
return "a tuple type expression";
|
return "a tuple type expression";
|
||||||
case NodeKind::BindPattern:
|
case NodeKind::BindPattern:
|
||||||
return "a variable binder";
|
return "a variable binder";
|
||||||
case NodeKind::NamedPattern:
|
case NodeKind::NamedTuplePattern:
|
||||||
return "a pattern for a variant member";
|
return "a pattern for a variant member";
|
||||||
case NodeKind::TuplePattern:
|
case NodeKind::TuplePattern:
|
||||||
return "a pattern for a tuple";
|
return "a pattern for a tuple";
|
||||||
|
|
|
@ -150,6 +150,39 @@ finish:
|
||||||
return new ListPattern { LBracket, Elements, RBracket };
|
return new ListPattern { LBracket, Elements, RBracket };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::vector<std::tuple<RecordPatternField*, Comma*>>> Parser::parseRecordPatternFields() {
|
||||||
|
std::vector<std::tuple<RecordPatternField*, Comma*>> Fields;
|
||||||
|
for (;;) {
|
||||||
|
auto T0 = Tokens.peek();
|
||||||
|
if (T0->getKind() == NodeKind::RBrace) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto Name = expectToken<Identifier>();
|
||||||
|
Equals* Equals = nullptr;
|
||||||
|
Pattern* Pattern = nullptr;
|
||||||
|
auto T1 = Tokens.peek();
|
||||||
|
if (T1->getKind() == NodeKind::Equals) {
|
||||||
|
Tokens.get();
|
||||||
|
Equals = static_cast<class Equals*>(T1);
|
||||||
|
Pattern = parseWidePattern();
|
||||||
|
}
|
||||||
|
auto Field = new RecordPatternField(Name, Equals, Pattern);
|
||||||
|
auto T2 = Tokens.peek();
|
||||||
|
if (T2->getKind() == NodeKind::RBrace) {
|
||||||
|
Fields.push_back(std::make_tuple(Field, nullptr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (T2->getKind() != NodeKind::Comma) {
|
||||||
|
DE.add<UnexpectedTokenDiagnostic>(File, T2, std::vector { NodeKind::RBrace, NodeKind::Comma });
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
Tokens.get();
|
||||||
|
auto Comma = static_cast<class Comma*>(T2);
|
||||||
|
Fields.push_back(std::make_tuple(Field, Comma));
|
||||||
|
}
|
||||||
|
return Fields;
|
||||||
|
}
|
||||||
|
|
||||||
Pattern* Parser::parsePrimitivePattern(bool IsNarrow) {
|
Pattern* Parser::parsePrimitivePattern(bool IsNarrow) {
|
||||||
auto T0 = Tokens.peek();
|
auto T0 = Tokens.peek();
|
||||||
switch (T0->getKind()) {
|
switch (T0->getKind()) {
|
||||||
|
@ -165,7 +198,19 @@ finish:
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
auto Name = static_cast<IdentifierAlt*>(T0);
|
auto Name = static_cast<IdentifierAlt*>(T0);
|
||||||
if (IsNarrow) {
|
if (IsNarrow) {
|
||||||
return new NamedPattern(Name, {});
|
return new NamedTuplePattern(Name, {});
|
||||||
|
}
|
||||||
|
auto T1 = Tokens.peek();
|
||||||
|
if (T1->getKind() == NodeKind::LBrace) {
|
||||||
|
auto LBrace = static_cast<class LBrace*>(T1);
|
||||||
|
Tokens.get();
|
||||||
|
auto Fields = parseRecordPatternFields();
|
||||||
|
if (!Fields) {
|
||||||
|
skipToRBrace();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto RBrace = static_cast<class RBrace*>(Tokens.get());
|
||||||
|
return new NamedRecordPattern({}, Name, LBrace, *Fields, RBrace);
|
||||||
}
|
}
|
||||||
std::vector<Pattern*> Patterns;
|
std::vector<Pattern*> Patterns;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -190,7 +235,7 @@ finish:
|
||||||
}
|
}
|
||||||
Patterns.push_back(P);
|
Patterns.push_back(P);
|
||||||
}
|
}
|
||||||
return new NamedPattern { Name, Patterns };
|
return new NamedTuplePattern { Name, Patterns };
|
||||||
}
|
}
|
||||||
case NodeKind::LBracket:
|
case NodeKind::LBracket:
|
||||||
return parseListPattern();
|
return parseListPattern();
|
||||||
|
@ -523,20 +568,20 @@ after_tuple_element:
|
||||||
}
|
}
|
||||||
auto Pattern = parseWidePattern();
|
auto Pattern = parseWidePattern();
|
||||||
if (!Pattern) {
|
if (!Pattern) {
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto RArrowAlt = expectToken<class RArrowAlt>();
|
auto RArrowAlt = expectToken<class RArrowAlt>();
|
||||||
if (!RArrowAlt) {
|
if (!RArrowAlt) {
|
||||||
Pattern->unref();
|
Pattern->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto Expression = parseExpression();
|
auto Expression = parseExpression();
|
||||||
if (!Expression) {
|
if (!Expression) {
|
||||||
Pattern->unref();
|
Pattern->unref();
|
||||||
RArrowAlt->unref();
|
RArrowAlt->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
checkLineFoldEnd();
|
checkLineFoldEnd();
|
||||||
|
@ -853,7 +898,7 @@ finish:
|
||||||
ExpressionStatement* Parser::parseExpressionStatement() {
|
ExpressionStatement* Parser::parseExpressionStatement() {
|
||||||
auto E = parseExpression();
|
auto E = parseExpression();
|
||||||
if (!E) {
|
if (!E) {
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
checkLineFoldEnd();
|
checkLineFoldEnd();
|
||||||
|
@ -875,7 +920,7 @@ finish:
|
||||||
Expression = parseExpression();
|
Expression = parseExpression();
|
||||||
if (!Expression) {
|
if (!Expression) {
|
||||||
ReturnKeyword->unref();
|
ReturnKeyword->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
checkLineFoldEnd();
|
checkLineFoldEnd();
|
||||||
|
@ -890,14 +935,14 @@ finish:
|
||||||
auto Test = parseExpression();
|
auto Test = parseExpression();
|
||||||
if (!Test) {
|
if (!Test) {
|
||||||
IfKeyword->unref();
|
IfKeyword->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto T1 = expectToken<BlockStart>();
|
auto T1 = expectToken<BlockStart>();
|
||||||
if (!T1) {
|
if (!T1) {
|
||||||
IfKeyword->unref();
|
IfKeyword->unref();
|
||||||
Test->unref();
|
Test->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::vector<Node*> Then;
|
std::vector<Node*> Then;
|
||||||
|
@ -980,7 +1025,7 @@ finish:
|
||||||
if (Foreign) {
|
if (Foreign) {
|
||||||
Foreign->unref();
|
Foreign->unref();
|
||||||
}
|
}
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
Let = static_cast<LetKeyword*>(T0);
|
Let = static_cast<LetKeyword*>(T0);
|
||||||
|
@ -1002,7 +1047,7 @@ finish:
|
||||||
if (Mut) {
|
if (Mut) {
|
||||||
Mut->unref();
|
Mut->unref();
|
||||||
}
|
}
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,7 +1079,7 @@ after_params:
|
||||||
if (TE) {
|
if (TE) {
|
||||||
TA = new TypeAssert(static_cast<Colon*>(T2), TE);
|
TA = new TypeAssert(static_cast<Colon*>(T2), TE);
|
||||||
} else {
|
} else {
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
T2 = Tokens.peek();
|
T2 = Tokens.peek();
|
||||||
|
@ -1064,7 +1109,7 @@ after_params:
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
auto E = parseExpression();
|
auto E = parseExpression();
|
||||||
if (!E) {
|
if (!E) {
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
Body = new LetExprBody(static_cast<Equals*>(T2), E);
|
Body = new LetExprBody(static_cast<Equals*>(T2), E);
|
||||||
|
@ -1195,13 +1240,13 @@ after_vars:
|
||||||
InstanceDeclaration* Parser::parseInstanceDeclaration() {
|
InstanceDeclaration* Parser::parseInstanceDeclaration() {
|
||||||
auto InstanceKeyword = expectToken<class InstanceKeyword>();
|
auto InstanceKeyword = expectToken<class InstanceKeyword>();
|
||||||
if (!InstanceKeyword) {
|
if (!InstanceKeyword) {
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto Name = expectToken<IdentifierAlt>();
|
auto Name = expectToken<IdentifierAlt>();
|
||||||
if (!Name) {
|
if (!Name) {
|
||||||
InstanceKeyword->unref();
|
InstanceKeyword->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::vector<TypeExpression*> TypeExps;
|
std::vector<TypeExpression*> TypeExps;
|
||||||
|
@ -1217,7 +1262,7 @@ after_vars:
|
||||||
for (auto TE: TypeExps) {
|
for (auto TE: TypeExps) {
|
||||||
TE->unref();
|
TE->unref();
|
||||||
}
|
}
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
TypeExps.push_back(TE);
|
TypeExps.push_back(TE);
|
||||||
|
@ -1229,7 +1274,7 @@ after_vars:
|
||||||
for (auto TE: TypeExps) {
|
for (auto TE: TypeExps) {
|
||||||
TE->unref();
|
TE->unref();
|
||||||
}
|
}
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::vector<Node*> Elements;
|
std::vector<Node*> Elements;
|
||||||
|
@ -1266,7 +1311,7 @@ after_vars:
|
||||||
if (PubKeyword) {
|
if (PubKeyword) {
|
||||||
PubKeyword->unref();
|
PubKeyword->unref();
|
||||||
}
|
}
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto Name = expectToken<IdentifierAlt>();
|
auto Name = expectToken<IdentifierAlt>();
|
||||||
|
@ -1275,7 +1320,7 @@ after_vars:
|
||||||
PubKeyword->unref();
|
PubKeyword->unref();
|
||||||
}
|
}
|
||||||
ClassKeyword->unref();
|
ClassKeyword->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::vector<VarTypeExpression*> TypeVars;
|
std::vector<VarTypeExpression*> TypeVars;
|
||||||
|
@ -1293,7 +1338,7 @@ after_vars:
|
||||||
for (auto TV: TypeVars) {
|
for (auto TV: TypeVars) {
|
||||||
TV->unref();
|
TV->unref();
|
||||||
}
|
}
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
TypeVars.push_back(TE);
|
TypeVars.push_back(TE);
|
||||||
|
@ -1307,7 +1352,7 @@ after_vars:
|
||||||
for (auto TV: TypeVars) {
|
for (auto TV: TypeVars) {
|
||||||
TV->unref();
|
TV->unref();
|
||||||
}
|
}
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::vector<Node*> Elements;
|
std::vector<Node*> Elements;
|
||||||
|
@ -1333,7 +1378,7 @@ after_vars:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RecordDeclarationField*> Parser::parseRecordFields() {
|
std::vector<RecordDeclarationField*> Parser::parseRecordDeclarationFields() {
|
||||||
std::vector<RecordDeclarationField*> Fields;
|
std::vector<RecordDeclarationField*> Fields;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto T1 = Tokens.peek();
|
auto T1 = Tokens.peek();
|
||||||
|
@ -1343,20 +1388,20 @@ after_vars:
|
||||||
}
|
}
|
||||||
auto Name = expectToken<Identifier>();
|
auto Name = expectToken<Identifier>();
|
||||||
if (!Name) {
|
if (!Name) {
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto Colon = expectToken<class Colon>();
|
auto Colon = expectToken<class Colon>();
|
||||||
if (!Colon) {
|
if (!Colon) {
|
||||||
Name->unref();
|
Name->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto TE = parseTypeExpression();
|
auto TE = parseTypeExpression();
|
||||||
if (!TE) {
|
if (!TE) {
|
||||||
Name->unref();
|
Name->unref();
|
||||||
Colon->unref();
|
Colon->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
checkLineFoldEnd();
|
checkLineFoldEnd();
|
||||||
|
@ -1377,7 +1422,7 @@ after_vars:
|
||||||
if (Pub) {
|
if (Pub) {
|
||||||
Pub->unref();
|
Pub->unref();
|
||||||
}
|
}
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto Name = expectToken<IdentifierAlt>();
|
auto Name = expectToken<IdentifierAlt>();
|
||||||
|
@ -1386,7 +1431,7 @@ after_vars:
|
||||||
Pub->unref();
|
Pub->unref();
|
||||||
}
|
}
|
||||||
Struct->unref();
|
Struct->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::vector<VarTypeExpression*> Vars;
|
std::vector<VarTypeExpression*> Vars;
|
||||||
|
@ -1407,10 +1452,10 @@ after_vars:
|
||||||
}
|
}
|
||||||
Struct->unref();
|
Struct->unref();
|
||||||
Name->unref();
|
Name->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto Fields = parseRecordFields();
|
auto Fields = parseRecordDeclarationFields();
|
||||||
Tokens.get()->unref(); // Always a LineFoldEnd
|
Tokens.get()->unref(); // Always a LineFoldEnd
|
||||||
return new RecordDeclaration { Pub, Struct, Name, Vars, BS, Fields };
|
return new RecordDeclaration { Pub, Struct, Name, Vars, BS, Fields };
|
||||||
}
|
}
|
||||||
|
@ -1427,7 +1472,7 @@ after_vars:
|
||||||
if (Pub) {
|
if (Pub) {
|
||||||
Pub->unref();
|
Pub->unref();
|
||||||
}
|
}
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto Name = expectToken<IdentifierAlt>();
|
auto Name = expectToken<IdentifierAlt>();
|
||||||
|
@ -1436,7 +1481,7 @@ after_vars:
|
||||||
Pub->unref();
|
Pub->unref();
|
||||||
}
|
}
|
||||||
Enum->unref();
|
Enum->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::vector<VarTypeExpression*> TVs;
|
std::vector<VarTypeExpression*> TVs;
|
||||||
|
@ -1457,7 +1502,7 @@ after_vars:
|
||||||
}
|
}
|
||||||
Enum->unref();
|
Enum->unref();
|
||||||
Name->unref();
|
Name->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::vector<VariantDeclarationMember*> Members;
|
std::vector<VariantDeclarationMember*> Members;
|
||||||
|
@ -1470,14 +1515,14 @@ next_member:
|
||||||
}
|
}
|
||||||
auto Name = expectToken<IdentifierAlt>();
|
auto Name = expectToken<IdentifierAlt>();
|
||||||
if (!Name) {
|
if (!Name) {
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto T1 = Tokens.peek();
|
auto T1 = Tokens.peek();
|
||||||
if (T1->getKind() == NodeKind::BlockStart) {
|
if (T1->getKind() == NodeKind::BlockStart) {
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
auto BS = static_cast<BlockStart*>(T1);
|
auto BS = static_cast<BlockStart*>(T1);
|
||||||
auto Fields = parseRecordFields();
|
auto Fields = parseRecordDeclarationFields();
|
||||||
// TODO continue; on error in Fields
|
// TODO continue; on error in Fields
|
||||||
Members.push_back(new RecordVariantDeclarationMember { Name, BS, Fields });
|
Members.push_back(new RecordVariantDeclarationMember { Name, BS, Fields });
|
||||||
} else {
|
} else {
|
||||||
|
@ -1514,7 +1559,7 @@ next_member:
|
||||||
// TODO
|
// TODO
|
||||||
default:
|
default:
|
||||||
DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector<NodeKind> { NodeKind::LetKeyword, NodeKind::TypeKeyword });
|
DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector<NodeKind> { NodeKind::LetKeyword, NodeKind::TypeKeyword });
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1584,7 +1629,7 @@ next_member:
|
||||||
auto E = parseExpression();
|
auto E = parseExpression();
|
||||||
if (!E) {
|
if (!E) {
|
||||||
At->unref();
|
At->unref();
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
checkLineFoldEnd();
|
checkLineFoldEnd();
|
||||||
|
@ -1602,26 +1647,111 @@ next_annotation:;
|
||||||
return Annotations;
|
return Annotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::skipToLineFoldEnd() {
|
void Parser::skipToRBrace() {
|
||||||
unsigned Level = 0;
|
unsigned ParenLevel = 0;
|
||||||
|
unsigned BracketLevel = 0;
|
||||||
|
unsigned BraceLevel = 0;
|
||||||
|
unsigned BlockLevel = 0;
|
||||||
|
for (;;) {
|
||||||
|
auto T0 = Tokens.peek();
|
||||||
|
switch (T0->getKind()) {
|
||||||
|
case NodeKind::EndOfFile:
|
||||||
|
return;
|
||||||
|
case NodeKind::LineFoldEnd:
|
||||||
|
Tokens.get()->unref();
|
||||||
|
if (BlockLevel == 0 && ParenLevel == 0 && BracketLevel == 0 && BlockLevel == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NodeKind::BlockStart:
|
||||||
|
Tokens.get()->unref();
|
||||||
|
BlockLevel++;
|
||||||
|
break;
|
||||||
|
case NodeKind::BlockEnd:
|
||||||
|
Tokens.get()->unref();
|
||||||
|
BlockLevel--;
|
||||||
|
break;
|
||||||
|
case NodeKind::LParen:
|
||||||
|
Tokens.get()->unref();
|
||||||
|
ParenLevel++;
|
||||||
|
break;
|
||||||
|
case NodeKind::LBracket:
|
||||||
|
Tokens.get()->unref();
|
||||||
|
BracketLevel++;
|
||||||
|
break;
|
||||||
|
case NodeKind::LBrace:
|
||||||
|
Tokens.get()->unref();
|
||||||
|
BraceLevel++;
|
||||||
|
break;
|
||||||
|
case NodeKind::RParen:
|
||||||
|
Tokens.get()->unref();
|
||||||
|
ParenLevel--;
|
||||||
|
break;
|
||||||
|
case NodeKind::RBracket:
|
||||||
|
Tokens.get()->unref();
|
||||||
|
BracketLevel--;
|
||||||
|
break;
|
||||||
|
case NodeKind::RBrace:
|
||||||
|
if (BlockLevel == 0 && ParenLevel == 0 && BracketLevel == 0 && BlockLevel == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Tokens.get()->unref();
|
||||||
|
BraceLevel--;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Tokens.get()->unref();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::skipPastLineFoldEnd() {
|
||||||
|
unsigned ParenLevel = 0;
|
||||||
|
unsigned BracketLevel = 0;
|
||||||
|
unsigned BraceLevel = 0;
|
||||||
|
unsigned BlockLevel = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto T0 = Tokens.get();
|
auto T0 = Tokens.get();
|
||||||
switch (T0->getKind()) {
|
switch (T0->getKind()) {
|
||||||
case NodeKind::EndOfFile:
|
case NodeKind::EndOfFile:
|
||||||
return;
|
return;
|
||||||
case NodeKind::LineFoldEnd:
|
case NodeKind::LineFoldEnd:
|
||||||
T0->unref();
|
T0->unref();
|
||||||
if (Level == 0) {
|
if (BlockLevel == 0 && ParenLevel == 0 && BracketLevel == 0 && BlockLevel == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NodeKind::BlockStart:
|
case NodeKind::BlockStart:
|
||||||
T0->unref();
|
T0->unref();
|
||||||
Level++;
|
BlockLevel++;
|
||||||
break;
|
break;
|
||||||
case NodeKind::BlockEnd:
|
case NodeKind::BlockEnd:
|
||||||
T0->unref();
|
T0->unref();
|
||||||
Level--;
|
BlockLevel--;
|
||||||
|
break;
|
||||||
|
case NodeKind::LParen:
|
||||||
|
T0->unref();
|
||||||
|
ParenLevel++;
|
||||||
|
break;
|
||||||
|
case NodeKind::LBracket:
|
||||||
|
T0->unref();
|
||||||
|
BracketLevel++;
|
||||||
|
break;
|
||||||
|
case NodeKind::LBrace:
|
||||||
|
T0->unref();
|
||||||
|
BraceLevel++;
|
||||||
|
break;
|
||||||
|
case NodeKind::RParen:
|
||||||
|
T0->unref();
|
||||||
|
ParenLevel--;
|
||||||
|
break;
|
||||||
|
case NodeKind::RBracket:
|
||||||
|
T0->unref();
|
||||||
|
BracketLevel--;
|
||||||
|
break;
|
||||||
|
case NodeKind::RBrace:
|
||||||
|
T0->unref();
|
||||||
|
BraceLevel--;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
T0->unref();
|
T0->unref();
|
||||||
|
@ -1636,7 +1766,7 @@ next_annotation:;
|
||||||
Tokens.get()->unref();
|
Tokens.get()->unref();
|
||||||
} else {
|
} else {
|
||||||
DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector { NodeKind::LineFoldEnd });
|
DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector { NodeKind::LineFoldEnd });
|
||||||
skipToLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue