#include "bolt/CST.hpp" #include "bolt/Scanner.hpp" #include "bolt/Parser.hpp" #include "bolt/Diagnostics.hpp" namespace bolt { Parser::Parser(Stream& S): Tokens(S) {} Token* Parser::peekFirstTokenAfterModifiers() { std::size_t I = 0; for (;;) { auto T0 = Tokens.peek(I++); switch (T0->Type) { case NodeType::PubKeyword: case NodeType::MutKeyword: continue; default: return T0; } } } #define BOLT_EXPECT_TOKEN(name) \ { \ auto __Token = Tokens.get(); \ if (__Token->Type != NodeType::name) { \ throw UnexpectedTokenDiagnostic(__Token, std::vector { NodeType::name }); \ } \ } Pattern* Parser::parsePattern() { auto T0 = Tokens.peek(); switch (T0->Type) { case NodeType::Identifier: Tokens.get(); return new BindPattern(static_cast(T0)); default: throw UnexpectedTokenDiagnostic(T0, std::vector { NodeType::Identifier }); } } QualifiedName* Parser::parseQualifiedName() { std::vector ModulePath; auto Name = Tokens.get(); if (Name->Type != NodeType::Identifier) { throw UnexpectedTokenDiagnostic(Name, std::vector { NodeType::Identifier }); } for (;;) { auto T1 = Tokens.peek(); if (T1->Type == NodeType::Dot) { break; } Tokens.get(); ModulePath.push_back(static_cast(Name)); Name = Tokens.get(); if (Name->Type != NodeType::Identifier) { throw UnexpectedTokenDiagnostic(Name, std::vector { NodeType::Identifier }); } } return new QualifiedName(ModulePath, static_cast(Name)); } TypeExpression* Parser::parseTypeExpression() { auto T0 = Tokens.peek(); switch (T0->Type) { case NodeType::Identifier: return new ReferenceTypeExpression(parseQualifiedName()); default: throw UnexpectedTokenDiagnostic(T0, std::vector { NodeType::Identifier }); } } Expression* Parser::parseExpression() { auto T0 = Tokens.peek(); switch (T0->Type) { case NodeType::Identifier: Tokens.get(); return new ReferenceExpression(static_cast(T0)); case NodeType::IntegerLiteral: case NodeType::StringLiteral: Tokens.get(); return new ConstantExpression(T0); default: throw UnexpectedTokenDiagnostic(T0, std::vector { NodeType::Identifier, NodeType::IntegerLiteral }); } } ExpressionStatement* Parser::parseExpressionStatement() { auto E = parseExpression(); BOLT_EXPECT_TOKEN(LineFoldEnd); return new ExpressionStatement(E); } LetDeclaration* Parser::parseLetDeclaration() { PubKeyword* Pub; LetKeyword* Let; MutKeyword* Mut; auto T0 = Tokens.get(); if (T0->Type == NodeType::PubKeyword) { Pub = static_cast(T0); T0 = Tokens.get(); } if (T0->Type != NodeType::LetKeyword) { throw UnexpectedTokenDiagnostic(T0, std::vector { NodeType::LetKeyword }); } Let = static_cast(T0); auto T1 = Tokens.peek(); if (T1->Type == NodeType::MutKeyword) { Mut = static_cast(T1); Tokens.get(); } auto Patt = parsePattern(); std::vector Params; Token* T2; for (;;) { T2 = Tokens.peek(); switch (T2->Type) { case NodeType::LineFoldEnd: case NodeType::BlockStart: case NodeType::Equals: case NodeType::Colon: goto after_params; default: Params.push_back(new Param(parsePattern(), nullptr)); } } after_params: TypeAssert* TA = nullptr; if (T2->Type == NodeType::Colon) { Tokens.get(); auto TE = parseTypeExpression(); TA = new TypeAssert(static_cast(T2), TE); T2 = Tokens.peek(); } LetBody* Body; switch (T2->Type) { case NodeType::BlockStart: { Tokens.get(); std::vector Elements; for (;;) { auto T3 = Tokens.peek(); if (T3->Type == NodeType::BlockEnd) { break; } Elements.push_back(parseLetBodyElement()); } Tokens.get(); Body = new LetBlockBody(static_cast(T2), Elements); break; } case NodeType::Equals: Tokens.get(); Body = new LetExprBody(static_cast(T2), parseExpression()); break; case NodeType::LineFoldEnd: Body = nullptr; break; default: std::vector Expected { NodeType::BlockStart, NodeType::LineFoldEnd, NodeType::Equals }; if (TA == nullptr) { // First tokens of TypeAssert Expected.push_back(NodeType::Colon); // First tokens of Pattern Expected.push_back(NodeType::Identifier); } throw UnexpectedTokenDiagnostic(T2, Expected); } BOLT_EXPECT_TOKEN(LineFoldEnd); return new LetDeclaration( Pub, Let, Mut, Patt, Params, TA, Body ); } LetBodyElement* Parser::parseLetBodyElement() { auto T0 = peekFirstTokenAfterModifiers(); switch (T0->Type) { case NodeType::LetKeyword: return parseLetDeclaration(); default: return parseExpressionStatement(); } } SourceElement* Parser::parseSourceElement() { auto T0 = peekFirstTokenAfterModifiers(); switch (T0->Type) { case NodeType::LetKeyword: return parseLetDeclaration(); default: return parseExpressionStatement(); } } SourceFile* Parser::parseSourceFile() { std::vector Elements; for (;;) { auto T0 = Tokens.peek(); if (T0->Type == NodeType::EndOfFile) { break; } Elements.push_back(parseSourceElement()); } return new SourceFile(Elements); } }