-
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
libnixf: remove green node design (#291)
- Loading branch information
Showing
60 changed files
with
449 additions
and
3,578 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
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 |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/// \file | ||
/// \brief AST nodes. | ||
/// | ||
/// Declares the AST nodes used by the parser, the nodes may be used in latter | ||
/// stages, for example semantic analysis. | ||
/// It is expected that they may share some nodes, so they are reference | ||
/// counted. | ||
|
||
#pragma once | ||
|
||
#include "nixf/Basic/Range.h" | ||
|
||
#include <cassert> | ||
#include <memory> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace nixf { | ||
|
||
class Node { | ||
public: | ||
enum NodeKind { | ||
NK_InterpolableParts, | ||
NK_BeginExpr, | ||
NK_ExprInt, | ||
NK_ExprFloat, | ||
NK_EndExpr, | ||
}; | ||
|
||
private: | ||
NodeKind Kind; | ||
OffsetRange Range; | ||
|
||
protected: | ||
explicit Node(NodeKind Kind, OffsetRange Range) : Kind(Kind), Range(Range) {} | ||
|
||
public: | ||
NodeKind getKind() { return Kind; } | ||
OffsetRange getRange() { return Range; } | ||
}; | ||
|
||
class Expr : public Node { | ||
protected: | ||
explicit Expr(NodeKind Kind, OffsetRange Range) : Node(Kind, Range) { | ||
assert(NK_BeginExpr <= Kind && Kind <= NK_EndExpr); | ||
} | ||
}; | ||
|
||
using NixInt = int64_t; | ||
using NixFloat = double; | ||
|
||
class ExprInt : public Expr { | ||
NixInt Value; | ||
|
||
public: | ||
ExprInt(OffsetRange Range, NixInt Value) | ||
: Expr(NK_ExprInt, Range), Value(Value) {} | ||
[[nodiscard]] NixInt getValue() const { return Value; } | ||
}; | ||
|
||
class ExprFloat : public Expr { | ||
NixFloat Value; | ||
|
||
public: | ||
ExprFloat(OffsetRange Range, NixFloat Value) | ||
: Expr(NK_ExprFloat, Range), Value(Value) {} | ||
[[nodiscard]] NixFloat getValue() const { return Value; } | ||
}; | ||
|
||
class StringPart { | ||
enum StringPartKind { | ||
SPK_Escaped, | ||
SPK_Interpolation, | ||
} Kind; | ||
std::string Escaped; | ||
std::shared_ptr<Expr> Interpolation; | ||
|
||
public: | ||
explicit StringPart(std::string Escaped) | ||
: Kind(SPK_Escaped), Escaped(std::move(Escaped)), Interpolation(nullptr) { | ||
} | ||
|
||
explicit StringPart(std::shared_ptr<Expr> Expr) | ||
: Kind(SPK_Interpolation), Interpolation(std::move(Expr)) {} | ||
|
||
StringPartKind getKind() { return Kind; } | ||
}; | ||
|
||
class InterpolatedParts : public Node { | ||
std::vector<StringPart> Fragments; | ||
|
||
public: | ||
InterpolatedParts(OffsetRange Range, std::vector<StringPart> Fragments) | ||
: Node(NK_InterpolableParts, Range), Fragments(std::move(Fragments)) {} | ||
}; | ||
|
||
} // namespace nixf |
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,151 +1,20 @@ | ||
#include "nixf/Basic/DiagnosticEngine.h" | ||
#include "nixf/Lex/Lexer.h" | ||
#include "nixf/Syntax/RawSyntax.h" | ||
#include "nixf/Syntax/Token.h" | ||
/// \file | ||
/// \brief Parser interface. | ||
/// | ||
/// libnixf parser. This is a recursive descent parser, focusing on error | ||
/// recovery. | ||
#pragma once | ||
|
||
#include <limits> | ||
#include <map> | ||
#include <queue> | ||
#include <memory> | ||
#include <string_view> | ||
|
||
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]; | ||
} | ||
class Node; | ||
class DiagnosticEngine; | ||
|
||
~GuardTokensRAII() { | ||
assert(GuardTokens[Kind] > 0); | ||
--GuardTokens[Kind]; | ||
} | ||
|
||
tok::TokenKind Kind; | ||
GuardTokensTy &GuardTokens; | ||
}; | ||
|
||
class ExprSyntax; | ||
class Parser { | ||
std::string_view Src; | ||
Lexer Lex; | ||
RawTwineBuilder Builder; | ||
DiagnosticEngine &Diag; | ||
|
||
/// These tokens should not be consumed as unknown nodes from error recovery. | ||
friend struct GuardTokensRAII; | ||
GuardTokensTy GuardTokens; | ||
|
||
std::deque<TokenAbs> LookAheadBuf; | ||
|
||
std::optional<TokenView> LastToken; | ||
|
||
TokenView peek(std::size_t N = 0, TokenAbs (Lexer::*Ptr)() = &Lexer::lex) { | ||
while (N >= LookAheadBuf.size()) { | ||
LookAheadBuf.emplace_back((Lex.*Ptr)()); | ||
} | ||
return LookAheadBuf[N]; | ||
} | ||
|
||
void consume() { | ||
if (LookAheadBuf.empty()) | ||
peek(0); | ||
Builder.push(LookAheadBuf.front().take()); | ||
popFront(); | ||
} | ||
|
||
std::unique_ptr<Token> popFront() { | ||
LastToken = LookAheadBuf.front(); | ||
std::unique_ptr<Token> Ptr = LookAheadBuf.front().take(); | ||
LookAheadBuf.pop_front(); | ||
return Ptr; | ||
} | ||
|
||
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<RawNode> (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<RawNode> Expr); | ||
|
||
// Concret n-terms. | ||
std::unique_ptr<RawNode> parseInterpolation(); | ||
|
||
std::unique_ptr<RawNode> parseStringParts(); | ||
std::unique_ptr<RawNode> parseString(); | ||
|
||
std::unique_ptr<RawNode> parseIndString(); | ||
std::unique_ptr<RawNode> parseIndStringParts(); | ||
|
||
std::unique_ptr<RawNode> parsePath(); | ||
std::unique_ptr<RawNode> parseAttrPath(); | ||
std::unique_ptr<RawNode> parseAttrName(); | ||
std::unique_ptr<RawNode> parseBinding(); | ||
std::unique_ptr<RawNode> parseInherit(); | ||
std::unique_ptr<RawNode> parseBinds(); | ||
std::unique_ptr<RawNode> parseAttrSetExpr(); | ||
std::unique_ptr<RawNode> parseParenExpr(); | ||
std::unique_ptr<RawNode> parseLegacyLet(); | ||
std::unique_ptr<RawNode> parseListExpr(); | ||
std::unique_ptr<RawNode> parseListBody(); | ||
|
||
std::unique_ptr<RawNode> parseFormal(); | ||
std::unique_ptr<RawNode> parseFormals(); | ||
std::unique_ptr<RawNode> parseBracedFormals(); | ||
std::unique_ptr<RawNode> parseLambdaArg(); | ||
std::unique_ptr<RawNode> parseLambdaExpr(); | ||
|
||
std::unique_ptr<RawNode> parseIfExpr(); | ||
std::unique_ptr<RawNode> parseAssertExpr(); | ||
std::unique_ptr<RawNode> parseWithExpr(); | ||
std::unique_ptr<RawNode> parseLetInExpr(); | ||
|
||
// Abstract level, these functions may return nullptr. | ||
std::unique_ptr<RawNode> parseExprSelect(); | ||
std::unique_ptr<RawNode> parseExprSimple(); | ||
|
||
/// Parse expr_app | ||
/// \p Limit of expr_select should be consumed, default to +inf | ||
std::unique_ptr<RawNode> | ||
parseExprApp(unsigned Limit = std::numeric_limits<unsigned>::max()); | ||
|
||
std::unique_ptr<RawNode> 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<RawNode> parseExprOpBP(unsigned LeftRBP); | ||
|
||
std::unique_ptr<RawNode> parseExpr(); | ||
|
||
/// Create an "Unknown" with many tokens until \p Predicate does not hold | ||
std::unique_ptr<RawNode> 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<RawNode> parse(); | ||
}; | ||
/// \brief Parse a string. | ||
/// \param Diag Diagnostics will be written here. | ||
std::shared_ptr<Node> parse(std::string_view Src, DiagnosticEngine &Diag); | ||
|
||
} // namespace nixf |
File renamed without changes.
Oops, something went wrong.