nixd
Loading...
Searching...
No Matches
ParseSupport.cpp
Go to the documentation of this file.
1/// \file
2/// \brief Basic supporting functions for parsing.
3
4#include "Parser.h"
5
7#include "nixf/Parse/Parser.h"
8
9using namespace nixf;
10
11Diagnostic &detail::diagNullExpr(std::vector<Diagnostic> &Diags,
12 LexerCursor Loc, std::string As) {
13 Diagnostic &D =
14 Diags.emplace_back(Diagnostic::DK_Expected, LexerCursorRange(Loc));
15 D << std::move(As) + " expression";
16 D.fix("insert dummy expression").edit(TextEdit::mkInsertion(Loc, " expr"));
17 return D;
18}
19
20void Parser::pushState(ParserState NewState) {
21 resetLookAheadBuf();
22 State.push(NewState);
23}
24
25void Parser::popState() {
26 resetLookAheadBuf();
27 State.pop();
28}
29
30Parser::StateRAII Parser::withState(ParserState NewState) {
31 pushState(NewState);
32 return {*this};
33}
34
35Parser::SyncRAII Parser::withSync(TokenKind Kind) { return {*this, Kind}; }
36
37std::shared_ptr<Node> nixf::parse(std::string_view Src,
38 std::vector<Diagnostic> &Diags) {
39 Parser P(Src, Diags);
40 return P.parse();
41}
42
43std::shared_ptr<Expr> nixf::Parser::parse() {
44 auto Expr = parseExpr();
45 if (Token Tok = peek(); Tok.kind() != tok::tok_eof) {
46 // TODO: maybe we'd like to have multiple expressions in a single file.
47 // Report an error.
48 Diags.emplace_back(Diagnostic::DK_UnexpectedText, Tok.range());
49 }
50 return Expr;
51}
52
53void Parser::resetLookAheadBuf() {
54 if (!LookAheadBuf.empty()) {
55 Token Tok = LookAheadBuf.front();
56
57 // Reset the lexer cursor at the beginning of the token.
58 Lex.setCur(Tok.lCur());
59 LookAheadBuf.clear();
60 }
61}
62
63Token Parser::peek(std::size_t N) {
64 while (N >= LookAheadBuf.size()) {
65 switch (State.top()) {
66 case PS_Expr:
67 LookAheadBuf.emplace_back(Lex.lex());
68 break;
69 case PS_String:
70 LookAheadBuf.emplace_back(Lex.lexString());
71 break;
72 case PS_IndString:
73 LookAheadBuf.emplace_back(Lex.lexIndString());
74 break;
75 case PS_Path:
76 LookAheadBuf.emplace_back(Lex.lexPath());
77 break;
78 }
79 }
80 return LookAheadBuf[N];
81}
82
83std::optional<LexerCursorRange> Parser::consumeAsUnknown() {
84 LexerCursor Begin = peek().lCur();
85 bool Consumed = false;
86 for (Token Tok = peek(); Tok.kind() != tok_eof; Tok = peek()) {
87 if (SyncTokens.contains(Tok.kind()))
88 break;
89 Consumed = true;
90 consume();
91 }
92 if (!Consumed)
93 return std::nullopt;
94 assert(LastToken && "LastToken should be set after consume()");
95 return LexerCursorRange{Begin, LastToken->rCur()};
96}
97
98Parser::ExpectResult Parser::expect(TokenKind Kind) {
99 auto Sync = withSync(Kind);
100 if (Token Tok = peek(); Tok.kind() == Kind) {
101 return Tok;
102 }
103 // UNKNOWN ?
104 // ~~~~~~~ consider remove unexpected text
105 if (removeUnexpected()) {
106 if (Token Tok = peek(); Tok.kind() == Kind) {
107 return Tok;
108 }
109 // If the next token is not the expected one, then insert it.
110 // (we have two errors now).
111 }
112 // expected Kind
113 LexerCursor Insert = LastToken ? LastToken->rCur() : peek().lCur();
114 Diagnostic &D =
115 Diags.emplace_back(Diagnostic::DK_Expected, LexerCursorRange(Insert));
116 D << std::string(tok::spelling(Kind));
117 D.fix("insert " + std::string(tok::spelling(Kind)))
118 .edit(TextEdit::mkInsertion(Insert, std::string(tok::spelling(Kind))));
119 return {&D};
120}
Fix & fix(std::string Message)
Definition Diagnostic.h:203
Fix & edit(TextEdit Edit)
Definition Diagnostic.h:65
A point in the source file.
Definition Range.h:57
Token lex()
Definition Lexer.cpp:439
Token lexIndString()
Definition Lexer.cpp:405
Token lexPath()
Definition Lexer.cpp:327
Token lexString()
Definition Lexer.cpp:357
void setCur(const LexerCursor &NewCur)
Reset the cursor at source offset (zero-based indexing)
Definition Lexer.h:126
std::shared_ptr< Expr > parse()
Top-level parsing.
static TextEdit mkInsertion(LexerCursor P, std::string NewText)
Definition Diagnostic.h:35
A token. With it's kind, and the range in source code.
Definition Token.h:55
LexerCursor lCur() const
Definition Token.h:63
tok::TokenKind kind() const
Definition Token.h:65
Parser interface.
Diagnostic & diagNullExpr(std::vector< Diagnostic > &Diags, LexerCursor Loc, std::string As)
constexpr std::string_view spelling(TokenKind Kind)
Definition Token.h:13
std::shared_ptr< Node > parse(std::string_view Src, std::vector< Diagnostic > &Diags)
Parse a string.
Parser for the Nix expression language.