2023-04-16 14:10:45 +03:00
|
|
|
#include "print.hh"
|
2023-05-09 17:45:12 +03:00
|
|
|
#include <unordered_set>
|
2023-04-09 23:42:20 +03:00
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
|
|
|
std::ostream &
|
2023-04-16 13:56:31 +03:00
|
|
|
printLiteralString(std::ostream & str, const std::string_view string)
|
2023-04-15 21:56:51 +03:00
|
|
|
{
|
2023-04-09 23:42:20 +03:00
|
|
|
str << "\"";
|
|
|
|
for (auto i = string.begin(); i != string.end(); ++i) {
|
|
|
|
if (*i == '\"' || *i == '\\') str << "\\" << *i;
|
|
|
|
else if (*i == '\n') str << "\\n";
|
|
|
|
else if (*i == '\r') str << "\\r";
|
|
|
|
else if (*i == '\t') str << "\\t";
|
|
|
|
else if (*i == '$' && *(i+1) == '{') str << "\\" << *i;
|
|
|
|
else str << *i;
|
|
|
|
}
|
|
|
|
str << "\"";
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream &
|
2023-04-16 13:56:31 +03:00
|
|
|
printLiteralBool(std::ostream & str, bool boolean)
|
2023-04-15 21:56:51 +03:00
|
|
|
{
|
2023-04-09 23:42:20 +03:00
|
|
|
str << (boolean ? "true" : "false");
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2023-05-09 17:45:12 +03:00
|
|
|
// Returns `true' is a string is a reserved keyword which requires quotation
|
|
|
|
// when printing attribute set field names.
|
|
|
|
//
|
|
|
|
// This list should generally be kept in sync with `./lexer.l'.
|
|
|
|
// You can test if a keyword needs to be added by running:
|
|
|
|
// $ nix eval --expr '{ <KEYWORD> = 1; }'
|
|
|
|
// For example `or' doesn't need to be quoted.
|
|
|
|
bool isReservedKeyword(const std::string_view str)
|
|
|
|
{
|
|
|
|
static const std::unordered_set<std::string_view> reservedKeywords = {
|
|
|
|
"if", "then", "else", "assert", "with", "let", "in", "rec", "inherit"
|
|
|
|
};
|
|
|
|
return reservedKeywords.contains(str);
|
|
|
|
}
|
|
|
|
|
2023-04-16 15:07:35 +03:00
|
|
|
std::ostream &
|
|
|
|
printIdentifier(std::ostream & str, std::string_view s) {
|
|
|
|
if (s.empty())
|
|
|
|
str << "\"\"";
|
2023-05-09 17:45:12 +03:00
|
|
|
else if (isReservedKeyword(s))
|
2023-04-16 15:07:35 +03:00
|
|
|
str << '"' << s << '"';
|
|
|
|
else {
|
|
|
|
char c = s[0];
|
|
|
|
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')) {
|
|
|
|
printLiteralString(str, s);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
for (auto c : s)
|
|
|
|
if (!((c >= 'a' && c <= 'z') ||
|
|
|
|
(c >= 'A' && c <= 'Z') ||
|
|
|
|
(c >= '0' && c <= '9') ||
|
|
|
|
c == '_' || c == '\'' || c == '-')) {
|
|
|
|
printLiteralString(str, s);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
str << s;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isVarName(std::string_view s)
|
|
|
|
{
|
|
|
|
if (s.size() == 0) return false;
|
2023-05-09 17:45:12 +03:00
|
|
|
if (isReservedKeyword(s)) return false;
|
2023-04-16 15:07:35 +03:00
|
|
|
char c = s[0];
|
|
|
|
if ((c >= '0' && c <= '9') || c == '-' || c == '\'') return false;
|
|
|
|
for (auto & i : s)
|
|
|
|
if (!((i >= 'a' && i <= 'z') ||
|
|
|
|
(i >= 'A' && i <= 'Z') ||
|
|
|
|
(i >= '0' && i <= '9') ||
|
|
|
|
i == '_' || i == '-' || i == '\''))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream &
|
|
|
|
printAttributeName(std::ostream & str, std::string_view name) {
|
|
|
|
if (isVarName(name))
|
|
|
|
str << name;
|
|
|
|
else
|
|
|
|
printLiteralString(str, name);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-04-09 23:42:20 +03:00
|
|
|
}
|