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,
|
||||
MatchCase,
|
||||
MatchExpression,
|
||||
MemberExpression,
|
||||
NestedExpression,
|
||||
ConstantExpression,
|
||||
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 {
|
||||
public:
|
||||
|
||||
|
|
|
@ -109,6 +109,8 @@ namespace bolt {
|
|||
return static_cast<D*>(this)->visitMatchCase(static_cast<MatchCase*>(N));
|
||||
case NodeKind::MatchExpression:
|
||||
return static_cast<D*>(this)->visitMatchExpression(static_cast<MatchExpression*>(N));
|
||||
case NodeKind::MemberExpression:
|
||||
return static_cast<D*>(this)->visitMemberExpression(static_cast<MemberExpression*>(N));
|
||||
case NodeKind::NestedExpression:
|
||||
return static_cast<D*>(this)->visitNestedExpression(static_cast<NestedExpression*>(N));
|
||||
case NodeKind::ConstantExpression:
|
||||
|
@ -372,6 +374,10 @@ namespace bolt {
|
|||
visitExpression(N);
|
||||
}
|
||||
|
||||
void visitMemberExpression(MemberExpression* N) {
|
||||
visitExpression(N);
|
||||
}
|
||||
|
||||
void visitNestedExpression(NestedExpression* N) {
|
||||
visitExpression(N);
|
||||
}
|
||||
|
@ -607,6 +613,9 @@ namespace bolt {
|
|||
case NodeKind::MatchExpression:
|
||||
visitEachChild(static_cast<MatchExpression*>(N));
|
||||
break;
|
||||
case NodeKind::MemberExpression:
|
||||
visitEachChild(static_cast<MemberExpression*>(N));
|
||||
break;
|
||||
case NodeKind::NestedExpression:
|
||||
visitEachChild(static_cast<NestedExpression*>(N));
|
||||
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) {
|
||||
BOLT_VISIT(N->LParen);
|
||||
BOLT_VISIT(N->Inner);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "zen/config.hpp"
|
||||
|
|
|
@ -78,6 +78,7 @@ namespace bolt {
|
|||
|
||||
Expression* parseInfixOperatorAfterExpression(Expression* LHS, int MinPrecedence);
|
||||
|
||||
Expression* parseMemberExpression();
|
||||
Expression* parsePrimitiveExpression();
|
||||
|
||||
ConstraintExpression* parseConstraintExpression();
|
||||
|
|
|
@ -275,6 +275,14 @@ namespace bolt {
|
|||
return BlockStart;
|
||||
}
|
||||
|
||||
Token* MemberExpression::getFirstToken() {
|
||||
return E->getFirstToken();
|
||||
}
|
||||
|
||||
Token* MemberExpression::getLastToken() {
|
||||
return Name;
|
||||
}
|
||||
|
||||
Token* NestedExpression::getFirstToken() {
|
||||
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 make sure that if we have Eq Int, Eq a ~ Eq Int such that an instance binding eq has the correct type
|
||||
|
||||
// TODO make unficiation work like union-find in find()
|
||||
// TODO (maybe) make unficiation work like union-find in find()
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
@ -1184,7 +1182,8 @@ namespace bolt {
|
|||
|
||||
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) {
|
||||
auto Match = Solution.find(static_cast<TVar*>(Ty));
|
||||
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() {
|
||||
auto Operator = parsePrimitiveExpression();
|
||||
auto Operator = parseMemberExpression();
|
||||
std::vector<Expression*> Args;
|
||||
for (;;) {
|
||||
auto T1 = Tokens.peek();
|
||||
|
|
Loading…
Reference in a new issue