From b596cc9e7960b9256bcd557334d81e9d555be5a2 Mon Sep 17 00:00:00 2001 From: pennae Date: Mon, 15 Jan 2024 16:52:18 +0100 Subject: [PATCH] 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. --- src/libexpr/eval.cc | 16 ++++++++++++++++ src/libexpr/lexer.l | 6 +++--- src/libexpr/parser-state.hh | 17 +++++++++-------- src/libexpr/parser.y | 36 +++++++++++++++++++++++++----------- 4 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 6eee7cdce..b05ccfc85 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -22,6 +22,7 @@ #include "fetch-to-store.hh" #include "tarball.hh" #include "flake/flakeref.hh" +#include "parser-tab.hh" #include #include @@ -2800,6 +2801,21 @@ std::optional EvalState::resolveSearchPathPath(const SearchPath::Pa } +Expr * EvalState::parse( + char * text, + size_t length, + Pos::Origin origin, + const SourcePath & basePath, + std::shared_ptr & 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 { throw TypeError({ diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index fae0e7a85..d7a0b5048 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -148,7 +148,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_LIT; @@ -158,7 +158,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_LIT; } @@ -287,7 +287,7 @@ or { return OR_KW; } <> { 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..6ab9fc962 100644 --- a/src/libexpr/parser-state.hh +++ b/src/libexpr/parser-state.hh @@ -37,11 +37,12 @@ struct ParserLocation { }; struct ParserState { - EvalState & state; SymbolTable & symbols; + PosTable & positions; Expr * result; SourcePath basePath; PosTable::Origin origin; + const ref rootFS; void dupAttr(const AttrPath & attrPath, 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({ .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 +147,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 +257,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 519d6b11f..faf5e897f 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -32,6 +32,19 @@ #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, + const ref rootFS); + +} + #endif } @@ -52,7 +65,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)] }); } @@ -141,7 +154,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); } @@ -231,7 +244,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)); } @@ -271,7 +284,7 @@ path_start /* add back in the trailing '/' to the first segment */ if ($1.p[$1.l-1] == '/' && $1.l > 1) path += "/"; - $$ = new ExprPath(ref(state->state.rootFS), std::move(path)); + $$ = new ExprPath(ref(state->rootFS), std::move(path)); } | HPATH { if (evalSettings.pureEval) { @@ -281,7 +294,7 @@ path_start ); } Path path(getHome() + std::string($1.p + 1, $1.l - 1)); - $$ = new ExprPath(ref(state->state.rootFS), std::move(path)); + $$ = new ExprPath(ref(state->rootFS), std::move(path)); } ; @@ -327,7 +340,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; } @@ -394,19 +407,22 @@ formal namespace nix { -Expr * EvalState::parse( +Expr * parseExprFromBuf( char * text, size_t length, Pos::Origin origin, const SourcePath & basePath, - std::shared_ptr & staticEnv) + SymbolTable & symbols, + PosTable & positions, + const ref rootFS) { yyscan_t scanner; ParserState state { - .state = *this, .symbols = symbols, + .positions = positions, .basePath = basePath, .origin = {origin}, + .rootFS = rootFS, }; yylex_init(&scanner); @@ -415,8 +431,6 @@ Expr * EvalState::parse( yy_scan_buffer(text, length, scanner); yyparse(scanner, &state); - state.result->bindVars(*this, staticEnv); - return state.result; }