2022-08-19 19:52:57 +02:00
|
|
|
|
2023-05-20 23:48:26 +02:00
|
|
|
#include <exception>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
|
2022-08-19 19:52:57 +02:00
|
|
|
#include "bolt/CST.hpp"
|
|
|
|
#include "bolt/Scanner.hpp"
|
|
|
|
#include "bolt/Parser.hpp"
|
|
|
|
#include "bolt/Diagnostics.hpp"
|
|
|
|
|
|
|
|
namespace bolt {
|
|
|
|
|
2022-08-21 16:25:52 +02:00
|
|
|
std::optional<OperatorInfo> OperatorTable::getInfix(Token* T) {
|
|
|
|
auto Match = Mapping.find(T->getText());
|
|
|
|
if (Match == Mapping.end() || !Match->second.isInfix()) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
return Match->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OperatorTable::isInfix(Token* T) {
|
|
|
|
auto Match = Mapping.find(T->getText());
|
|
|
|
return Match != Mapping.end() && Match->second.isInfix();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OperatorTable::isPrefix(Token* T) {
|
|
|
|
auto Match = Mapping.find(T->getText());
|
|
|
|
return Match != Mapping.end() && Match->second.isPrefix();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OperatorTable::isSuffix(Token* T) {
|
|
|
|
auto Match = Mapping.find(T->getText());
|
|
|
|
return Match != Mapping.end() && Match->second.isSuffix();
|
|
|
|
}
|
|
|
|
|
|
|
|
void OperatorTable::add(std::string Name, unsigned Flags, int Precedence) {
|
|
|
|
Mapping.emplace(Name, OperatorInfo { Precedence, Flags });
|
|
|
|
}
|
|
|
|
|
2022-08-24 12:36:43 +02:00
|
|
|
Parser::Parser(TextFile& File, Stream<Token*>& S):
|
|
|
|
File(File), Tokens(S) {
|
2022-08-21 16:25:52 +02:00
|
|
|
ExprOperators.add("**", OperatorFlags_InfixR, 10);
|
|
|
|
ExprOperators.add("*", OperatorFlags_InfixL, 5);
|
|
|
|
ExprOperators.add("/", OperatorFlags_InfixL, 5);
|
|
|
|
ExprOperators.add("+", OperatorFlags_InfixL, 4);
|
|
|
|
ExprOperators.add("-", OperatorFlags_InfixL, 4);
|
|
|
|
ExprOperators.add("<", OperatorFlags_InfixL, 3);
|
|
|
|
ExprOperators.add(">", OperatorFlags_InfixL, 3);
|
|
|
|
ExprOperators.add("<=", OperatorFlags_InfixL, 3);
|
|
|
|
ExprOperators.add(">=", OperatorFlags_InfixL, 3);
|
|
|
|
ExprOperators.add("==", OperatorFlags_InfixL, 3);
|
|
|
|
ExprOperators.add("!=", OperatorFlags_InfixL, 3);
|
|
|
|
ExprOperators.add(":", OperatorFlags_InfixL, 2);
|
|
|
|
ExprOperators.add("<|>", OperatorFlags_InfixL, 1);
|
|
|
|
ExprOperators.add("$", OperatorFlags_InfixR, 0);
|
|
|
|
}
|
2022-08-19 19:52:57 +02:00
|
|
|
|
|
|
|
Token* Parser::peekFirstTokenAfterModifiers() {
|
|
|
|
std::size_t I = 0;
|
|
|
|
for (;;) {
|
|
|
|
auto T0 = Tokens.peek(I++);
|
2023-05-20 23:48:26 +02:00
|
|
|
switch (T0->getKind()) {
|
|
|
|
case NodeKind::PubKeyword:
|
|
|
|
case NodeKind::MutKeyword:
|
2022-08-19 19:52:57 +02:00
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
return T0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define BOLT_EXPECT_TOKEN(name) \
|
|
|
|
{ \
|
|
|
|
auto __Token = Tokens.get(); \
|
2023-05-20 23:48:26 +02:00
|
|
|
if (!llvm::isa<name>(__Token)) { \
|
|
|
|
throw UnexpectedTokenDiagnostic(File, __Token, std::vector<NodeKind> { NodeKind::name }); \
|
2022-08-19 19:52:57 +02:00
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2023-05-20 23:48:26 +02:00
|
|
|
Token* Parser::expectToken(NodeKind Kind) {
|
2022-08-25 23:04:09 +02:00
|
|
|
auto T = Tokens.get();
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T->getKind() != Kind) {
|
|
|
|
throw UnexpectedTokenDiagnostic(File, T, std::vector<NodeKind> { Kind }); \
|
2022-08-25 23:04:09 +02:00
|
|
|
}
|
|
|
|
return T;
|
|
|
|
}
|
|
|
|
|
2022-08-19 19:52:57 +02:00
|
|
|
Pattern* Parser::parsePattern() {
|
|
|
|
auto T0 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
switch (T0->getKind()) {
|
|
|
|
case NodeKind::Identifier:
|
2022-08-19 19:52:57 +02:00
|
|
|
Tokens.get();
|
|
|
|
return new BindPattern(static_cast<Identifier*>(T0));
|
|
|
|
default:
|
2023-05-20 23:48:26 +02:00
|
|
|
throw UnexpectedTokenDiagnostic(File, T0, std::vector { NodeKind::Identifier });
|
2022-08-19 19:52:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-20 23:48:26 +02:00
|
|
|
TypeExpression* Parser::parseTypeExpression() {
|
|
|
|
return parseQualifiedTypeExpression();
|
|
|
|
}
|
|
|
|
|
|
|
|
TypeExpression* Parser::parseQualifiedTypeExpression() {
|
|
|
|
bool HasConstraints = false;
|
|
|
|
auto T0 = Tokens.peek();
|
|
|
|
if (llvm::isa<LParen>(T0)) {
|
|
|
|
std::size_t I = 1;
|
|
|
|
for (;;) {
|
|
|
|
auto T0 = Tokens.peek(I++);
|
|
|
|
switch (T0->getKind()) {
|
|
|
|
case NodeKind::RArrowAlt:
|
|
|
|
HasConstraints = true;
|
|
|
|
goto after_scan;
|
|
|
|
case NodeKind::Equals:
|
|
|
|
case NodeKind::BlockStart:
|
|
|
|
case NodeKind::LineFoldEnd:
|
|
|
|
case NodeKind::EndOfFile:
|
|
|
|
goto after_scan;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
after_scan:
|
|
|
|
if (!HasConstraints) {
|
|
|
|
return parseArrowTypeExpression();
|
|
|
|
}
|
|
|
|
Tokens.get();
|
|
|
|
LParen* LParen = static_cast<class LParen*>(T0);
|
|
|
|
std::vector<std::tuple<ConstraintExpression*, Comma*>> Constraints;
|
|
|
|
RParen* RParen;
|
|
|
|
RArrowAlt* RArrowAlt;
|
|
|
|
for (;;) {
|
|
|
|
ConstraintExpression* C;
|
|
|
|
auto T0 = Tokens.peek();
|
|
|
|
switch (T0->getKind()) {
|
|
|
|
case NodeKind::RParen:
|
|
|
|
Tokens.get();
|
|
|
|
RParen = static_cast<class RParen*>(T0);
|
|
|
|
RArrowAlt = expectToken<class RArrowAlt>();
|
|
|
|
goto after_constraints;
|
|
|
|
default:
|
|
|
|
C = parseConstraintExpression();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Comma* Comma = nullptr;
|
|
|
|
auto T1 = Tokens.get();
|
|
|
|
switch (T1->getKind()) {
|
|
|
|
case NodeKind::Comma:
|
|
|
|
Constraints.push_back(std::make_tuple(C, static_cast<class Comma*>(T1)));
|
|
|
|
continue;
|
|
|
|
case NodeKind::RParen:
|
|
|
|
RArrowAlt = static_cast<class RArrowAlt*>(T1);
|
|
|
|
Constraints.push_back(std::make_tuple(C, nullptr));
|
|
|
|
RArrowAlt = expectToken<class RArrowAlt>();
|
|
|
|
goto after_constraints;
|
|
|
|
default:
|
|
|
|
throw UnexpectedTokenDiagnostic(File, T1, std::vector { NodeKind::Comma, NodeKind::RArrowAlt });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
after_constraints:
|
|
|
|
auto TE = parseArrowTypeExpression();
|
|
|
|
return new QualifiedTypeExpression(Constraints, RArrowAlt, TE);
|
|
|
|
}
|
|
|
|
|
2022-08-25 19:04:25 +02:00
|
|
|
TypeExpression* Parser::parsePrimitiveTypeExpression() {
|
2022-08-19 19:52:57 +02:00
|
|
|
auto T0 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
switch (T0->getKind()) {
|
|
|
|
case NodeKind::Identifier:
|
|
|
|
return parseVarTypeExpression();
|
2023-05-21 00:25:01 +02:00
|
|
|
case NodeKind::IdentifierAlt:
|
|
|
|
{
|
|
|
|
std::vector<std::tuple<IdentifierAlt*, Dot*>> ModulePath;
|
|
|
|
auto Name = expectToken<IdentifierAlt>();
|
|
|
|
for (;;) {
|
|
|
|
auto T1 = Tokens.peek();
|
|
|
|
if (T1->getKind() != NodeKind::Dot) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Tokens.get();
|
|
|
|
ModulePath.push_back(std::make_tuple(static_cast<IdentifierAlt*>(Name), static_cast<Dot*>(T1)));
|
|
|
|
Name = expectToken<IdentifierAlt>();
|
2023-05-20 23:48:26 +02:00
|
|
|
}
|
2023-05-21 00:25:01 +02:00
|
|
|
return new ReferenceTypeExpression(ModulePath, static_cast<IdentifierAlt*>(Name));
|
|
|
|
}
|
2022-08-19 19:52:57 +02:00
|
|
|
default:
|
2023-05-20 23:48:26 +02:00
|
|
|
throw UnexpectedTokenDiagnostic(File, T0, std::vector { NodeKind::Identifier });
|
2022-08-19 19:52:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-20 23:48:26 +02:00
|
|
|
TypeExpression* Parser::parseArrowTypeExpression() {
|
2022-08-25 19:04:25 +02:00
|
|
|
auto RetType = parsePrimitiveTypeExpression();
|
|
|
|
std::vector<TypeExpression*> ParamTypes;
|
|
|
|
for (;;) {
|
|
|
|
auto T1 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T1->getKind() != NodeKind::RArrow) {
|
2022-08-25 19:04:25 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
Tokens.get();
|
|
|
|
ParamTypes.push_back(RetType);
|
|
|
|
RetType = parsePrimitiveTypeExpression();
|
|
|
|
}
|
2023-05-20 23:48:26 +02:00
|
|
|
if (!ParamTypes.empty()) {
|
2022-08-25 19:04:25 +02:00
|
|
|
return new ArrowTypeExpression(ParamTypes, RetType);
|
|
|
|
}
|
|
|
|
return RetType;
|
|
|
|
}
|
|
|
|
|
2022-08-21 16:25:52 +02:00
|
|
|
Expression* Parser::parsePrimitiveExpression() {
|
2022-08-19 19:52:57 +02:00
|
|
|
auto T0 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
switch (T0->getKind()) {
|
|
|
|
case NodeKind::Identifier:
|
2022-08-24 12:36:43 +02:00
|
|
|
{
|
2023-05-21 00:25:01 +02:00
|
|
|
std::vector<std::tuple<IdentifierAlt*, Dot*>> ModulePath;
|
|
|
|
for (;;) {
|
|
|
|
auto T1 = Tokens.peek();
|
|
|
|
if (T1->getKind() != NodeKind::IdentifierAlt) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Tokens.get();
|
|
|
|
auto Dot = expectToken<class Dot>();
|
|
|
|
ModulePath.push_back(std::make_tuple(static_cast<IdentifierAlt*>(T1), Dot));
|
|
|
|
}
|
|
|
|
return new ReferenceExpression(ModulePath, expectToken<Identifier>());
|
2022-08-24 12:36:43 +02:00
|
|
|
}
|
2023-05-20 23:48:26 +02:00
|
|
|
case NodeKind::LParen:
|
2022-08-26 22:10:18 +02:00
|
|
|
{
|
|
|
|
Tokens.get();
|
|
|
|
auto E = parseExpression();
|
2023-05-20 23:48:26 +02:00
|
|
|
auto T2 = static_cast<RParen*>(expectToken(NodeKind::RParen));
|
2022-08-26 22:10:18 +02:00
|
|
|
return new NestedExpression(static_cast<LParen*>(T0), E, T2);
|
|
|
|
}
|
2023-05-21 11:30:25 +02:00
|
|
|
case NodeKind::MatchKeyword:
|
|
|
|
{
|
|
|
|
Tokens.get();
|
|
|
|
auto T1 = Tokens.peek();
|
|
|
|
Expression* Value = nullptr;
|
|
|
|
BlockStart* BlockStart;
|
|
|
|
if (llvm::isa<class BlockStart>(T1)) {
|
|
|
|
BlockStart = static_cast<class BlockStart*>(T1);
|
|
|
|
} else {
|
|
|
|
Value = parseExpression();
|
|
|
|
BlockStart = expectToken<class BlockStart>();
|
|
|
|
}
|
|
|
|
std::vector<MatchCase*> Cases;
|
|
|
|
for (;;) {
|
|
|
|
auto T2 = Tokens.peek();
|
|
|
|
if (llvm::isa<BlockEnd>(T2)) {
|
|
|
|
Tokens.get();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
auto Pattern = parsePattern();
|
|
|
|
auto RArrowAlt = expectToken<class RArrowAlt>();
|
|
|
|
auto Expression = parseExpression();
|
|
|
|
expectToken<LineFoldEnd>();
|
|
|
|
Cases.push_back(new MatchCase { Pattern, RArrowAlt, Expression });
|
|
|
|
}
|
|
|
|
return new MatchExpression(static_cast<MatchKeyword*>(T0), Value, BlockStart, Cases);
|
|
|
|
}
|
2023-05-20 23:48:26 +02:00
|
|
|
case NodeKind::IntegerLiteral:
|
|
|
|
case NodeKind::StringLiteral:
|
2022-08-19 19:52:57 +02:00
|
|
|
Tokens.get();
|
|
|
|
return new ConstantExpression(T0);
|
|
|
|
default:
|
2023-05-20 23:48:26 +02:00
|
|
|
throw UnexpectedTokenDiagnostic(File, T0, std::vector { NodeKind::Identifier, NodeKind::IntegerLiteral, NodeKind::StringLiteral });
|
2022-08-19 19:52:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-21 16:25:52 +02:00
|
|
|
Expression* Parser::parseCallExpression() {
|
|
|
|
auto Operator = parsePrimitiveExpression();
|
|
|
|
std::vector<Expression*> Args;
|
|
|
|
for (;;) {
|
|
|
|
auto T1 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T1->getKind() == NodeKind::LineFoldEnd || T1->getKind() == NodeKind::RParen || T1->getKind() == NodeKind::BlockStart || ExprOperators.isInfix(T1)) {
|
2022-08-21 16:25:52 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
Args.push_back(parsePrimitiveExpression());
|
|
|
|
}
|
|
|
|
if (Args.empty()) {
|
|
|
|
return Operator;
|
|
|
|
}
|
|
|
|
return new CallExpression(Operator, Args);
|
|
|
|
}
|
|
|
|
|
|
|
|
Expression* Parser::parseUnaryExpression() {
|
|
|
|
std::vector<Token*> Prefix;
|
|
|
|
for (;;) {
|
|
|
|
auto T0 = Tokens.peek();
|
|
|
|
if (!ExprOperators.isPrefix(T0)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Tokens.get();
|
|
|
|
Prefix.push_back(T0);
|
|
|
|
}
|
|
|
|
auto E = parseCallExpression();
|
|
|
|
for (auto Iter = Prefix.rbegin(); Iter != Prefix.rend(); Iter++) {
|
2023-05-20 23:48:26 +02:00
|
|
|
E = new PrefixExpression(*Iter, E);
|
2022-08-21 16:25:52 +02:00
|
|
|
}
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
Expression* Parser::parseInfixOperatorAfterExpression(Expression* LHS, int MinPrecedence) {
|
|
|
|
for (;;) {
|
|
|
|
auto T0 = Tokens.peek();
|
|
|
|
auto Info0 = ExprOperators.getInfix(T0);
|
|
|
|
if (!Info0 || Info0->Precedence < MinPrecedence) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Tokens.get();
|
|
|
|
auto RHS = parseUnaryExpression();
|
|
|
|
for (;;) {
|
|
|
|
auto T1 = Tokens.peek();
|
|
|
|
auto Info1 = ExprOperators.getInfix(T1);
|
|
|
|
if (!Info1 || Info1->Precedence < Info0->Precedence && (Info1->Precedence > Info0->Precedence || Info1->isRightAssoc())) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
RHS = parseInfixOperatorAfterExpression(RHS, Info1->Precedence);
|
|
|
|
}
|
|
|
|
LHS = new InfixExpression(LHS, T0, RHS);
|
|
|
|
}
|
|
|
|
return LHS;
|
|
|
|
}
|
|
|
|
|
|
|
|
Expression* Parser::parseExpression() {
|
|
|
|
return parseInfixOperatorAfterExpression(parseUnaryExpression(), 0);
|
|
|
|
}
|
|
|
|
|
2022-08-19 19:52:57 +02:00
|
|
|
ExpressionStatement* Parser::parseExpressionStatement() {
|
|
|
|
auto E = parseExpression();
|
|
|
|
BOLT_EXPECT_TOKEN(LineFoldEnd);
|
|
|
|
return new ExpressionStatement(E);
|
|
|
|
}
|
|
|
|
|
2022-08-25 23:04:09 +02:00
|
|
|
ReturnStatement* Parser::parseReturnStatement() {
|
2023-05-20 23:48:26 +02:00
|
|
|
auto T0 = static_cast<ReturnKeyword*>(expectToken(NodeKind::ReturnKeyword));
|
2022-08-25 23:04:09 +02:00
|
|
|
Expression* Expression = nullptr;
|
|
|
|
auto T1 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T1->getKind() != NodeKind::LineFoldEnd) {
|
2022-08-25 23:04:09 +02:00
|
|
|
Expression = parseExpression();
|
|
|
|
}
|
|
|
|
BOLT_EXPECT_TOKEN(LineFoldEnd);
|
|
|
|
return new ReturnStatement(static_cast<ReturnKeyword*>(T0), Expression);
|
|
|
|
}
|
|
|
|
|
|
|
|
IfStatement* Parser::parseIfStatement() {
|
|
|
|
std::vector<IfStatementPart*> Parts;
|
2023-05-20 23:48:26 +02:00
|
|
|
auto T0 = expectToken(NodeKind::IfKeyword);
|
2022-08-25 23:04:09 +02:00
|
|
|
auto Test = parseExpression();
|
2023-05-20 23:48:26 +02:00
|
|
|
auto T1 = static_cast<BlockStart*>(expectToken(NodeKind::BlockStart));
|
2022-08-25 23:04:09 +02:00
|
|
|
std::vector<Node*> Then;
|
|
|
|
for (;;) {
|
|
|
|
auto T2 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T2->getKind() == NodeKind::BlockEnd) {
|
2022-08-25 23:04:09 +02:00
|
|
|
Tokens.get();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Then.push_back(parseLetBodyElement());
|
|
|
|
}
|
|
|
|
Parts.push_back(new IfStatementPart(T0, Test, T1, Then));
|
|
|
|
BOLT_EXPECT_TOKEN(LineFoldEnd)
|
|
|
|
auto T3 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T3->getKind() == NodeKind::ElseKeyword) {
|
2022-08-25 23:04:09 +02:00
|
|
|
Tokens.get();
|
2023-05-20 23:48:26 +02:00
|
|
|
auto T4 = static_cast<BlockStart*>(expectToken(NodeKind::BlockStart));
|
2022-08-25 23:04:09 +02:00
|
|
|
std::vector<Node*> Else;
|
|
|
|
for (;;) {
|
|
|
|
auto T5 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T5->getKind() == NodeKind::BlockEnd) {
|
2022-08-25 23:04:09 +02:00
|
|
|
Tokens.get();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Else.push_back(parseLetBodyElement());
|
|
|
|
}
|
|
|
|
Parts.push_back(new IfStatementPart(T3, nullptr, T4, Else));
|
|
|
|
BOLT_EXPECT_TOKEN(LineFoldEnd)
|
|
|
|
}
|
|
|
|
return new IfStatement(Parts);
|
|
|
|
}
|
|
|
|
|
2022-08-19 19:52:57 +02:00
|
|
|
LetDeclaration* Parser::parseLetDeclaration() {
|
|
|
|
|
2022-08-24 20:57:26 +02:00
|
|
|
PubKeyword* Pub = nullptr;
|
2022-08-19 19:52:57 +02:00
|
|
|
LetKeyword* Let;
|
2022-08-24 20:57:26 +02:00
|
|
|
MutKeyword* Mut = nullptr;
|
2022-08-19 19:52:57 +02:00
|
|
|
auto T0 = Tokens.get();
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T0->getKind() == NodeKind::PubKeyword) {
|
2022-08-19 19:52:57 +02:00
|
|
|
Pub = static_cast<PubKeyword*>(T0);
|
|
|
|
T0 = Tokens.get();
|
|
|
|
}
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T0->getKind() != NodeKind::LetKeyword) {
|
|
|
|
throw UnexpectedTokenDiagnostic(File, T0, std::vector { NodeKind::LetKeyword });
|
2022-08-19 19:52:57 +02:00
|
|
|
}
|
|
|
|
Let = static_cast<LetKeyword*>(T0);
|
|
|
|
auto T1 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T1->getKind() == NodeKind::MutKeyword) {
|
2022-08-19 19:52:57 +02:00
|
|
|
Mut = static_cast<MutKeyword*>(T1);
|
|
|
|
Tokens.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto Patt = parsePattern();
|
|
|
|
|
2023-05-20 23:48:26 +02:00
|
|
|
std::vector<Parameter*> Params;
|
2022-08-19 19:52:57 +02:00
|
|
|
Token* T2;
|
|
|
|
for (;;) {
|
|
|
|
T2 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
switch (T2->getKind()) {
|
|
|
|
case NodeKind::LineFoldEnd:
|
|
|
|
case NodeKind::BlockStart:
|
|
|
|
case NodeKind::Equals:
|
|
|
|
case NodeKind::Colon:
|
2022-08-19 19:52:57 +02:00
|
|
|
goto after_params;
|
|
|
|
default:
|
2023-05-20 23:48:26 +02:00
|
|
|
Params.push_back(new Parameter(parsePattern(), nullptr));
|
2022-08-19 19:52:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
after_params:
|
|
|
|
|
|
|
|
TypeAssert* TA = nullptr;
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T2->getKind() == NodeKind::Colon) {
|
2022-08-19 19:52:57 +02:00
|
|
|
Tokens.get();
|
|
|
|
auto TE = parseTypeExpression();
|
|
|
|
TA = new TypeAssert(static_cast<Colon*>(T2), TE);
|
|
|
|
T2 = Tokens.peek();
|
|
|
|
}
|
|
|
|
|
|
|
|
LetBody* Body;
|
2023-05-20 23:48:26 +02:00
|
|
|
switch (T2->getKind()) {
|
|
|
|
case NodeKind::BlockStart:
|
2022-08-19 19:52:57 +02:00
|
|
|
{
|
|
|
|
Tokens.get();
|
2022-08-21 16:25:52 +02:00
|
|
|
std::vector<Node*> Elements;
|
2022-08-19 19:52:57 +02:00
|
|
|
for (;;) {
|
|
|
|
auto T3 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T3->getKind() == NodeKind::BlockEnd) {
|
2022-08-19 19:52:57 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
Elements.push_back(parseLetBodyElement());
|
|
|
|
}
|
|
|
|
Tokens.get();
|
|
|
|
Body = new LetBlockBody(static_cast<BlockStart*>(T2), Elements);
|
|
|
|
break;
|
|
|
|
}
|
2023-05-20 23:48:26 +02:00
|
|
|
case NodeKind::Equals:
|
2022-08-19 19:52:57 +02:00
|
|
|
Tokens.get();
|
|
|
|
Body = new LetExprBody(static_cast<Equals*>(T2), parseExpression());
|
|
|
|
break;
|
2023-05-20 23:48:26 +02:00
|
|
|
case NodeKind::LineFoldEnd:
|
2022-08-19 19:52:57 +02:00
|
|
|
Body = nullptr;
|
|
|
|
break;
|
|
|
|
default:
|
2023-05-20 23:48:26 +02:00
|
|
|
std::vector<NodeKind> Expected { NodeKind::BlockStart, NodeKind::LineFoldEnd, NodeKind::Equals };
|
2022-08-19 19:52:57 +02:00
|
|
|
if (TA == nullptr) {
|
|
|
|
// First tokens of TypeAssert
|
2023-05-20 23:48:26 +02:00
|
|
|
Expected.push_back(NodeKind::Colon);
|
2022-08-19 19:52:57 +02:00
|
|
|
// First tokens of Pattern
|
2023-05-20 23:48:26 +02:00
|
|
|
Expected.push_back(NodeKind::Identifier);
|
2022-08-19 19:52:57 +02:00
|
|
|
}
|
2022-08-24 20:57:26 +02:00
|
|
|
throw UnexpectedTokenDiagnostic(File, T2, Expected);
|
2022-08-19 19:52:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BOLT_EXPECT_TOKEN(LineFoldEnd);
|
|
|
|
|
|
|
|
return new LetDeclaration(
|
|
|
|
Pub,
|
|
|
|
Let,
|
|
|
|
Mut,
|
|
|
|
Patt,
|
|
|
|
Params,
|
|
|
|
TA,
|
|
|
|
Body
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-08-21 16:25:52 +02:00
|
|
|
Node* Parser::parseLetBodyElement() {
|
2022-08-19 19:52:57 +02:00
|
|
|
auto T0 = peekFirstTokenAfterModifiers();
|
2023-05-20 23:48:26 +02:00
|
|
|
switch (T0->getKind()) {
|
|
|
|
case NodeKind::LetKeyword:
|
2022-08-19 19:52:57 +02:00
|
|
|
return parseLetDeclaration();
|
2023-05-20 23:48:26 +02:00
|
|
|
case NodeKind::ReturnKeyword:
|
2022-08-25 23:04:09 +02:00
|
|
|
return parseReturnStatement();
|
2023-05-20 23:48:26 +02:00
|
|
|
case NodeKind::IfKeyword:
|
2022-08-25 23:04:09 +02:00
|
|
|
return parseIfStatement();
|
2022-08-19 19:52:57 +02:00
|
|
|
default:
|
|
|
|
return parseExpressionStatement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-20 23:48:26 +02:00
|
|
|
ConstraintExpression* Parser::parseConstraintExpression() {
|
|
|
|
bool HasTilde = false;
|
|
|
|
for (std::size_t I = 0; ; I++) {
|
|
|
|
auto Tok = Tokens.peek(I);
|
|
|
|
switch (Tok->getKind()) {
|
|
|
|
case NodeKind::Tilde:
|
|
|
|
HasTilde = true;
|
|
|
|
goto after_seek;
|
|
|
|
case NodeKind::RParen:
|
|
|
|
case NodeKind::Comma:
|
|
|
|
case NodeKind::RArrowAlt:
|
|
|
|
case NodeKind::EndOfFile:
|
|
|
|
goto after_seek;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
after_seek:
|
|
|
|
if (HasTilde) {
|
|
|
|
auto Left = parseArrowTypeExpression();
|
|
|
|
auto Tilde = expectToken<class Tilde>();
|
|
|
|
auto Right = parseArrowTypeExpression();
|
|
|
|
return new EqualityConstraintExpression { Left, Tilde, Right };
|
|
|
|
}
|
|
|
|
auto Name = expectToken<Identifier>();
|
|
|
|
std::vector<VarTypeExpression*> TEs;
|
|
|
|
for (;;) {
|
|
|
|
auto T1 = Tokens.peek();
|
|
|
|
switch (T1->getKind()) {
|
|
|
|
case NodeKind::RParen:
|
|
|
|
case NodeKind::RArrowAlt:
|
|
|
|
case NodeKind::Comma:
|
|
|
|
goto after_vars;
|
|
|
|
case NodeKind::Identifier:
|
|
|
|
Tokens.get();
|
|
|
|
TEs.push_back(new VarTypeExpression { static_cast<Identifier*>(T1) });
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw UnexpectedTokenDiagnostic(File, T1, std::vector { NodeKind::RParen, NodeKind::RArrowAlt, NodeKind::Comma, NodeKind::Identifier });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
after_vars:
|
|
|
|
return new TypeclassConstraintExpression { Name, TEs };
|
|
|
|
}
|
|
|
|
|
|
|
|
VarTypeExpression* Parser::parseVarTypeExpression() {
|
|
|
|
auto Name = expectToken<Identifier>();
|
|
|
|
// TODO reject constructor symbols (starting with a capital letter)
|
|
|
|
return new VarTypeExpression { Name };
|
|
|
|
}
|
|
|
|
|
|
|
|
InstanceDeclaration* Parser::parseInstanceDeclaration() {
|
|
|
|
auto InstanceKeyword = expectToken<class InstanceKeyword>();
|
2023-05-21 00:25:01 +02:00
|
|
|
auto Name = expectToken<IdentifierAlt>();
|
2023-05-20 23:48:26 +02:00
|
|
|
std::vector<TypeExpression*> TypeExps;
|
|
|
|
for (;;) {
|
|
|
|
auto T1 = Tokens.peek();
|
|
|
|
if (T1->is<BlockStart>()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
TypeExps.push_back(parseTypeExpression());
|
|
|
|
}
|
|
|
|
auto BlockStart = expectToken<class BlockStart>();
|
|
|
|
std::vector<Node*> Elements;
|
|
|
|
for (;;) {
|
|
|
|
auto T2 = Tokens.peek();
|
|
|
|
if (T2->is<BlockEnd>()) {
|
|
|
|
Tokens.get();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Elements.push_back(parseClassElement());
|
|
|
|
}
|
|
|
|
expectToken(NodeKind::LineFoldEnd);
|
|
|
|
return new InstanceDeclaration(
|
|
|
|
InstanceKeyword,
|
|
|
|
Name,
|
|
|
|
TypeExps,
|
|
|
|
BlockStart,
|
|
|
|
Elements
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassDeclaration* Parser::parseClassDeclaration() {
|
|
|
|
PubKeyword* PubKeyword = nullptr;
|
|
|
|
auto T0 = Tokens.peek();
|
|
|
|
if (T0->getKind() == NodeKind::PubKeyword) {
|
|
|
|
Tokens.get();
|
|
|
|
PubKeyword = static_cast<class PubKeyword*>(T0);
|
|
|
|
}
|
|
|
|
auto ClassKeyword = expectToken<class ClassKeyword>();
|
2023-05-21 00:25:01 +02:00
|
|
|
auto Name = expectToken<IdentifierAlt>();
|
2023-05-20 23:48:26 +02:00
|
|
|
std::vector<VarTypeExpression*> TypeVars;
|
|
|
|
for (;;) {
|
|
|
|
auto T2 = Tokens.peek();
|
|
|
|
if (T2->getKind() == NodeKind::BlockStart) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
TypeVars.push_back(parseVarTypeExpression());
|
|
|
|
}
|
|
|
|
auto BlockStart = expectToken<class BlockStart>();
|
|
|
|
std::vector<Node*> Elements;
|
|
|
|
for (;;) {
|
|
|
|
auto T2 = Tokens.peek();
|
|
|
|
if (T2->is<BlockEnd>()) {
|
|
|
|
Tokens.get();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Elements.push_back(parseClassElement());
|
|
|
|
}
|
|
|
|
expectToken(NodeKind::LineFoldEnd);
|
|
|
|
return new ClassDeclaration(
|
|
|
|
PubKeyword,
|
|
|
|
ClassKeyword,
|
|
|
|
Name,
|
|
|
|
TypeVars,
|
|
|
|
BlockStart,
|
|
|
|
Elements
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Node* Parser::parseClassElement() {
|
|
|
|
auto T0 = Tokens.peek();
|
|
|
|
switch (T0->getKind()) {
|
|
|
|
case NodeKind::LetKeyword:
|
|
|
|
return parseLetDeclaration();
|
|
|
|
case NodeKind::TypeKeyword:
|
|
|
|
// TODO
|
|
|
|
default:
|
|
|
|
throw UnexpectedTokenDiagnostic(File, T0, std::vector<NodeKind> { NodeKind::LetKeyword, NodeKind::TypeKeyword });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-21 16:25:52 +02:00
|
|
|
Node* Parser::parseSourceElement() {
|
2022-08-19 19:52:57 +02:00
|
|
|
auto T0 = peekFirstTokenAfterModifiers();
|
2023-05-20 23:48:26 +02:00
|
|
|
switch (T0->getKind()) {
|
|
|
|
case NodeKind::LetKeyword:
|
2022-08-19 19:52:57 +02:00
|
|
|
return parseLetDeclaration();
|
2023-05-20 23:48:26 +02:00
|
|
|
case NodeKind::IfKeyword:
|
2022-08-25 23:04:09 +02:00
|
|
|
return parseIfStatement();
|
2023-05-20 23:48:26 +02:00
|
|
|
case NodeKind::ClassKeyword:
|
|
|
|
return parseClassDeclaration();
|
|
|
|
case NodeKind::InstanceKeyword:
|
|
|
|
return parseInstanceDeclaration();
|
2022-08-19 19:52:57 +02:00
|
|
|
default:
|
|
|
|
return parseExpressionStatement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceFile* Parser::parseSourceFile() {
|
2022-08-21 16:25:52 +02:00
|
|
|
std::vector<Node*> Elements;
|
2022-08-19 19:52:57 +02:00
|
|
|
for (;;) {
|
|
|
|
auto T0 = Tokens.peek();
|
2023-05-20 23:48:26 +02:00
|
|
|
if (T0->is<EndOfFile>()) {
|
2022-08-19 19:52:57 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
Elements.push_back(parseSourceElement());
|
|
|
|
}
|
2022-08-24 12:36:43 +02:00
|
|
|
return new SourceFile(File, Elements);
|
2022-08-19 19:52:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|