mirror of
https://github.com/NixOS/nix.git
synced 2025-11-08 11:36:03 +01:00
libexpr: parser.y: api.value.type variant
This commit is contained in:
parent
7e8db2eb59
commit
32b286e5d6
6 changed files with 99 additions and 125 deletions
|
|
@ -2050,10 +2050,10 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
||||||
};
|
};
|
||||||
|
|
||||||
// List of returned strings. References to these Values must NOT be persisted.
|
// List of returned strings. References to these Values must NOT be persisted.
|
||||||
SmallTemporaryValueVector<conservativeStackReservation> values(es->size());
|
SmallTemporaryValueVector<conservativeStackReservation> values(es.size());
|
||||||
Value * vTmpP = values.data();
|
Value * vTmpP = values.data();
|
||||||
|
|
||||||
for (auto & [i_pos, i] : *es) {
|
for (auto & [i_pos, i] : es) {
|
||||||
Value & vTmp = *vTmpP++;
|
Value & vTmp = *vTmpP++;
|
||||||
i->eval(state, env, vTmp);
|
i->eval(state, env, vTmp);
|
||||||
|
|
||||||
|
|
@ -2097,7 +2097,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
||||||
.debugThrow();
|
.debugThrow();
|
||||||
} else {
|
} else {
|
||||||
if (s.empty())
|
if (s.empty())
|
||||||
s.reserve(es->size());
|
s.reserve(es.size());
|
||||||
/* skip canonization of first path, which would only be not
|
/* skip canonization of first path, which would only be not
|
||||||
canonized in the first place if it's coming from a ./${foo} type
|
canonized in the first place if it's coming from a ./${foo} type
|
||||||
path */
|
path */
|
||||||
|
|
|
||||||
|
|
@ -695,11 +695,11 @@ struct ExprConcatStrings : Expr
|
||||||
{
|
{
|
||||||
PosIdx pos;
|
PosIdx pos;
|
||||||
bool forceString;
|
bool forceString;
|
||||||
std::vector<std::pair<PosIdx, Expr *>> * es;
|
std::vector<std::pair<PosIdx, Expr *>> es;
|
||||||
ExprConcatStrings(const PosIdx & pos, bool forceString, std::vector<std::pair<PosIdx, Expr *>> * es)
|
ExprConcatStrings(const PosIdx & pos, bool forceString, std::vector<std::pair<PosIdx, Expr *>> && es)
|
||||||
: pos(pos)
|
: pos(pos)
|
||||||
, forceString(forceString)
|
, forceString(forceString)
|
||||||
, es(es) {};
|
, es(std::move(es)) {};
|
||||||
|
|
||||||
PosIdx getPos() const override
|
PosIdx getPos() const override
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vector<std::pair<PosIdx, st
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Strip spaces from each line. */
|
/* Strip spaces from each line. */
|
||||||
auto * es2 = new std::vector<std::pair<PosIdx, Expr *>>;
|
std::vector<std::pair<PosIdx, Expr *>> es2{};
|
||||||
atStartOfLine = true;
|
atStartOfLine = true;
|
||||||
size_t curDropped = 0;
|
size_t curDropped = 0;
|
||||||
size_t n = es.size();
|
size_t n = es.size();
|
||||||
|
|
@ -290,7 +290,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vector<std::pair<PosIdx, st
|
||||||
const auto trimExpr = [&](Expr * e) {
|
const auto trimExpr = [&](Expr * e) {
|
||||||
atStartOfLine = false;
|
atStartOfLine = false;
|
||||||
curDropped = 0;
|
curDropped = 0;
|
||||||
es2->emplace_back(i->first, e);
|
es2.emplace_back(i->first, e);
|
||||||
};
|
};
|
||||||
const auto trimString = [&](const StringToken & t) {
|
const auto trimString = [&](const StringToken & t) {
|
||||||
std::string s2;
|
std::string s2;
|
||||||
|
|
@ -324,7 +324,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vector<std::pair<PosIdx, st
|
||||||
|
|
||||||
// Ignore empty strings for a minor optimisation and AST simplification
|
// Ignore empty strings for a minor optimisation and AST simplification
|
||||||
if (s2 != "") {
|
if (s2 != "") {
|
||||||
es2->emplace_back(i->first, new ExprString(alloc, s2));
|
es2.emplace_back(i->first, new ExprString(alloc, s2));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (; i != es.end(); ++i, --n) {
|
for (; i != es.end(); ++i, --n) {
|
||||||
|
|
@ -333,19 +333,17 @@ ParserState::stripIndentation(const PosIdx pos, std::vector<std::pair<PosIdx, st
|
||||||
|
|
||||||
// If there is nothing at all, return the empty string directly.
|
// If there is nothing at all, return the empty string directly.
|
||||||
// This also ensures that equivalent empty strings result in the same ast, which is helpful when testing formatters.
|
// This also ensures that equivalent empty strings result in the same ast, which is helpful when testing formatters.
|
||||||
if (es2->size() == 0) {
|
if (es2.size() == 0) {
|
||||||
auto * const result = new ExprString("");
|
auto * const result = new ExprString("");
|
||||||
delete es2;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is a single string, then don't do a concatenation. */
|
/* If this is a single string, then don't do a concatenation. */
|
||||||
if (es2->size() == 1 && dynamic_cast<ExprString *>((*es2)[0].second)) {
|
if (es2.size() == 1 && dynamic_cast<ExprString *>((es2)[0].second)) {
|
||||||
auto * const result = (*es2)[0].second;
|
auto * const result = (es2)[0].second;
|
||||||
delete es2;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return new ExprConcatStrings(pos, true, es2);
|
return new ExprConcatStrings(pos, true, std::move(es2));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PosIdx LexerState::at(const ParserLocation & loc)
|
inline PosIdx LexerState::at(const ParserLocation & loc)
|
||||||
|
|
|
||||||
|
|
@ -142,11 +142,11 @@ or { return OR_KW; }
|
||||||
return PIPE_INTO;
|
return PIPE_INTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ID} { yylval->id = {yytext, (size_t) yyleng}; return ID; }
|
{ID} { yylval->emplace<StringToken>(yytext, (size_t) yyleng); return ID; }
|
||||||
{INT} { errno = 0;
|
{INT} { errno = 0;
|
||||||
std::optional<int64_t> numMay = string2Int<int64_t>(yytext);
|
std::optional<int64_t> numMay = string2Int<int64_t>(yytext);
|
||||||
if (numMay.has_value()) {
|
if (numMay.has_value()) {
|
||||||
yylval->n = NixInt{*numMay};
|
yylval->emplace<NixInt>(*numMay);
|
||||||
} else {
|
} else {
|
||||||
throw ParseError(ErrorInfo{
|
throw ParseError(ErrorInfo{
|
||||||
.msg = HintFmt("invalid integer '%1%'", yytext),
|
.msg = HintFmt("invalid integer '%1%'", yytext),
|
||||||
|
|
@ -156,7 +156,7 @@ or { return OR_KW; }
|
||||||
return INT_LIT;
|
return INT_LIT;
|
||||||
}
|
}
|
||||||
{FLOAT} { errno = 0;
|
{FLOAT} { errno = 0;
|
||||||
yylval->nf = strtod(yytext, 0);
|
yylval->emplace<NixFloat>(strtod(yytext, 0));
|
||||||
if (errno != 0)
|
if (errno != 0)
|
||||||
throw ParseError(ErrorInfo{
|
throw ParseError(ErrorInfo{
|
||||||
.msg = HintFmt("invalid float '%1%'", yytext),
|
.msg = HintFmt("invalid float '%1%'", yytext),
|
||||||
|
|
@ -183,7 +183,7 @@ or { return OR_KW; }
|
||||||
/* It is impossible to match strings ending with '$' with one
|
/* It is impossible to match strings ending with '$' with one
|
||||||
regex because trailing contexts are only valid at the end
|
regex because trailing contexts are only valid at the end
|
||||||
of a rule. (A sane but undocumented limitation.) */
|
of a rule. (A sane but undocumented limitation.) */
|
||||||
yylval->str = unescapeStr(yytext, yyleng, [&]() { return state->positions[CUR_POS]; });
|
yylval->emplace<StringToken>(unescapeStr(yytext, yyleng, [&]() { return state->positions[CUR_POS]; }));
|
||||||
return STR;
|
return STR;
|
||||||
}
|
}
|
||||||
<STRING>\$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; }
|
<STRING>\$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; }
|
||||||
|
|
@ -198,27 +198,27 @@ or { return OR_KW; }
|
||||||
|
|
||||||
\'\'(\ *\n)? { PUSH_STATE(IND_STRING); return IND_STRING_OPEN; }
|
\'\'(\ *\n)? { PUSH_STATE(IND_STRING); return IND_STRING_OPEN; }
|
||||||
<IND_STRING>([^\$\']|\$[^\{\']|\'[^\'\$])+ {
|
<IND_STRING>([^\$\']|\$[^\{\']|\'[^\'\$])+ {
|
||||||
yylval->str = {yytext, (size_t) yyleng, true};
|
yylval->emplace<StringToken>(yytext, (size_t) yyleng, true);
|
||||||
forceNoNullByte(yylval->str, [&]() { return state->positions[CUR_POS]; });
|
forceNoNullByte(yylval->as<StringToken>(), [&]() { return state->positions[CUR_POS]; });
|
||||||
return IND_STR;
|
return IND_STR;
|
||||||
}
|
}
|
||||||
<IND_STRING>\'\'\$ |
|
<IND_STRING>\'\'\$ |
|
||||||
<IND_STRING>\$ {
|
<IND_STRING>\$ {
|
||||||
yylval->str = {"$", 1};
|
yylval->emplace<StringToken>("$", 1);
|
||||||
return IND_STR;
|
return IND_STR;
|
||||||
}
|
}
|
||||||
<IND_STRING>\'\'\' {
|
<IND_STRING>\'\'\' {
|
||||||
yylval->str = {"''", 2};
|
yylval->emplace<StringToken>("''", 2);
|
||||||
return IND_STR;
|
return IND_STR;
|
||||||
}
|
}
|
||||||
<IND_STRING>\'\'\\{ANY} {
|
<IND_STRING>\'\'\\{ANY} {
|
||||||
yylval->str = unescapeStr(yytext + 2, yyleng - 2, [&]() { return state->positions[CUR_POS]; });
|
yylval->emplace<StringToken>(unescapeStr(yytext + 2, yyleng - 2, [&]() { return state->positions[CUR_POS]; }));
|
||||||
return IND_STR;
|
return IND_STR;
|
||||||
}
|
}
|
||||||
<IND_STRING>\$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; }
|
<IND_STRING>\$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; }
|
||||||
<IND_STRING>\'\' { POP_STATE(); return IND_STRING_CLOSE; }
|
<IND_STRING>\'\' { POP_STATE(); return IND_STRING_CLOSE; }
|
||||||
<IND_STRING>\' {
|
<IND_STRING>\' {
|
||||||
yylval->str = {"'", 1};
|
yylval->emplace<StringToken>("'", 1);
|
||||||
return IND_STR;
|
return IND_STR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,14 +232,14 @@ or { return OR_KW; }
|
||||||
<PATH_START>{PATH_SEG} {
|
<PATH_START>{PATH_SEG} {
|
||||||
POP_STATE();
|
POP_STATE();
|
||||||
PUSH_STATE(INPATH_SLASH);
|
PUSH_STATE(INPATH_SLASH);
|
||||||
yylval->path = {yytext, (size_t) yyleng};
|
yylval->emplace<StringToken>(yytext, (size_t) yyleng);
|
||||||
return PATH;
|
return PATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
<PATH_START>{HPATH_START} {
|
<PATH_START>{HPATH_START} {
|
||||||
POP_STATE();
|
POP_STATE();
|
||||||
PUSH_STATE(INPATH_SLASH);
|
PUSH_STATE(INPATH_SLASH);
|
||||||
yylval->path = {yytext, (size_t) yyleng};
|
yylval->emplace<StringToken>(yytext, (size_t) yyleng);
|
||||||
return HPATH;
|
return HPATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,7 +248,7 @@ or { return OR_KW; }
|
||||||
PUSH_STATE(INPATH_SLASH);
|
PUSH_STATE(INPATH_SLASH);
|
||||||
else
|
else
|
||||||
PUSH_STATE(INPATH);
|
PUSH_STATE(INPATH);
|
||||||
yylval->path = {yytext, (size_t) yyleng};
|
yylval->emplace<StringToken>(yytext, (size_t) yyleng);
|
||||||
return PATH;
|
return PATH;
|
||||||
}
|
}
|
||||||
{HPATH} {
|
{HPATH} {
|
||||||
|
|
@ -256,7 +256,7 @@ or { return OR_KW; }
|
||||||
PUSH_STATE(INPATH_SLASH);
|
PUSH_STATE(INPATH_SLASH);
|
||||||
else
|
else
|
||||||
PUSH_STATE(INPATH);
|
PUSH_STATE(INPATH);
|
||||||
yylval->path = {yytext, (size_t) yyleng};
|
yylval->emplace<StringToken>(yytext, (size_t) yyleng);
|
||||||
return HPATH;
|
return HPATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -272,7 +272,7 @@ or { return OR_KW; }
|
||||||
PUSH_STATE(INPATH_SLASH);
|
PUSH_STATE(INPATH_SLASH);
|
||||||
else
|
else
|
||||||
PUSH_STATE(INPATH);
|
PUSH_STATE(INPATH);
|
||||||
yylval->str = {yytext, (size_t) yyleng};
|
yylval->emplace<StringToken>(yytext, (size_t) yyleng);
|
||||||
return STR;
|
return STR;
|
||||||
}
|
}
|
||||||
<INPATH>{ANY} |
|
<INPATH>{ANY} |
|
||||||
|
|
@ -294,8 +294,8 @@ or { return OR_KW; }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
{SPATH} { yylval->path = {yytext, (size_t) yyleng}; return SPATH; }
|
{SPATH} { yylval->emplace<StringToken>(yytext, (size_t) yyleng); return SPATH; }
|
||||||
{URI} { yylval->uri = {yytext, (size_t) yyleng}; return URI; }
|
{URI} { yylval->emplace<StringToken>(yytext, (size_t) yyleng); return URI; }
|
||||||
|
|
||||||
%{
|
%{
|
||||||
// Doc comment rule
|
// Doc comment rule
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,7 @@ void ExprConcatStrings::show(const SymbolTable & symbols, std::ostream & str) co
|
||||||
{
|
{
|
||||||
bool first = true;
|
bool first = true;
|
||||||
str << "(";
|
str << "(";
|
||||||
for (auto & i : *es) {
|
for (auto & i : es) {
|
||||||
if (first)
|
if (first)
|
||||||
first = false;
|
first = false;
|
||||||
else
|
else
|
||||||
|
|
@ -564,7 +564,7 @@ void ExprConcatStrings::bindVars(EvalState & es, const std::shared_ptr<const Sta
|
||||||
if (es.debugRepl)
|
if (es.debugRepl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
for (auto & i : *this->es)
|
for (auto & i : this->es)
|
||||||
i.second->bindVars(es, env);
|
i.second->bindVars(es, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@
|
||||||
|
|
||||||
%code requires {
|
%code requires {
|
||||||
|
|
||||||
|
// bison adds a bunch of switch statements with default:
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wswitch-enum"
|
||||||
|
|
||||||
#ifndef BISON_HEADER
|
#ifndef BISON_HEADER
|
||||||
#define BISON_HEADER
|
#define BISON_HEADER
|
||||||
|
|
||||||
|
|
@ -120,46 +124,28 @@ static Expr * makeCall(PosIdx pos, Expr * fn, Expr * arg) {
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%union {
|
%define api.value.type variant
|
||||||
// !!! We're probably leaking stuff here.
|
|
||||||
nix::Expr * e;
|
|
||||||
nix::ExprList * list;
|
|
||||||
nix::ExprAttrs * attrs;
|
|
||||||
nix::Formals * formals;
|
|
||||||
nix::Formal * formal;
|
|
||||||
nix::NixInt n;
|
|
||||||
nix::NixFloat nf;
|
|
||||||
nix::StringToken id; // !!! -> Symbol
|
|
||||||
nix::StringToken path;
|
|
||||||
nix::StringToken uri;
|
|
||||||
nix::StringToken str;
|
|
||||||
std::vector<nix::AttrName> * attrNames;
|
|
||||||
std::vector<std::pair<nix::AttrName, nix::PosIdx>> * inheritAttrs;
|
|
||||||
std::vector<std::pair<nix::PosIdx, nix::Expr *>> * string_parts;
|
|
||||||
std::variant<nix::Expr *, std::string_view> * to_be_string;
|
|
||||||
std::vector<std::pair<nix::PosIdx, std::variant<nix::Expr *, nix::StringToken>>> * ind_string_parts;
|
|
||||||
}
|
|
||||||
|
|
||||||
%type <e> start expr expr_function expr_if expr_op
|
%type <nix::Expr *> start expr expr_function expr_if expr_op
|
||||||
%type <e> expr_select expr_simple expr_app
|
%type <nix::Expr *> expr_select expr_simple expr_app
|
||||||
%type <e> expr_pipe_from expr_pipe_into
|
%type <nix::Expr *> expr_pipe_from expr_pipe_into
|
||||||
%type <list> expr_list
|
%type <nix::ExprList *> expr_list
|
||||||
%type <attrs> binds binds1
|
%type <nix::ExprAttrs *> binds binds1
|
||||||
%type <formals> formals formal_set
|
%type <nix::Formals *> formals formal_set
|
||||||
%type <formal> formal
|
%type <nix::Formal> formal
|
||||||
%type <attrNames> attrpath
|
%type <std::vector<nix::AttrName>> attrpath
|
||||||
%type <inheritAttrs> attrs
|
%type <std::vector<std::pair<nix::AttrName, nix::PosIdx>>> attrs
|
||||||
%type <string_parts> string_parts_interpolated
|
%type <std::vector<std::pair<nix::PosIdx, nix::Expr *>>> string_parts_interpolated
|
||||||
%type <ind_string_parts> ind_string_parts
|
%type <std::vector<std::pair<nix::PosIdx, std::variant<nix::Expr *, nix::StringToken>>>> ind_string_parts
|
||||||
%type <e> path_start
|
%type <nix::Expr *> path_start
|
||||||
%type <to_be_string> string_parts string_attr
|
%type <std::variant<nix::Expr *, std::string_view>> string_parts string_attr
|
||||||
%type <id> attr
|
%type <nix::StringToken> attr
|
||||||
%token <id> ID
|
%token <nix::StringToken> ID
|
||||||
%token <str> STR IND_STR
|
%token <nix::StringToken> STR IND_STR
|
||||||
%token <n> INT_LIT
|
%token <nix::NixInt> INT_LIT
|
||||||
%token <nf> FLOAT_LIT
|
%token <nix::NixFloat> FLOAT_LIT
|
||||||
%token <path> PATH HPATH SPATH PATH_END
|
%token <nix::StringToken> PATH HPATH SPATH PATH_END
|
||||||
%token <uri> URI
|
%token <nix::StringToken> URI
|
||||||
%token IF THEN ELSE ASSERT WITH LET IN_KW REC INHERIT EQ NEQ AND OR IMPL OR_KW
|
%token IF THEN ELSE ASSERT WITH LET IN_KW REC INHERIT EQ NEQ AND OR IMPL OR_KW
|
||||||
%token PIPE_FROM PIPE_INTO /* <| and |> */
|
%token PIPE_FROM PIPE_INTO /* <| and |> */
|
||||||
%token DOLLAR_CURLY /* == ${ */
|
%token DOLLAR_CURLY /* == ${ */
|
||||||
|
|
@ -261,9 +247,9 @@ expr_op
|
||||||
| expr_op OR expr_op { $$ = new ExprOpOr(state->at(@2), $1, $3); }
|
| expr_op OR expr_op { $$ = new ExprOpOr(state->at(@2), $1, $3); }
|
||||||
| expr_op IMPL expr_op { $$ = new ExprOpImpl(state->at(@2), $1, $3); }
|
| expr_op IMPL expr_op { $$ = new ExprOpImpl(state->at(@2), $1, $3); }
|
||||||
| expr_op UPDATE expr_op { $$ = new ExprOpUpdate(state->at(@2), $1, $3); }
|
| expr_op UPDATE expr_op { $$ = new ExprOpUpdate(state->at(@2), $1, $3); }
|
||||||
| expr_op '?' attrpath { $$ = new ExprOpHasAttr(state->alloc, $1, std::move(*$3)); delete $3; }
|
| expr_op '?' attrpath { $$ = new ExprOpHasAttr(state->alloc, $1, std::move($3)); }
|
||||||
| expr_op '+' expr_op
|
| expr_op '+' expr_op
|
||||||
{ $$ = new ExprConcatStrings(state->at(@2), false, new std::vector<std::pair<PosIdx, Expr *> >({{state->at(@1), $1}, {state->at(@3), $3}})); }
|
{ $$ = new ExprConcatStrings(state->at(@2), false, {{state->at(@1), $1}, {state->at(@3), $3}}); }
|
||||||
| expr_op '-' expr_op { $$ = new ExprCall(state->at(@2), new ExprVar(state->s.sub), {$1, $3}); }
|
| expr_op '-' expr_op { $$ = new ExprCall(state->at(@2), new ExprVar(state->s.sub), {$1, $3}); }
|
||||||
| expr_op '*' expr_op { $$ = new ExprCall(state->at(@2), new ExprVar(state->s.mul), {$1, $3}); }
|
| expr_op '*' expr_op { $$ = new ExprCall(state->at(@2), new ExprVar(state->s.mul), {$1, $3}); }
|
||||||
| expr_op '/' expr_op { $$ = new ExprCall(state->at(@2), new ExprVar(state->s.div), {$1, $3}); }
|
| expr_op '/' expr_op { $$ = new ExprCall(state->at(@2), new ExprVar(state->s.div), {$1, $3}); }
|
||||||
|
|
@ -282,9 +268,9 @@ expr_app
|
||||||
|
|
||||||
expr_select
|
expr_select
|
||||||
: expr_simple '.' attrpath
|
: expr_simple '.' attrpath
|
||||||
{ $$ = new ExprSelect(state->alloc, CUR_POS, $1, std::move(*$3), nullptr); delete $3; }
|
{ $$ = new ExprSelect(state->alloc, CUR_POS, $1, std::move($3), nullptr); }
|
||||||
| expr_simple '.' attrpath OR_KW expr_select
|
| expr_simple '.' attrpath OR_KW expr_select
|
||||||
{ $$ = new ExprSelect(state->alloc, CUR_POS, $1, std::move(*$3), $5); delete $3; $5->warnIfCursedOr(state->symbols, state->positions); }
|
{ $$ = new ExprSelect(state->alloc, CUR_POS, $1, std::move($3), $5); $5->warnIfCursedOr(state->symbols, state->positions); }
|
||||||
| /* Backwards compatibility: because Nixpkgs has a function named ‘or’,
|
| /* Backwards compatibility: because Nixpkgs has a function named ‘or’,
|
||||||
allow stuff like ‘map or [...]’. This production is problematic (see
|
allow stuff like ‘map or [...]’. This production is problematic (see
|
||||||
https://github.com/NixOS/nix/issues/11118) and will be refactored in the
|
https://github.com/NixOS/nix/issues/11118) and will be refactored in the
|
||||||
|
|
@ -311,17 +297,15 @@ expr_simple
|
||||||
std::visit(overloaded{
|
std::visit(overloaded{
|
||||||
[&](std::string_view str) { $$ = new ExprString(state->alloc, str); },
|
[&](std::string_view str) { $$ = new ExprString(state->alloc, str); },
|
||||||
[&](Expr * expr) { $$ = expr; }},
|
[&](Expr * expr) { $$ = expr; }},
|
||||||
*$2);
|
$2);
|
||||||
delete $2;
|
|
||||||
}
|
}
|
||||||
| IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE {
|
| IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE {
|
||||||
$$ = state->stripIndentation(CUR_POS, std::move(*$2));
|
$$ = state->stripIndentation(CUR_POS, std::move($2));
|
||||||
delete $2;
|
|
||||||
}
|
}
|
||||||
| path_start PATH_END
|
| path_start PATH_END
|
||||||
| path_start string_parts_interpolated PATH_END {
|
| path_start string_parts_interpolated PATH_END {
|
||||||
$2->insert($2->begin(), {state->at(@1), $1});
|
$2.insert($2.begin(), {state->at(@1), $1});
|
||||||
$$ = new ExprConcatStrings(CUR_POS, false, $2);
|
$$ = new ExprConcatStrings(CUR_POS, false, std::move($2));
|
||||||
}
|
}
|
||||||
| SPATH {
|
| SPATH {
|
||||||
std::string_view path($1.p + 1, $1.l - 2);
|
std::string_view path($1.p + 1, $1.l - 2);
|
||||||
|
|
@ -354,20 +338,19 @@ expr_simple
|
||||||
;
|
;
|
||||||
|
|
||||||
string_parts
|
string_parts
|
||||||
: STR { $$ = new std::variant<Expr *, std::string_view>($1); }
|
: STR { $$ = $1; }
|
||||||
| string_parts_interpolated { $$ = new std::variant<Expr *, std::string_view>(new ExprConcatStrings(CUR_POS, true, $1)); }
|
| string_parts_interpolated { $$ = new ExprConcatStrings(CUR_POS, true, std::move($1)); }
|
||||||
| { $$ = new std::variant<Expr *, std::string_view>(std::string_view()); }
|
| { $$ = std::string_view(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
string_parts_interpolated
|
string_parts_interpolated
|
||||||
: string_parts_interpolated STR
|
: string_parts_interpolated STR
|
||||||
{ $$ = $1; $1->emplace_back(state->at(@2), new ExprString(state->alloc, $2)); }
|
{ $$ = $1; $$.emplace_back(state->at(@2), new ExprString(state->alloc, $2)); }
|
||||||
| string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = $1; $1->emplace_back(state->at(@2), $3); }
|
| string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = $1; $$.emplace_back(state->at(@2), $3); }
|
||||||
| DOLLAR_CURLY expr '}' { $$ = new std::vector<std::pair<PosIdx, Expr *>>; $$->emplace_back(state->at(@1), $2); }
|
| DOLLAR_CURLY expr '}' { $$.emplace_back(state->at(@1), $2); }
|
||||||
| STR DOLLAR_CURLY expr '}' {
|
| STR DOLLAR_CURLY expr '}' {
|
||||||
$$ = new std::vector<std::pair<PosIdx, Expr *>>;
|
$$.emplace_back(state->at(@1), new ExprString(state->alloc, $1));
|
||||||
$$->emplace_back(state->at(@1), new ExprString(state->alloc, $1));
|
$$.emplace_back(state->at(@2), $3);
|
||||||
$$->emplace_back(state->at(@2), $3);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -408,9 +391,9 @@ path_start
|
||||||
;
|
;
|
||||||
|
|
||||||
ind_string_parts
|
ind_string_parts
|
||||||
: ind_string_parts IND_STR { $$ = $1; $1->emplace_back(state->at(@2), $2); }
|
: ind_string_parts IND_STR { $$ = $1; $$.emplace_back(state->at(@2), $2); }
|
||||||
| ind_string_parts DOLLAR_CURLY expr '}' { $$ = $1; $1->emplace_back(state->at(@2), $3); }
|
| ind_string_parts DOLLAR_CURLY expr '}' { $$ = $1; $$.emplace_back(state->at(@2), $3); }
|
||||||
| { $$ = new std::vector<std::pair<PosIdx, std::variant<Expr *, StringToken>>>; }
|
| { }
|
||||||
;
|
;
|
||||||
|
|
||||||
binds
|
binds
|
||||||
|
|
@ -421,19 +404,17 @@ binds
|
||||||
binds1
|
binds1
|
||||||
: binds1[accum] attrpath '=' expr ';'
|
: binds1[accum] attrpath '=' expr ';'
|
||||||
{ $$ = $accum;
|
{ $$ = $accum;
|
||||||
state->addAttr($$, std::move(*$attrpath), @attrpath, $expr, @expr);
|
state->addAttr($$, std::move($attrpath), @attrpath, $expr, @expr);
|
||||||
delete $attrpath;
|
|
||||||
}
|
}
|
||||||
| binds[accum] INHERIT attrs ';'
|
| binds[accum] INHERIT attrs ';'
|
||||||
{ $$ = $accum;
|
{ $$ = $accum;
|
||||||
for (auto & [i, iPos] : *$attrs) {
|
for (auto & [i, iPos] : $attrs) {
|
||||||
if ($accum->attrs.find(i.symbol) != $accum->attrs.end())
|
if ($accum->attrs.find(i.symbol) != $accum->attrs.end())
|
||||||
state->dupAttr(i.symbol, iPos, $accum->attrs[i.symbol].pos);
|
state->dupAttr(i.symbol, iPos, $accum->attrs[i.symbol].pos);
|
||||||
$accum->attrs.emplace(
|
$accum->attrs.emplace(
|
||||||
i.symbol,
|
i.symbol,
|
||||||
ExprAttrs::AttrDef(new ExprVar(iPos, i.symbol), iPos, ExprAttrs::AttrDef::Kind::Inherited));
|
ExprAttrs::AttrDef(new ExprVar(iPos, i.symbol), iPos, ExprAttrs::AttrDef::Kind::Inherited));
|
||||||
}
|
}
|
||||||
delete $attrs;
|
|
||||||
}
|
}
|
||||||
| binds[accum] INHERIT '(' expr ')' attrs ';'
|
| binds[accum] INHERIT '(' expr ')' attrs ';'
|
||||||
{ $$ = $accum;
|
{ $$ = $accum;
|
||||||
|
|
@ -441,7 +422,7 @@ binds1
|
||||||
$accum->inheritFromExprs = std::make_unique<std::vector<Expr *>>();
|
$accum->inheritFromExprs = std::make_unique<std::vector<Expr *>>();
|
||||||
$accum->inheritFromExprs->push_back($expr);
|
$accum->inheritFromExprs->push_back($expr);
|
||||||
auto from = new nix::ExprInheritFrom(state->at(@expr), $accum->inheritFromExprs->size() - 1);
|
auto from = new nix::ExprInheritFrom(state->at(@expr), $accum->inheritFromExprs->size() - 1);
|
||||||
for (auto & [i, iPos] : *$attrs) {
|
for (auto & [i, iPos] : $attrs) {
|
||||||
if ($accum->attrs.find(i.symbol) != $accum->attrs.end())
|
if ($accum->attrs.find(i.symbol) != $accum->attrs.end())
|
||||||
state->dupAttr(i.symbol, iPos, $accum->attrs[i.symbol].pos);
|
state->dupAttr(i.symbol, iPos, $accum->attrs[i.symbol].pos);
|
||||||
$accum->attrs.emplace(
|
$accum->attrs.emplace(
|
||||||
|
|
@ -451,51 +432,45 @@ binds1
|
||||||
iPos,
|
iPos,
|
||||||
ExprAttrs::AttrDef::Kind::InheritedFrom));
|
ExprAttrs::AttrDef::Kind::InheritedFrom));
|
||||||
}
|
}
|
||||||
delete $attrs;
|
|
||||||
}
|
}
|
||||||
| attrpath '=' expr ';'
|
| attrpath '=' expr ';'
|
||||||
{ $$ = new ExprAttrs;
|
{ $$ = new ExprAttrs;
|
||||||
state->addAttr($$, std::move(*$attrpath), @attrpath, $expr, @expr);
|
state->addAttr($$, std::move($attrpath), @attrpath, $expr, @expr);
|
||||||
delete $attrpath;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
attrs
|
attrs
|
||||||
: attrs attr { $$ = $1; $1->emplace_back(AttrName(state->symbols.create($2)), state->at(@2)); }
|
: attrs attr { $$ = $1; $$.emplace_back(AttrName(state->symbols.create($2)), state->at(@2)); }
|
||||||
| attrs string_attr
|
| attrs string_attr
|
||||||
{ $$ = $1;
|
{ $$ = $1;
|
||||||
std::visit(overloaded {
|
std::visit(overloaded {
|
||||||
[&](std::string_view str) { $$->emplace_back(AttrName(state->symbols.create(str)), state->at(@2)); },
|
[&](std::string_view str) { $$.emplace_back(AttrName(state->symbols.create(str)), state->at(@2)); },
|
||||||
[&](Expr * expr) {
|
[&](Expr * expr) {
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = HintFmt("dynamic attributes not allowed in inherit"),
|
.msg = HintFmt("dynamic attributes not allowed in inherit"),
|
||||||
.pos = state->positions[state->at(@2)]
|
.pos = state->positions[state->at(@2)]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, *$2);
|
}, $2);
|
||||||
delete $2;
|
|
||||||
}
|
}
|
||||||
| { $$ = new std::vector<std::pair<AttrName, PosIdx>>; }
|
| { }
|
||||||
;
|
;
|
||||||
|
|
||||||
attrpath
|
attrpath
|
||||||
: attrpath '.' attr { $$ = $1; $1->push_back(AttrName(state->symbols.create($3))); }
|
: attrpath '.' attr { $$ = $1; $$.push_back(AttrName(state->symbols.create($3))); }
|
||||||
| attrpath '.' string_attr
|
| attrpath '.' string_attr
|
||||||
{ $$ = $1;
|
{ $$ = $1;
|
||||||
std::visit(overloaded {
|
std::visit(overloaded {
|
||||||
[&](std::string_view str) { $$->push_back(AttrName(state->symbols.create(str))); },
|
[&](std::string_view str) { $$.push_back(AttrName(state->symbols.create(str))); },
|
||||||
[&](Expr * expr) { $$->push_back(AttrName(expr)); }
|
[&](Expr * expr) { $$.push_back(AttrName(expr)); }
|
||||||
}, *$3);
|
}, $3);
|
||||||
delete $3;
|
|
||||||
}
|
}
|
||||||
| attr { $$ = new std::vector<AttrName>; $$->push_back(AttrName(state->symbols.create($1))); }
|
| attr { $$.push_back(AttrName(state->symbols.create($1))); }
|
||||||
| string_attr
|
| string_attr
|
||||||
{ $$ = new std::vector<AttrName>;
|
{ std::visit(overloaded {
|
||||||
std::visit(overloaded {
|
[&](std::string_view str) { $$.push_back(AttrName(state->symbols.create(str))); },
|
||||||
[&](std::string_view str) { $$->push_back(AttrName(state->symbols.create(str))); },
|
[&](Expr * expr) { $$.push_back(AttrName(expr)); }
|
||||||
[&](Expr * expr) { $$->push_back(AttrName(expr)); }
|
}, $1);
|
||||||
}, *$1);
|
|
||||||
delete $1;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -506,7 +481,7 @@ attr
|
||||||
|
|
||||||
string_attr
|
string_attr
|
||||||
: '"' string_parts '"' { $$ = $2; }
|
: '"' string_parts '"' { $$ = $2; }
|
||||||
| DOLLAR_CURLY expr '}' { $$ = new std::variant<Expr *, std::string_view>($2); }
|
| DOLLAR_CURLY expr '}' { $$ = $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
expr_list
|
expr_list
|
||||||
|
|
@ -524,14 +499,14 @@ formal_set
|
||||||
|
|
||||||
formals
|
formals
|
||||||
: formals[accum] ',' formal
|
: formals[accum] ',' formal
|
||||||
{ $$ = $accum; $$->formals.emplace_back(*$formal); delete $formal; }
|
{ $$ = $accum; $$->formals.emplace_back(std::move($formal)); }
|
||||||
| formal
|
| formal
|
||||||
{ $$ = new Formals; $$->formals.emplace_back(*$formal); delete $formal; }
|
{ $$ = new Formals; $$->formals.emplace_back(std::move($formal)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
formal
|
formal
|
||||||
: ID { $$ = new Formal{CUR_POS, state->symbols.create($1), 0}; }
|
: ID { $$ = Formal{CUR_POS, state->symbols.create($1), 0}; }
|
||||||
| ID '?' expr { $$ = new Formal{CUR_POS, state->symbols.create($1), $3}; }
|
| ID '?' expr { $$ = Formal{CUR_POS, state->symbols.create($1), $3}; }
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
@ -582,3 +557,4 @@ Expr * parseExprFromBuf(
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#pragma GCC diagnostic pop // end ignored "-Wswitch-enum"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue