mirror of
https://github.com/NixOS/nix.git
synced 2025-11-08 19:46:02 +01:00
libexpr: Switch parser.y to %skeleton lalr1.cc
Since the parser is now LALR we can easily switch over to the less ugly sketelon than the default C one. This would allow us to switch from %union to %define api.value.type variant in the future to avoid the need for triviall POD types.
This commit is contained in:
parent
241c7cd1f9
commit
a8715a2d6e
6 changed files with 51 additions and 33 deletions
|
|
@ -24,7 +24,6 @@ struct StringToken
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This type must be trivially copyable; see YYLTYPE_IS_TRIVIAL in parser.y.
|
|
||||||
struct ParserLocation
|
struct ParserLocation
|
||||||
{
|
{
|
||||||
int beginOffset;
|
int beginOffset;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
#include "lexer-helpers.hh"
|
#include "lexer-helpers.hh"
|
||||||
|
|
||||||
void nix::lexer::internal::initLoc(YYLTYPE * loc)
|
void nix::lexer::internal::initLoc(Parser::location_type * loc)
|
||||||
{
|
{
|
||||||
loc->beginOffset = loc->endOffset = 0;
|
loc->beginOffset = loc->endOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nix::lexer::internal::adjustLoc(yyscan_t yyscanner, YYLTYPE * loc, const char * s, size_t len)
|
void nix::lexer::internal::adjustLoc(yyscan_t yyscanner, Parser::location_type * loc, const char * s, size_t len)
|
||||||
{
|
{
|
||||||
loc->stash();
|
loc->stash();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,12 @@
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
// including the generated headers twice leads to errors
|
#include "parser-scanner-decls.hh"
|
||||||
#ifndef BISON_HEADER
|
|
||||||
# include "lexer-tab.hh"
|
|
||||||
# include "parser-tab.hh"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace nix::lexer::internal {
|
namespace nix::lexer::internal {
|
||||||
|
|
||||||
void initLoc(YYLTYPE * loc);
|
void initLoc(Parser::location_type * loc);
|
||||||
|
|
||||||
void adjustLoc(yyscan_t yyscanner, YYLTYPE * loc, const char * s, size_t len);
|
void adjustLoc(yyscan_t yyscanner, Parser::location_type * loc, const char * s, size_t len);
|
||||||
|
|
||||||
} // namespace nix::lexer::internal
|
} // namespace nix::lexer::internal
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,10 @@ static void requireExperimentalFeature(const ExperimentalFeature & feature, cons
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using enum nix::Parser::token::token_kind_type;
|
||||||
|
using YYSTYPE = nix::Parser::value_type;
|
||||||
|
using YYLTYPE = nix::Parser::location_type;
|
||||||
|
|
||||||
// yacc generates code that uses unannotated fallthrough.
|
// yacc generates code that uses unannotated fallthrough.
|
||||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||||
|
|
||||||
|
|
|
||||||
17
src/libexpr/parser-scanner-decls.hh
Normal file
17
src/libexpr/parser-scanner-decls.hh
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef BISON_HEADER
|
||||||
|
# include "parser-tab.hh"
|
||||||
|
using YYSTYPE = nix::parser::BisonParser::value_type;
|
||||||
|
using YYLTYPE = nix::parser::BisonParser::location_type;
|
||||||
|
# include "lexer-tab.hh" // IWYU pragma: export
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
class Parser : public parser::BisonParser
|
||||||
|
{
|
||||||
|
using BisonParser::BisonParser;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nix
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
%skeleton "lalr1.cc"
|
||||||
%define api.location.type { ::nix::ParserLocation }
|
%define api.location.type { ::nix::ParserLocation }
|
||||||
%define api.pure
|
%define api.namespace { ::nix::parser }
|
||||||
|
%define api.parser.class { BisonParser }
|
||||||
%locations
|
%locations
|
||||||
%define parse.error verbose
|
%define parse.error verbose
|
||||||
%defines
|
%defines
|
||||||
|
|
@ -26,19 +28,12 @@
|
||||||
#include "nix/expr/eval-settings.hh"
|
#include "nix/expr/eval-settings.hh"
|
||||||
#include "nix/expr/parser-state.hh"
|
#include "nix/expr/parser-state.hh"
|
||||||
|
|
||||||
// Bison seems to have difficulty growing the parser stack when using C++ with
|
#define YY_DECL \
|
||||||
// a custom location type. This undocumented macro tells Bison that our
|
int yylex( \
|
||||||
// location type is "trivially copyable" in C++-ese, so it is safe to use the
|
nix::Parser::value_type * yylval_param, \
|
||||||
// same memcpy macro it uses to grow the stack that it uses with its own
|
nix::Parser::location_type * yylloc_param, \
|
||||||
// default location type. Without this, we get "error: memory exhausted" when
|
yyscan_t yyscanner, \
|
||||||
// parsing some large Nix files. Our other options are to increase the initial
|
nix::ParserState * state)
|
||||||
// stack size (200 by default) to be as large as we ever want to support (so
|
|
||||||
// that growing the stack is unnecessary), or redefine the stack-relocation
|
|
||||||
// macro ourselves (which is also undocumented).
|
|
||||||
#define YYLTYPE_IS_TRIVIAL 1
|
|
||||||
|
|
||||||
#define YY_DECL int yylex \
|
|
||||||
(YYSTYPE * yylval_param, YYLTYPE * yylloc_param, yyscan_t yyscanner, nix::ParserState * state)
|
|
||||||
|
|
||||||
// For efficiency, we only track offsets; not line,column coordinates
|
// For efficiency, we only track offsets; not line,column coordinates
|
||||||
# define YYLLOC_DEFAULT(Current, Rhs, N) \
|
# define YYLLOC_DEFAULT(Current, Rhs, N) \
|
||||||
|
|
@ -78,24 +73,30 @@ Expr * parseExprFromBuf(
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
||||||
#include "parser-tab.hh"
|
/* The parser is very performance sensitive and loses out on a lot
|
||||||
#include "lexer-tab.hh"
|
of performance even with basic stdlib assertions. Since those don't
|
||||||
|
affect ABI we can disable those just for this file. */
|
||||||
|
#if defined(_GLIBCXX_ASSERTIONS) && !defined(_GLIBCXX_DEBUG)
|
||||||
|
#undef _GLIBCXX_ASSERTIONS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "parser-scanner-decls.hh"
|
||||||
|
|
||||||
YY_DECL;
|
YY_DECL;
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
#define CUR_POS state->at(yyloc)
|
#define CUR_POS state->at(yylhs.location)
|
||||||
|
|
||||||
|
void parser::BisonParser::error(const location_type &loc_, const std::string &error)
|
||||||
void yyerror(YYLTYPE * loc, yyscan_t scanner, ParserState * state, const char * error)
|
|
||||||
{
|
{
|
||||||
|
auto loc = loc_;
|
||||||
if (std::string_view(error).starts_with("syntax error, unexpected end of file")) {
|
if (std::string_view(error).starts_with("syntax error, unexpected end of file")) {
|
||||||
loc->beginOffset = loc->endOffset;
|
loc.beginOffset = loc.endOffset;
|
||||||
}
|
}
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = HintFmt(error),
|
.msg = HintFmt(error),
|
||||||
.pos = state->positions[state->at(*loc)]
|
.pos = state->positions[state->at(loc)]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,7 +183,7 @@ start: expr {
|
||||||
state->result = $1;
|
state->result = $1;
|
||||||
|
|
||||||
// This parser does not use yynerrs; suppress the warning.
|
// This parser does not use yynerrs; suppress the warning.
|
||||||
(void) yynerrs;
|
(void) yynerrs_;
|
||||||
};
|
};
|
||||||
|
|
||||||
expr: expr_function;
|
expr: expr_function;
|
||||||
|
|
@ -563,7 +564,8 @@ Expr * parseExprFromBuf(
|
||||||
Finally _destroy([&] { yylex_destroy(scanner); });
|
Finally _destroy([&] { yylex_destroy(scanner); });
|
||||||
|
|
||||||
yy_scan_buffer(text, length, scanner);
|
yy_scan_buffer(text, length, scanner);
|
||||||
yyparse(scanner, &state);
|
Parser parser(scanner, &state);
|
||||||
|
parser.parse();
|
||||||
|
|
||||||
return state.result;
|
return state.result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue