aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreldritch horrors <pennae@lix.systems>2024-03-08 05:35:12 +0100
committereldritch horrors <pennae@lix.systems>2024-03-09 00:25:54 -0700
commit92693973b6e059e9d6056cf6547cc66459efc580 (patch)
tree9194588c9a016787219b13f34a93cf80647c5bca
parentfaaae9d045c392894ed78d9f9466ce2968f9bcb4 (diff)
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. (cherry picked from commit b596cc9e7960b9256bcd557334d81e9d555be5a2) Change-Id: I481a7623afc783e9d28a6eb4627552cf8a780986
-rw-r--r--src/libexpr/eval.cc17
-rw-r--r--src/libexpr/lexer.l6
-rw-r--r--src/libexpr/parser-state.hh16
-rw-r--r--src/libexpr/parser.y29
4 files changed, 48 insertions, 20 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 35b09f4d5..2a6a89ddb 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -17,6 +17,7 @@
#include "gc-small-vector.hh"
#include "fetch-to-store.hh"
#include "flake/flakeref.hh"
+#include "parser-tab.hh"
#include <algorithm>
#include <chrono>
@@ -2806,6 +2807,22 @@ std::optional<std::string> EvalState::resolveSearchPathPath(const SearchPath::Pa
return res;
}
+
+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);
+
+ result->bindVars(*this, staticEnv);
+
+ return result;
+}
+
+
std::string ExternalValueBase::coerceToString(const Pos & pos, NixStringContext & context, bool copyMore, bool copyToStore) const
{
throw TypeError({
diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l
index 2d6f8dc47..6f7a9cd6b 100644
--- a/src/libexpr/lexer.l
+++ b/src/libexpr/lexer.l
@@ -154,7 +154,7 @@ or { return OR_KW; }
} catch (const boost::bad_lexical_cast &) {
throw ParseError({
.msg = hintfmt("invalid integer '%1%'", yytext),
- .errPos = state->state.positions[CUR_POS],
+ .errPos = state->positions[CUR_POS],
});
}
return INT;
@@ -164,7 +164,7 @@ or { return OR_KW; }
if (errno != 0)
throw ParseError({
.msg = hintfmt("invalid float '%1%'", yytext),
- .errPos = state->state.positions[CUR_POS],
+ .errPos = state->positions[CUR_POS],
});
return FLOAT;
}
@@ -293,7 +293,7 @@ or { return OR_KW; }
<INPATH_SLASH><<EOF>> {
throw ParseError({
.msg = hintfmt("path has a trailing slash"),
- .errPos = state->state.positions[CUR_POS],
+ .errPos = state->positions[CUR_POS],
});
}
diff --git a/src/libexpr/parser-state.hh b/src/libexpr/parser-state.hh
index 167d3f4ae..34863c001 100644
--- a/src/libexpr/parser-state.hh
+++ b/src/libexpr/parser-state.hh
@@ -37,8 +37,8 @@ struct ParserLocation {
};
struct ParserState {
- EvalState & state;
SymbolTable & symbols;
+ PosTable & positions;
Expr * result;
SourcePath basePath;
PosTable::Origin origin;
@@ -56,16 +56,16 @@ inline void ParserState::dupAttr(const AttrPath & attrPath, const PosIdx pos, co
{
throw ParseError({
.msg = hintfmt("attribute '%1%' already defined at %2%",
- showAttrPath(state.symbols, attrPath), state.positions[prevPos]),
- .errPos = state.positions[pos]
+ showAttrPath(symbols, attrPath), positions[prevPos]),
+ .errPos = positions[pos]
});
}
inline void ParserState::dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos)
{
throw ParseError({
- .msg = hintfmt("attribute '%1%' already defined at %2%", state.symbols[attr], state.positions[prevPos]),
- .errPos = state.positions[pos]
+ .msg = hintfmt("attribute '%1%' already defined at %2%", symbols[attr], positions[prevPos]),
+ .errPos = positions[pos]
});
}
@@ -146,13 +146,13 @@ inline Formals * ParserState::validateFormals(Formals * formals, PosIdx pos, Sym
if (duplicate)
throw ParseError({
.msg = hintfmt("duplicate formal function argument '%1%'", symbols[duplicate->first]),
- .errPos = state.positions[duplicate->second]
+ .errPos = positions[duplicate->second]
});
if (arg && formals->has(arg))
throw ParseError({
.msg = hintfmt("duplicate formal function argument '%1%'", symbols[arg]),
- .errPos = state.positions[pos]
+ .errPos = positions[pos]
});
return formals;
@@ -256,7 +256,7 @@ inline Expr * ParserState::stripIndentation(const PosIdx pos,
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);
}
}
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 0d28d7961..5027b7b99 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -31,6 +31,18 @@
#define YY_DECL int yylex \
(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);
+
+}
+
#endif
}
@@ -51,7 +63,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParserState * state, const char *
{
throw ParseError({
.msg = hintfmt(error),
- .errPos = state->state.positions[state->at(*loc)]
+ .errPos = state->positions[state->at(*loc)]
});
}
@@ -140,7 +152,7 @@ expr_function
{ if (!$2->dynamicAttrs.empty())
throw ParseError({
.msg = hintfmt("dynamic attributes not allowed in let"),
- .errPos = state->state.positions[CUR_POS]
+ .errPos = state->positions[CUR_POS]
});
$$ = new ExprLet($2, $4);
}
@@ -230,7 +242,7 @@ expr_simple
if (noURLLiterals)
throw ParseError({
.msg = hintfmt("URL literals are disabled"),
- .errPos = state->state.positions[CUR_POS]
+ .errPos = state->positions[CUR_POS]
});
$$ = new ExprString(std::string($1));
}
@@ -326,7 +338,7 @@ attrs
} else
throw ParseError({
.msg = hintfmt("dynamic attributes not allowed in inherit"),
- .errPos = state->state.positions[state->at(@2)]
+ .errPos = state->positions[state->at(@2)]
});
}
| { $$ = new AttrPath; }
@@ -393,17 +405,18 @@ formal
namespace nix {
-Expr * EvalState::parse(
+Expr * parseExprFromBuf(
char * text,
size_t length,
Pos::Origin origin,
const SourcePath & basePath,
- std::shared_ptr<StaticEnv> & staticEnv)
+ SymbolTable & symbols,
+ PosTable & positions)
{
yyscan_t scanner;
ParserState state {
- .state = *this,
.symbols = symbols,
+ .positions = positions,
.basePath = basePath,
.origin = {origin},
};
@@ -414,8 +427,6 @@ Expr * EvalState::parse(
yy_scan_buffer(text, length, scanner);
yyparse(scanner, &state);
- state.result->bindVars(*this, staticEnv);
-
return state.result;
}