-
-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
libnixf: refactor parser header & remove legacy test
- Loading branch information
Showing
41 changed files
with
164 additions
and
2,987 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,149 +1,11 @@ | ||
#include "Lexer.h" | ||
#include "Nodes.h" | ||
#include "Token.h" | ||
#pragma once | ||
|
||
#include "nixf/Basic/DiagnosticEngine.h" | ||
|
||
#include <limits> | ||
#include <map> | ||
#include <queue> | ||
#include <memory> | ||
|
||
namespace nixf { | ||
|
||
using GuardTokensTy = std::map<tok::TokenKind, std::size_t>; | ||
struct GuardTokensRAII { | ||
GuardTokensRAII(GuardTokensTy &GuardTokens, tok::TokenKind Kind) | ||
: Kind(Kind), GuardTokens(GuardTokens) { | ||
++GuardTokens[Kind]; | ||
} | ||
|
||
~GuardTokensRAII() { | ||
assert(GuardTokens[Kind] > 0); | ||
--GuardTokens[Kind]; | ||
} | ||
|
||
tok::TokenKind Kind; | ||
GuardTokensTy &GuardTokens; | ||
}; | ||
|
||
class ExprSyntax; | ||
class Parser { | ||
std::string_view Src; | ||
Lexer Lex; | ||
DiagnosticEngine &Diag; | ||
|
||
/// These tokens should not be consumed as unknown nodes from error recovery. | ||
friend struct GuardTokensRAII; | ||
GuardTokensTy GuardTokens; | ||
|
||
std::deque<Token> LookAheadBuf; | ||
|
||
std::optional<Token> LastToken; | ||
|
||
Token peek(std::size_t N = 0, Token (Lexer::*Ptr)() = &Lexer::lex) { | ||
while (N >= LookAheadBuf.size()) { | ||
LookAheadBuf.emplace_back((Lex.*Ptr)()); | ||
} | ||
return LookAheadBuf[N]; | ||
} | ||
|
||
void consume() { | ||
if (LookAheadBuf.empty()) | ||
peek(0); | ||
popFront(); | ||
} | ||
|
||
Token popFront() { | ||
LastToken = LookAheadBuf.front(); | ||
LookAheadBuf.pop_front(); | ||
return *LastToken; | ||
} | ||
|
||
void resetCur(const char *NewCur) { | ||
Lex.setCur(NewCur); | ||
LookAheadBuf.clear(); | ||
} | ||
|
||
std::size_t getOffset(const char *Cur) { return Cur - Src.begin(); } | ||
|
||
// Private utilities. | ||
void matchBracket(tok::TokenKind LeftKind, | ||
std::unique_ptr<Node> (Parser::*InnerParse)(), | ||
tok::TokenKind RightKind); | ||
|
||
void addExprWithCheck(std::string As) { | ||
return addExprWithCheck(std::move(As), parseExpr()); | ||
} | ||
|
||
/// Check if \p Expr is nullptr. | ||
/// Emit diagnostic if so. | ||
void addExprWithCheck(std::string As, std::unique_ptr<Node> Expr); | ||
|
||
// Concret n-terms. | ||
std::unique_ptr<Expr> parseInterpolation(); | ||
|
||
std::unique_ptr<Node> parseStringParts(); | ||
std::unique_ptr<Node> parseString(); | ||
|
||
std::unique_ptr<Node> parseIndString(); | ||
std::unique_ptr<Node> parseIndStringParts(); | ||
|
||
std::unique_ptr<Node> parsePath(); | ||
std::unique_ptr<Node> parseAttrPath(); | ||
std::unique_ptr<Node> parseAttrName(); | ||
std::unique_ptr<Node> parseBinding(); | ||
std::unique_ptr<Node> parseInherit(); | ||
std::unique_ptr<Node> parseBinds(); | ||
std::unique_ptr<Node> parseAttrSetExpr(); | ||
std::unique_ptr<Node> parseParenExpr(); | ||
std::unique_ptr<Node> parseLegacyLet(); | ||
std::unique_ptr<Node> parseListExpr(); | ||
std::unique_ptr<Node> parseListBody(); | ||
|
||
std::unique_ptr<Node> parseFormal(); | ||
std::unique_ptr<Node> parseFormals(); | ||
std::unique_ptr<Node> parseBracedFormals(); | ||
std::unique_ptr<Node> parseLambdaArg(); | ||
std::unique_ptr<Node> parseLambdaExpr(); | ||
|
||
std::unique_ptr<Node> parseIfExpr(); | ||
std::unique_ptr<Node> parseAssertExpr(); | ||
std::unique_ptr<Node> parseWithExpr(); | ||
std::unique_ptr<Node> parseLetInExpr(); | ||
|
||
// Abstract level, these functions may return nullptr. | ||
std::unique_ptr<Node> parseExprSelect(); | ||
std::unique_ptr<Node> parseExprSimple(); | ||
|
||
/// Parse expr_app | ||
/// \p Limit of expr_select should be consumed, default to +inf | ||
std::unique_ptr<Node> | ||
parseExprApp(unsigned Limit = std::numeric_limits<unsigned>::max()); | ||
|
||
std::unique_ptr<Node> parseExprOp() { return parseExprOpBP(0); } | ||
|
||
/// \note Pratt Parser. | ||
/// Pratt, Vaughan. "Top down operator precedence." | ||
/// Proceedings of the 1st Annual ACM SIGACT-SIGPLAN Symposium on Principles | ||
/// of Programming Languages (1973). | ||
/// https://web.archive.org/web/20151223215421/http://hall.org.ua/halls/wizzard/pdf/Vaughan.Pratt.TDOP.pdf | ||
/// \returns expr_op | ||
std::unique_ptr<Node> parseExprOpBP(unsigned LeftRBP); | ||
|
||
std::unique_ptr<Expr> parseExpr(); | ||
|
||
/// Create an "Unknown" with many tokens until \p Predicate does not hold | ||
std::unique_ptr<Node> parseUnknownUntilGuard(); | ||
|
||
public: | ||
explicit Parser(std::string_view Src, DiagnosticEngine &Diag) | ||
: Src(Src), Lex(Src, Diag), Diag(Diag) {} | ||
|
||
/// \brief Top-level parsing. | ||
/// \returns a "ROOT" node | ||
/// printing this node will exactly get the source file. | ||
/// \note non-null | ||
std::unique_ptr<Node> parse(); | ||
}; | ||
class Node; | ||
class DiagnosticEngine; | ||
std::unique_ptr<Node> parse(std::string_view Src, DiagnosticEngine &Diag); | ||
|
||
} // namespace nixf |
Oops, something went wrong.