decouple parser and EvalState
there's no reason the parser itself should be doing semantic analysis like bindVars. split this bit apart (retaining the previous name in EvalState) and have the parser really do *only* parsing, decoupled from EvalState.
This commit is contained in:
parent
e1aa585964
commit
b596cc9e79
|
@ -22,6 +22,7 @@
|
||||||
#include "fetch-to-store.hh"
|
#include "fetch-to-store.hh"
|
||||||
#include "tarball.hh"
|
#include "tarball.hh"
|
||||||
#include "flake/flakeref.hh"
|
#include "flake/flakeref.hh"
|
||||||
|
#include "parser-tab.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
@ -2800,6 +2801,21 @@ std::optional<std::string> EvalState::resolveSearchPathPath(const SearchPath::Pa
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Expr * EvalState::parse(
|
||||||
|
char * text,
|
||||||
|
size_t length,
|
||||||
|
Pos::Origin origin,
|
||||||
|
const SourcePath & basePath,
|
||||||
|
std::shared_ptr<StaticEnv> & staticEnv)
|
||||||
|
{
|
||||||
|
auto result = parseExprFromBuf(text, length, origin, basePath, symbols, positions, rootFS);
|
||||||
|
|
||||||
|
result->bindVars(*this, staticEnv);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string ExternalValueBase::coerceToString(const Pos & pos, NixStringContext & context, bool copyMore, bool copyToStore) const
|
std::string ExternalValueBase::coerceToString(const Pos & pos, NixStringContext & context, bool copyMore, bool copyToStore) const
|
||||||
{
|
{
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
|
|
|
@ -148,7 +148,7 @@ or { return OR_KW; }
|
||||||
} catch (const boost::bad_lexical_cast &) {
|
} catch (const boost::bad_lexical_cast &) {
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("invalid integer '%1%'", yytext),
|
.msg = hintfmt("invalid integer '%1%'", yytext),
|
||||||
.errPos = state->state.positions[CUR_POS],
|
.errPos = state->positions[CUR_POS],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return INT_LIT;
|
return INT_LIT;
|
||||||
|
@ -158,7 +158,7 @@ or { return OR_KW; }
|
||||||
if (errno != 0)
|
if (errno != 0)
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("invalid float '%1%'", yytext),
|
.msg = hintfmt("invalid float '%1%'", yytext),
|
||||||
.errPos = state->state.positions[CUR_POS],
|
.errPos = state->positions[CUR_POS],
|
||||||
});
|
});
|
||||||
return FLOAT_LIT;
|
return FLOAT_LIT;
|
||||||
}
|
}
|
||||||
|
@ -287,7 +287,7 @@ or { return OR_KW; }
|
||||||
<INPATH_SLASH><<EOF>> {
|
<INPATH_SLASH><<EOF>> {
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("path has a trailing slash"),
|
.msg = hintfmt("path has a trailing slash"),
|
||||||
.errPos = state->state.positions[CUR_POS],
|
.errPos = state->positions[CUR_POS],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,12 @@ struct ParserLocation {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ParserState {
|
struct ParserState {
|
||||||
EvalState & state;
|
|
||||||
SymbolTable & symbols;
|
SymbolTable & symbols;
|
||||||
|
PosTable & positions;
|
||||||
Expr * result;
|
Expr * result;
|
||||||
SourcePath basePath;
|
SourcePath basePath;
|
||||||
PosTable::Origin origin;
|
PosTable::Origin origin;
|
||||||
|
const ref<InputAccessor> rootFS;
|
||||||
|
|
||||||
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
|
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
|
||||||
void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos);
|
void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos);
|
||||||
|
@ -56,16 +57,16 @@ inline void ParserState::dupAttr(const AttrPath & attrPath, const PosIdx pos, co
|
||||||
{
|
{
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("attribute '%1%' already defined at %2%",
|
.msg = hintfmt("attribute '%1%' already defined at %2%",
|
||||||
showAttrPath(state.symbols, attrPath), state.positions[prevPos]),
|
showAttrPath(symbols, attrPath), positions[prevPos]),
|
||||||
.errPos = state.positions[pos]
|
.errPos = positions[pos]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ParserState::dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos)
|
inline void ParserState::dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos)
|
||||||
{
|
{
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("attribute '%1%' already defined at %2%", state.symbols[attr], state.positions[prevPos]),
|
.msg = hintfmt("attribute '%1%' already defined at %2%", symbols[attr], positions[prevPos]),
|
||||||
.errPos = state.positions[pos]
|
.errPos = positions[pos]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,13 +147,13 @@ inline Formals * ParserState::validateFormals(Formals * formals, PosIdx pos, Sym
|
||||||
if (duplicate)
|
if (duplicate)
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("duplicate formal function argument '%1%'", symbols[duplicate->first]),
|
.msg = hintfmt("duplicate formal function argument '%1%'", symbols[duplicate->first]),
|
||||||
.errPos = state.positions[duplicate->second]
|
.errPos = positions[duplicate->second]
|
||||||
});
|
});
|
||||||
|
|
||||||
if (arg && formals->has(arg))
|
if (arg && formals->has(arg))
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("duplicate formal function argument '%1%'", symbols[arg]),
|
.msg = hintfmt("duplicate formal function argument '%1%'", symbols[arg]),
|
||||||
.errPos = state.positions[pos]
|
.errPos = positions[pos]
|
||||||
});
|
});
|
||||||
|
|
||||||
return formals;
|
return formals;
|
||||||
|
@ -256,7 +257,7 @@ inline Expr * ParserState::stripIndentation(const PosIdx pos,
|
||||||
|
|
||||||
inline PosIdx ParserState::at(const ParserLocation & loc)
|
inline PosIdx ParserState::at(const ParserLocation & loc)
|
||||||
{
|
{
|
||||||
return state.positions.add(origin, loc.first_line, loc.first_column);
|
return positions.add(origin, loc.first_line, loc.first_column);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,19 @@
|
||||||
#define YY_DECL int yylex \
|
#define YY_DECL int yylex \
|
||||||
(YYSTYPE * yylval_param, YYLTYPE * yylloc_param, yyscan_t yyscanner, nix::ParserState * state)
|
(YYSTYPE * yylval_param, YYLTYPE * yylloc_param, yyscan_t yyscanner, nix::ParserState * state)
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
Expr * parseExprFromBuf(
|
||||||
|
char * text,
|
||||||
|
size_t length,
|
||||||
|
Pos::Origin origin,
|
||||||
|
const SourcePath & basePath,
|
||||||
|
SymbolTable & symbols,
|
||||||
|
PosTable & positions,
|
||||||
|
const ref<InputAccessor> rootFS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -52,7 +65,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParserState * state, const char *
|
||||||
{
|
{
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt(error),
|
.msg = hintfmt(error),
|
||||||
.errPos = state->state.positions[state->at(*loc)]
|
.errPos = state->positions[state->at(*loc)]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +154,7 @@ expr_function
|
||||||
{ if (!$2->dynamicAttrs.empty())
|
{ if (!$2->dynamicAttrs.empty())
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("dynamic attributes not allowed in let"),
|
.msg = hintfmt("dynamic attributes not allowed in let"),
|
||||||
.errPos = state->state.positions[CUR_POS]
|
.errPos = state->positions[CUR_POS]
|
||||||
});
|
});
|
||||||
$$ = new ExprLet($2, $4);
|
$$ = new ExprLet($2, $4);
|
||||||
}
|
}
|
||||||
|
@ -231,7 +244,7 @@ expr_simple
|
||||||
if (noURLLiterals)
|
if (noURLLiterals)
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("URL literals are disabled"),
|
.msg = hintfmt("URL literals are disabled"),
|
||||||
.errPos = state->state.positions[CUR_POS]
|
.errPos = state->positions[CUR_POS]
|
||||||
});
|
});
|
||||||
$$ = new ExprString(std::string($1));
|
$$ = new ExprString(std::string($1));
|
||||||
}
|
}
|
||||||
|
@ -271,7 +284,7 @@ path_start
|
||||||
/* add back in the trailing '/' to the first segment */
|
/* add back in the trailing '/' to the first segment */
|
||||||
if ($1.p[$1.l-1] == '/' && $1.l > 1)
|
if ($1.p[$1.l-1] == '/' && $1.l > 1)
|
||||||
path += "/";
|
path += "/";
|
||||||
$$ = new ExprPath(ref<InputAccessor>(state->state.rootFS), std::move(path));
|
$$ = new ExprPath(ref<InputAccessor>(state->rootFS), std::move(path));
|
||||||
}
|
}
|
||||||
| HPATH {
|
| HPATH {
|
||||||
if (evalSettings.pureEval) {
|
if (evalSettings.pureEval) {
|
||||||
|
@ -281,7 +294,7 @@ path_start
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Path path(getHome() + std::string($1.p + 1, $1.l - 1));
|
Path path(getHome() + std::string($1.p + 1, $1.l - 1));
|
||||||
$$ = new ExprPath(ref<InputAccessor>(state->state.rootFS), std::move(path));
|
$$ = new ExprPath(ref<InputAccessor>(state->rootFS), std::move(path));
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -327,7 +340,7 @@ attrs
|
||||||
} else
|
} else
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("dynamic attributes not allowed in inherit"),
|
.msg = hintfmt("dynamic attributes not allowed in inherit"),
|
||||||
.errPos = state->state.positions[state->at(@2)]
|
.errPos = state->positions[state->at(@2)]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
| { $$ = new AttrPath; }
|
| { $$ = new AttrPath; }
|
||||||
|
@ -394,19 +407,22 @@ formal
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
Expr * EvalState::parse(
|
Expr * parseExprFromBuf(
|
||||||
char * text,
|
char * text,
|
||||||
size_t length,
|
size_t length,
|
||||||
Pos::Origin origin,
|
Pos::Origin origin,
|
||||||
const SourcePath & basePath,
|
const SourcePath & basePath,
|
||||||
std::shared_ptr<StaticEnv> & staticEnv)
|
SymbolTable & symbols,
|
||||||
|
PosTable & positions,
|
||||||
|
const ref<InputAccessor> rootFS)
|
||||||
{
|
{
|
||||||
yyscan_t scanner;
|
yyscan_t scanner;
|
||||||
ParserState state {
|
ParserState state {
|
||||||
.state = *this,
|
|
||||||
.symbols = symbols,
|
.symbols = symbols,
|
||||||
|
.positions = positions,
|
||||||
.basePath = basePath,
|
.basePath = basePath,
|
||||||
.origin = {origin},
|
.origin = {origin},
|
||||||
|
.rootFS = rootFS,
|
||||||
};
|
};
|
||||||
|
|
||||||
yylex_init(&scanner);
|
yylex_init(&scanner);
|
||||||
|
@ -415,8 +431,6 @@ Expr * EvalState::parse(
|
||||||
yy_scan_buffer(text, length, scanner);
|
yy_scan_buffer(text, length, scanner);
|
||||||
yyparse(scanner, &state);
|
yyparse(scanner, &state);
|
||||||
|
|
||||||
state.result->bindVars(*this, staticEnv);
|
|
||||||
|
|
||||||
return state.result;
|
return state.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue