Add support for parsing member expressions
This commit is contained in:
parent
09fcaccedc
commit
bce5bffa85
7 changed files with 77 additions and 6 deletions
|
@ -75,6 +75,7 @@ namespace bolt {
|
||||||
ReferenceExpression,
|
ReferenceExpression,
|
||||||
MatchCase,
|
MatchCase,
|
||||||
MatchExpression,
|
MatchExpression,
|
||||||
|
MemberExpression,
|
||||||
NestedExpression,
|
NestedExpression,
|
||||||
ConstantExpression,
|
ConstantExpression,
|
||||||
CallExpression,
|
CallExpression,
|
||||||
|
@ -1117,6 +1118,31 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MemberExpression : public Expression {
|
||||||
|
public:
|
||||||
|
|
||||||
|
Expression* E;
|
||||||
|
Dot* Dot;
|
||||||
|
Token* Name;
|
||||||
|
|
||||||
|
inline MemberExpression(
|
||||||
|
class Expression* E,
|
||||||
|
class Dot* Dot,
|
||||||
|
Token* Name
|
||||||
|
): Expression(NodeKind::MemberExpression),
|
||||||
|
E(E),
|
||||||
|
Dot(Dot),
|
||||||
|
Name(Name) {}
|
||||||
|
|
||||||
|
Token* getFirstToken() override;
|
||||||
|
Token* getLastToken() override;
|
||||||
|
|
||||||
|
inline Expression* getExpression() const {
|
||||||
|
return E;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class NestedExpression : public Expression {
|
class NestedExpression : public Expression {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,8 @@ namespace bolt {
|
||||||
return static_cast<D*>(this)->visitMatchCase(static_cast<MatchCase*>(N));
|
return static_cast<D*>(this)->visitMatchCase(static_cast<MatchCase*>(N));
|
||||||
case NodeKind::MatchExpression:
|
case NodeKind::MatchExpression:
|
||||||
return static_cast<D*>(this)->visitMatchExpression(static_cast<MatchExpression*>(N));
|
return static_cast<D*>(this)->visitMatchExpression(static_cast<MatchExpression*>(N));
|
||||||
|
case NodeKind::MemberExpression:
|
||||||
|
return static_cast<D*>(this)->visitMemberExpression(static_cast<MemberExpression*>(N));
|
||||||
case NodeKind::NestedExpression:
|
case NodeKind::NestedExpression:
|
||||||
return static_cast<D*>(this)->visitNestedExpression(static_cast<NestedExpression*>(N));
|
return static_cast<D*>(this)->visitNestedExpression(static_cast<NestedExpression*>(N));
|
||||||
case NodeKind::ConstantExpression:
|
case NodeKind::ConstantExpression:
|
||||||
|
@ -372,6 +374,10 @@ namespace bolt {
|
||||||
visitExpression(N);
|
visitExpression(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitMemberExpression(MemberExpression* N) {
|
||||||
|
visitExpression(N);
|
||||||
|
}
|
||||||
|
|
||||||
void visitNestedExpression(NestedExpression* N) {
|
void visitNestedExpression(NestedExpression* N) {
|
||||||
visitExpression(N);
|
visitExpression(N);
|
||||||
}
|
}
|
||||||
|
@ -607,6 +613,9 @@ namespace bolt {
|
||||||
case NodeKind::MatchExpression:
|
case NodeKind::MatchExpression:
|
||||||
visitEachChild(static_cast<MatchExpression*>(N));
|
visitEachChild(static_cast<MatchExpression*>(N));
|
||||||
break;
|
break;
|
||||||
|
case NodeKind::MemberExpression:
|
||||||
|
visitEachChild(static_cast<MemberExpression*>(N));
|
||||||
|
break;
|
||||||
case NodeKind::NestedExpression:
|
case NodeKind::NestedExpression:
|
||||||
visitEachChild(static_cast<NestedExpression*>(N));
|
visitEachChild(static_cast<NestedExpression*>(N));
|
||||||
break;
|
break;
|
||||||
|
@ -861,6 +870,12 @@ namespace bolt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitEachChild(MemberExpression* N) {
|
||||||
|
BOLT_VISIT(N->getExpression());
|
||||||
|
BOLT_VISIT(N->Dot);
|
||||||
|
BOLT_VISIT(N->Name);
|
||||||
|
}
|
||||||
|
|
||||||
void visitEachChild(NestedExpression* N) {
|
void visitEachChild(NestedExpression* N) {
|
||||||
BOLT_VISIT(N->LParen);
|
BOLT_VISIT(N->LParen);
|
||||||
BOLT_VISIT(N->Inner);
|
BOLT_VISIT(N->Inner);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "zen/config.hpp"
|
#include "zen/config.hpp"
|
||||||
|
|
|
@ -78,6 +78,7 @@ namespace bolt {
|
||||||
|
|
||||||
Expression* parseInfixOperatorAfterExpression(Expression* LHS, int MinPrecedence);
|
Expression* parseInfixOperatorAfterExpression(Expression* LHS, int MinPrecedence);
|
||||||
|
|
||||||
|
Expression* parseMemberExpression();
|
||||||
Expression* parsePrimitiveExpression();
|
Expression* parsePrimitiveExpression();
|
||||||
|
|
||||||
ConstraintExpression* parseConstraintExpression();
|
ConstraintExpression* parseConstraintExpression();
|
||||||
|
|
|
@ -275,6 +275,14 @@ namespace bolt {
|
||||||
return BlockStart;
|
return BlockStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token* MemberExpression::getFirstToken() {
|
||||||
|
return E->getFirstToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* MemberExpression::getLastToken() {
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
|
||||||
Token* NestedExpression::getFirstToken() {
|
Token* NestedExpression::getFirstToken() {
|
||||||
return LParen;
|
return LParen;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
|
|
||||||
// TODO Add list of CST variable names to TVar and unify them so that e.g. the typeclass checker may pick one when displaying a diagnostic
|
// TODO Add list of CST variable names to TVar and unify them so that e.g. the typeclass checker may pick one when displaying a diagnostic
|
||||||
|
|
||||||
// TODO make sure that if we have Eq Int, Eq a ~ Eq Int such that an instance binding eq has the correct type
|
// TODO (maybe) make unficiation work like union-find in find()
|
||||||
|
|
||||||
// TODO make unficiation work like union-find in find()
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
@ -1184,7 +1182,8 @@ namespace bolt {
|
||||||
|
|
||||||
bool Checker::unify(Type* A, Type* B, Node* Source) {
|
bool Checker::unify(Type* A, Type* B, Node* Source) {
|
||||||
|
|
||||||
auto find = [&](auto Ty) {
|
auto find = [&](auto OrigTy) {
|
||||||
|
auto Ty = OrigTy;
|
||||||
while (Ty->getKind() == TypeKind::Var) {
|
while (Ty->getKind() == TypeKind::Var) {
|
||||||
auto Match = Solution.find(static_cast<TVar*>(Ty));
|
auto Match = Solution.find(static_cast<TVar*>(Ty));
|
||||||
if (Match == Solution.end()) {
|
if (Match == Solution.end()) {
|
||||||
|
|
|
@ -279,8 +279,31 @@ after_constraints:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expression* Parser::parseMemberExpression() {
|
||||||
|
auto E = parsePrimitiveExpression();
|
||||||
|
for (;;) {
|
||||||
|
auto T1 = Tokens.peek(0);
|
||||||
|
auto T2 = Tokens.peek(1);
|
||||||
|
if (!llvm::isa<Dot>(T1)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (T2->getKind()) {
|
||||||
|
case NodeKind::IntegerLiteral:
|
||||||
|
case NodeKind::Identifier:
|
||||||
|
Tokens.get();
|
||||||
|
Tokens.get();
|
||||||
|
E = new MemberExpression { E, static_cast<Dot*>(T1), T2 };
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finish:
|
||||||
|
return E;
|
||||||
|
}
|
||||||
|
|
||||||
Expression* Parser::parseCallExpression() {
|
Expression* Parser::parseCallExpression() {
|
||||||
auto Operator = parsePrimitiveExpression();
|
auto Operator = parseMemberExpression();
|
||||||
std::vector<Expression*> Args;
|
std::vector<Expression*> Args;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto T1 = Tokens.peek();
|
auto T1 = Tokens.peek();
|
||||||
|
|
Loading…
Reference in a new issue