nixd
Toggle main menu visibility
Loading...
Searching...
No Matches
libnixf
src
Parse
ParseAttrs.cpp
Go to the documentation of this file.
1
#include "
Parser.h
"
2
3
using namespace
nixf
;
4
using namespace
detail
;
5
6
std::shared_ptr<AttrName>
Parser::parseAttrName
() {
7
switch
(
Token
Tok = peek(); Tok.
kind
()) {
8
case
tok_kw_or:
9
Diags.emplace_back(Diagnostic::DK_OrIdentifier, Tok.range());
10
[[fallthrough]];
11
case
tok_id: {
12
consume();
13
auto
ID =
14
std::make_shared<Identifier>(Tok.range(), std::string(Tok.view()));
15
return
std::make_shared<AttrName>(std::move(ID), Tok.range());
16
}
17
case
tok_dquote: {
18
std::shared_ptr<ExprString> String =
parseString
(
/*IsIndented=*/
false
);
19
return
std::make_shared<AttrName>(std::move(String));
20
}
21
case
tok_dollar_curly: {
22
std::shared_ptr<Interpolation>
Expr
=
parseInterpolation
();
23
return
std::make_shared<AttrName>(std::move(
Expr
));
24
}
25
default
:
26
return
nullptr
;
27
}
28
}
29
30
std::shared_ptr<AttrPath>
Parser::parseAttrPath
() {
31
auto
First =
parseAttrName
();
32
if
(!First)
33
return
nullptr
;
34
LexerCursor
Begin = First->lCur();
35
assert(LastToken &&
"LastToken should be set after valid attrname"
);
36
std::vector<std::shared_ptr<AttrName>> AttrNames;
37
const
AttrName
*PrevName = First.get();
38
const
AttrName
*NextName =
nullptr
;
39
AttrNames.emplace_back(std::move(First));
40
std::vector<std::shared_ptr<Dot>> Dots;
41
auto
SyncDot = withSync(tok_dot);
42
while
(
true
) {
43
if
(
Token
Tok = peek(); Tok.
kind
() == tok_dot) {
44
consume();
45
auto
Next =
parseAttrName
();
46
NextName = Next.get();
47
// Make a "dot" node.
48
auto
Do = std::make_shared<Dot>(Tok.range(), PrevName, NextName);
49
// Only update "PrevName" if "Next" is not nullptr.
50
// More information could be obtained by those dots.
51
if
(NextName)
52
PrevName = NextName;
53
Dots.emplace_back(std::move(Do));
54
if
(!Next) {
55
// extra ".", consider remove it.
56
Diagnostic
&D =
57
Diags.emplace_back(Diagnostic::DK_AttrPathExtraDot, Tok.range());
58
D.
fix
(
"remove extra ."
).
edit
(
TextEdit::mkRemoval
(Tok.range()));
59
D.
fix
(
"insert dummy attrname"
)
60
.
edit
(
TextEdit::mkInsertion
(Tok.rCur(), R
"("dummy")"));
61
continue
;
62
}
63
AttrNames.emplace_back(std::move(Next));
64
continue
;
65
}
66
break
;
67
}
68
return
std::make_shared<AttrPath>(
LexerCursorRange
{Begin, LastToken->rCur()},
69
std::move(AttrNames), std::move(Dots));
70
}
71
72
std::shared_ptr<Binding>
Parser::parseBinding
() {
73
auto
Path =
parseAttrPath
();
74
if
(!Path)
75
return
nullptr
;
76
assert(LastToken &&
"LastToken should be set after valid attrpath"
);
77
auto
SyncEq = withSync(tok_eq);
78
auto
SyncSemi = withSync(tok_semi_colon);
79
ExpectResult ExpTokEq = expect(tok_eq);
80
if
(!ExpTokEq.ok())
81
return
std::make_shared<Binding>(
82
LexerCursorRange
{Path->lCur(), LastToken->rCur()}, std::move(Path),
83
nullptr
,
nullptr
);
84
consume();
85
auto
TokEq = std::make_shared<Misc>(ExpTokEq.tok().
range
());
86
auto
Expr
=
parseExpr
();
87
if
(!
Expr
)
88
diagNullExpr
(Diags, LastToken->rCur(),
"binding"
);
89
if
(
Token
Tok = peek(); Tok.
kind
() == tok_semi_colon) {
90
consume();
91
}
else
{
92
// TODO: reset the cursor for error recovery.
93
// (https://github.com/nix-community/nixd/blob/2b0ca8cef0d13823132a52b6cd6f6d7372482664/libnixf/lib/Parse/Parser.cpp#L337)
94
// expected ";" for binding
95
Diagnostic
&D = Diags.emplace_back(Diagnostic::DK_Expected,
96
LexerCursorRange
(LastToken->rCur()));
97
D << std::string(tok::spelling(tok_semi_colon));
98
D.
fix
(
"insert ;"
).
edit
(
TextEdit::mkInsertion
(LastToken->rCur(),
";"
));
99
}
100
return
std::make_shared<Binding>(
101
LexerCursorRange
{Path->lCur(), LastToken->rCur()}, std::move(Path),
102
std::move(
Expr
), std::move(TokEq));
103
}
104
105
std::shared_ptr<Inherit>
Parser::parseInherit
() {
106
Token
TokInherit = peek();
107
if
(TokInherit.
kind
() != tok_kw_inherit)
108
return
nullptr
;
109
consume();
110
auto
SyncSemiColon = withSync(tok_semi_colon);
111
112
// These tokens might be consumed as "inherited_attrs"
113
auto
SyncID = withSync(tok_id);
114
auto
SyncQuote = withSync(tok_dquote);
115
auto
SyncDollarCurly = withSync(tok_dollar_curly);
116
117
assert(LastToken &&
"LastToken should be set after consume()"
);
118
std::vector<std::shared_ptr<AttrName>> AttrNames;
119
std::shared_ptr<Expr>
Expr
=
nullptr
;
120
if
(
Token
Tok = peek(); Tok.
kind
() == tok_l_paren) {
121
consume();
122
Expr
=
parseExpr
();
123
if
(!
Expr
)
124
diagNullExpr
(Diags, LastToken->rCur(),
"inherit"
);
125
if
(ExpectResult ER = expect(tok_r_paren); ER.ok())
126
consume();
127
else
128
ER.diag().note(Note::NK_ToMachThis, Tok.range())
129
<< std::string(tok::spelling(tok_l_paren));
130
}
131
while
(
true
) {
132
if
(
auto
AttrName
=
parseAttrName
()) {
133
AttrNames.emplace_back(std::move(
AttrName
));
134
continue
;
135
}
136
break
;
137
}
138
ExpectResult ER = expect(tok_semi_colon);
139
if
(ER.ok())
140
consume();
141
else
142
ER.diag().
note
(Note::NK_ToMachThis, TokInherit.
range
())
143
<< std::string(tok::spelling(tok_kw_inherit));
144
145
// If attrnames are emtpy, this is an emtpy "inherit";
146
if
(AttrNames.empty()) {
147
Diagnostic
&D =
148
Diags.emplace_back(Diagnostic::DK_EmptyInherit, TokInherit.
range
());
149
D.
tag
(
DiagnosticTag::Faded
);
150
Fix
&F = D.
fix
(
"remove `inherit` keyword"
);
151
F.
edit
(
TextEdit::mkRemoval
(TokInherit.
range
()));
152
if
(ER.ok()) {
153
// Remove ";" also.
154
F.
edit
(
TextEdit::mkRemoval
(ER.tok().
range
()));
155
}
156
}
157
return
std::make_shared<Inherit>(
158
LexerCursorRange
{TokInherit.
lCur
(), LastToken->rCur()},
159
std::move(AttrNames), std::move(
Expr
));
160
}
161
162
std::shared_ptr<Binds>
Parser::parseBinds
() {
163
// TODO: curently we don't support inherit
164
LexerCursor
Begin = peek().lCur();
165
std::vector<std::shared_ptr<Node>> Bindings;
166
// attrpath
167
auto
SyncID = withSync(tok_id);
168
auto
SyncQuote = withSync(tok_dquote);
169
auto
SyncDollarCurly = withSync(tok_dollar_curly);
170
171
// inherit
172
auto
SyncInherit = withSync(tok_kw_inherit);
173
while
(
true
) {
174
if
(
auto
Binding
=
parseBinding
()) {
175
Bindings.emplace_back(std::move(
Binding
));
176
continue
;
177
}
178
if
(
auto
Inherit
=
parseInherit
()) {
179
Bindings.emplace_back(std::move(
Inherit
));
180
continue
;
181
}
182
// If it is neither a binding, nor an inherit. Let's consume an "Unknown"
183
// For error recovery
184
if
(removeUnexpected())
185
continue
;
186
break
;
187
}
188
if
(Bindings.empty())
189
return
nullptr
;
190
assert(LastToken &&
"LastToken should be set after valid binding"
);
191
return
std::make_shared<Binds>(
LexerCursorRange
{Begin, LastToken->rCur()},
192
std::move(Bindings));
193
}
194
195
std::shared_ptr<ExprAttrs>
Parser::parseExprAttrs
() {
196
std::shared_ptr<Misc> Rec;
197
198
auto
Sync = withSync(tok_r_curly);
199
200
// "to match this ..."
201
// if "{" is missing, then use "rec", otherwise use "{"
202
Token
Matcher = peek();
203
LexerCursor
Begin = peek().lCur();
// rec or {
204
if
(
Token
Tok = peek(); Tok.
kind
() == tok_kw_rec) {
205
consume();
206
Rec = std::make_shared<Misc>(Tok.range());
207
}
208
if
(ExpectResult ER = expect(tok_l_curly); ER.ok()) {
209
consume();
210
Matcher = ER.tok();
211
}
212
assert(LastToken &&
"LastToken should be set after valid { or rec"
);
213
auto
Binds
=
parseBinds
();
214
if
(ExpectResult ER = expect(tok_r_curly); ER.ok())
215
consume();
216
else
217
ER.diag().note(Note::NK_ToMachThis, Matcher.
range
())
218
<< std::string(tok::spelling(Matcher.
kind
()));
219
return
Act.onExprAttrs(
LexerCursorRange
{Begin, LastToken->rCur()},
220
std::move(
Binds
), std::move(Rec));
221
}
nixf::AttrName
Definition
Attrs.h:10
nixf::Binding
Definition
Attrs.h:115
nixf::Binds
Definition
Attrs.h:173
nixf::Diagnostic::note
Note & note(Note::NoteKind Kind, LexerCursorRange Range)
Definition
Diagnostic.h:197
nixf::Diagnostic::fix
Fix & fix(std::string Message)
Definition
Diagnostic.h:203
nixf::Expr
Definition
Basic.h:70
nixf::Fix
Definition
Diagnostic.h:57
nixf::Fix::edit
Fix & edit(TextEdit Edit)
Definition
Diagnostic.h:65
nixf::Inherit
Definition
Attrs.h:145
nixf::LexerCursorRange
Definition
Range.h:105
nixf::LexerCursor
A point in the source file.
Definition
Range.h:57
nixf::Parser::parseInterpolation
std::shared_ptr< Interpolation > parseInterpolation()
Parse interpolations.
Definition
ParseStrings.cpp:6
nixf::Parser::parseExpr
std::shared_ptr< Expr > parseExpr()
Definition
ParseExpr.cpp:76
nixf::Parser::parseInherit
std::shared_ptr< Inherit > parseInherit()
Definition
ParseAttrs.cpp:105
nixf::Parser::parseAttrName
std::shared_ptr< AttrName > parseAttrName()
Definition
ParseAttrs.cpp:6
nixf::Parser::parseString
std::shared_ptr< ExprString > parseString(bool IsIndented)
Definition
ParseStrings.cpp:111
nixf::Parser::parseAttrPath
std::shared_ptr< AttrPath > parseAttrPath()
Definition
ParseAttrs.cpp:30
nixf::Parser::parseExprAttrs
std::shared_ptr< ExprAttrs > parseExprAttrs()
Definition
ParseAttrs.cpp:195
nixf::Parser::parseBinds
std::shared_ptr< Binds > parseBinds()
Definition
ParseAttrs.cpp:162
nixf::Parser::parseBinding
std::shared_ptr< Binding > parseBinding()
Definition
ParseAttrs.cpp:72
nixf::PartialDiagnostic::tag
void tag(DiagnosticTag Tag)
Definition
Diagnostic.h:96
nixf::TextEdit::mkRemoval
static TextEdit mkRemoval(LexerCursorRange RemovingRange)
Definition
Diagnostic.h:39
nixf::TextEdit::mkInsertion
static TextEdit mkInsertion(LexerCursor P, std::string NewText)
Definition
Diagnostic.h:35
nixf::Token
A token. With it's kind, and the range in source code.
Definition
Token.h:14
nixf::Token::lCur
LexerCursor lCur() const
Definition
Token.h:22
nixf::Token::kind
tok::TokenKind kind() const
Definition
Token.h:24
nixf::Token::range
LexerCursorRange range() const
Definition
Token.h:25
Diagnostic
Definition
Diagnostic.cpp.py:1
nixf::detail
Definition
src/Parse/Parser.h:22
nixf::detail::diagNullExpr
Diagnostic & diagNullExpr(std::vector< Diagnostic > &Diags, LexerCursor Loc, std::string As)
Definition
ParseSupport.cpp:11
nixf
Definition
Diagnostic.h:19
nixf::DiagnosticTag::Faded
@ Faded
Definition
Diagnostic.h:75
Parser.h
Parser for the Nix expression language.
Generated by
1.17.0