From 81f68519aa937662b969f9353393ad156121be93 Mon Sep 17 00:00:00 2001 From: Ulya Trofimovich Date: Mon, 18 Mar 2024 17:35:23 +0000 Subject: [PATCH] Merge syntax.{h,cc} into opt.{h,cc} and get rid of `Stx` struct. Syntax file handling is completely tied up with option handling, there's no need to maintain separate infrastructure for syntax configurations. --- CMakeLists.txt | 2 - Makefile.am | 2 - Makefile.lib.am | 2 - bootstrap/src/parse/conf_lexer.cc | 2 +- bootstrap/src/parse/conf_parser.cc | 131 ++++++++-------- bootstrap/src/parse/conf_parser.h | 4 +- src/codegen/output.h | 2 +- src/codegen/pass1_analyze.cc | 1 + src/codegen/pass2_generate.cc | 1 - src/codegen/pass4_render.cc | 1 - src/options/opt.cc | 230 +++++++++++++++++++++++++++-- src/options/opt.h | 167 ++++++++++++++++++--- src/options/syntax.cc | 220 --------------------------- src/options/syntax.h | 178 ---------------------- src/parse/conf_lexer.re | 2 +- src/parse/conf_parser.ypp | 46 +++--- src/parse/input.h | 1 - 17 files changed, 461 insertions(+), 531 deletions(-) delete mode 100644 src/options/syntax.cc delete mode 100644 src/options/syntax.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ed17fbb6..0c7b94c8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,7 +147,6 @@ set(re2c_sources src/codegen/pass4_render.cc src/options/opt.cc src/options/symtab.cc - src/options/syntax.cc src/nfa/re_to_nfa.cc src/adfa/adfa.cc src/debug/dump_adfa.cc @@ -482,7 +481,6 @@ if (RE2C_BUILD_LIBS) src/parse/input.cc src/options/opt.cc src/options/symtab.cc - src/options/syntax.cc src/cfg/cfg.cc src/cfg/compact.cc src/cfg/dce.cc diff --git a/Makefile.am b/Makefile.am index c3cf574d0..0fb202c50 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,6 @@ re2c_HDR = \ src/codegen/helpers.h \ src/options/opt.h \ src/options/symtab.h \ - src/options/syntax.h \ src/adfa/adfa.h \ src/cfg/cfg.h \ src/dfa/closure_leftmost.h \ @@ -75,7 +74,6 @@ re2c_SRC = \ src/codegen/pass4_render.cc \ src/options/opt.cc \ src/options/symtab.cc \ - src/options/syntax.cc \ src/nfa/re_to_nfa.cc \ src/adfa/adfa.cc \ src/debug/dump_adfa.cc \ diff --git a/Makefile.lib.am b/Makefile.lib.am index 4cd827e0e..acdbe7b22 100644 --- a/Makefile.lib.am +++ b/Makefile.lib.am @@ -15,7 +15,6 @@ libre2c_la_HDR = \ src/codegen/code.h \ src/options/opt.h \ src/options/symtab.h \ - src/options/syntax.h \ src/adfa/adfa.h \ src/cfg/cfg.h \ src/dfa/closure_leftmost.h \ @@ -72,7 +71,6 @@ libre2c_la_SRC = \ src/parse/input.cc \ src/options/opt.cc \ src/options/symtab.cc \ - src/options/syntax.cc \ src/cfg/cfg.cc \ src/cfg/compact.cc \ src/cfg/dce.cc \ diff --git a/bootstrap/src/parse/conf_lexer.cc b/bootstrap/src/parse/conf_lexer.cc index eead39a4d..e64e2d807 100644 --- a/bootstrap/src/parse/conf_lexer.cc +++ b/bootstrap/src/parse/conf_lexer.cc @@ -8802,7 +8802,7 @@ Ret Input::lex_syntax_file(Opt& opts) { ++cur; cur -= 5; #line 654 "../src/parse/conf_lexer.re" - { if (conf_parse(*this, opts, opts.stx) != 0) return Ret::FAIL; goto start; } + { if (conf_parse(*this, opts) != 0) return Ret::FAIL; goto start; } #line 8807 "src/parse/conf_lexer.cc" yy1614: ++cur; diff --git a/bootstrap/src/parse/conf_parser.cc b/bootstrap/src/parse/conf_parser.cc index f16f9f8c9..b77017119 100644 --- a/bootstrap/src/parse/conf_parser.cc +++ b/bootstrap/src/parse/conf_parser.cc @@ -76,6 +76,7 @@ #line 8 "../src/parse/conf_parser.ypp" +#include "src/msg/msg.h" #include "src/options/opt.h" #include "src/parse/input.h" #include "src/parse/conf_parser.h" @@ -83,12 +84,12 @@ using namespace re2c; extern "C" { - static void yyerror(Input& in, Opt& opts, Stx& stx, const char* s); + static void yyerror(Input& in, Opt& opts, const char* s); static int yylex(CONF_STYPE* yylval, Input& in, Opt& opts); } -#line 92 "src/parse/conf_parser.cc" +#line 93 "src/parse/conf_parser.cc" # ifndef YY_CAST # ifdef __cplusplus @@ -706,7 +707,7 @@ enum { YYENOMEM = -2 }; } \ else \ { \ - yyerror (in, opts, stx, YY_("syntax error: cannot back up")); \ + yyerror (in, opts, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (0) @@ -739,7 +740,7 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Kind, Value, in, opts, stx); \ + Kind, Value, in, opts); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) @@ -751,13 +752,12 @@ do { \ static void yy_symbol_value_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, re2c::Input& in, re2c::Opt& opts, re2c::Stx& stx) + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, re2c::Input& in, re2c::Opt& opts) { FILE *yyoutput = yyo; YY_USE (yyoutput); YY_USE (in); YY_USE (opts); - YY_USE (stx); if (!yyvaluep) return; YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN @@ -772,12 +772,12 @@ yy_symbol_value_print (FILE *yyo, static void yy_symbol_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, re2c::Input& in, re2c::Opt& opts, re2c::Stx& stx) + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, re2c::Input& in, re2c::Opt& opts) { YYFPRINTF (yyo, "%s %s (", yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); - yy_symbol_value_print (yyo, yykind, yyvaluep, in, opts, stx); + yy_symbol_value_print (yyo, yykind, yyvaluep, in, opts); YYFPRINTF (yyo, ")"); } @@ -811,7 +811,7 @@ do { \ static void yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, - int yyrule, re2c::Input& in, re2c::Opt& opts, re2c::Stx& stx) + int yyrule, re2c::Input& in, re2c::Opt& opts) { int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; @@ -824,7 +824,7 @@ yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), - &yyvsp[(yyi + 1) - (yynrhs)], in, opts, stx); + &yyvsp[(yyi + 1) - (yynrhs)], in, opts); YYFPRINTF (stderr, "\n"); } } @@ -832,7 +832,7 @@ yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, Rule, in, opts, stx); \ + yy_reduce_print (yyssp, yyvsp, Rule, in, opts); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that @@ -873,12 +873,11 @@ int yydebug; static void yydestruct (const char *yymsg, - yysymbol_kind_t yykind, YYSTYPE *yyvaluep, re2c::Input& in, re2c::Opt& opts, re2c::Stx& stx) + yysymbol_kind_t yykind, YYSTYPE *yyvaluep, re2c::Input& in, re2c::Opt& opts) { YY_USE (yyvaluep); YY_USE (in); YY_USE (opts); - YY_USE (stx); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); @@ -898,7 +897,7 @@ yydestruct (const char *yymsg, `----------*/ int -yyparse (re2c::Input& in, re2c::Opt& opts, re2c::Stx& stx) +yyparse (re2c::Input& in, re2c::Opt& opts) { /* Lookahead token kind. */ int yychar; @@ -1155,61 +1154,61 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); case 2: /* conf: '=' num */ #line 70 "../src/parse/conf_parser.ypp" { in.save_conf_num((yyvsp[0].num)); } -#line 1159 "src/parse/conf_parser.cc" +#line 1158 "src/parse/conf_parser.cc" break; case 3: /* conf: '=' str */ #line 71 "../src/parse/conf_parser.ypp" { in.save_conf_str((yyvsp[0].str)); } -#line 1165 "src/parse/conf_parser.cc" +#line 1164 "src/parse/conf_parser.cc" break; case 4: /* conf: '=' list */ #line 72 "../src/parse/conf_parser.ypp" { in.save_conf_list((yyvsp[0].list)); } -#line 1171 "src/parse/conf_parser.cc" +#line 1170 "src/parse/conf_parser.cc" break; case 5: /* conf: CONF_CODE '=' code_exprs */ #line 73 "../src/parse/conf_parser.ypp" { *(yyvsp[-2].codeptr) = (yyvsp[0].codes); } -#line 1177 "src/parse/conf_parser.cc" +#line 1176 "src/parse/conf_parser.cc" break; case 6: /* conf: CONF_CODE '=' CONF_CODE */ #line 74 "../src/parse/conf_parser.ypp" { *(yyvsp[-2].codeptr) = *(yyvsp[0].codeptr); } -#line 1183 "src/parse/conf_parser.cc" +#line 1182 "src/parse/conf_parser.cc" break; case 7: /* num: CONF_NUMBER */ #line 77 "../src/parse/conf_parser.ypp" { (yyval.num) = (yyvsp[0].num); } -#line 1189 "src/parse/conf_parser.cc" +#line 1188 "src/parse/conf_parser.cc" break; case 8: /* num: CONF_COND '?' num ':' num ')' */ #line 78 "../src/parse/conf_parser.ypp" { (yyval.num) = (yyvsp[-5].cond) ? (yyvsp[-3].num) : (yyvsp[-1].num); } -#line 1195 "src/parse/conf_parser.cc" +#line 1194 "src/parse/conf_parser.cc" break; case 10: /* str: CONF_COND '?' str ':' str ')' */ #line 82 "../src/parse/conf_parser.ypp" { (yyval.str) = (yyvsp[-5].cond) ? (yyvsp[-3].str) : (yyvsp[-1].str); } -#line 1201 "src/parse/conf_parser.cc" +#line 1200 "src/parse/conf_parser.cc" break; case 11: /* list: '[' ']' */ #line 85 "../src/parse/conf_parser.ypp" { (yyval.list) = in.get_tmp_list(); } -#line 1207 "src/parse/conf_parser.cc" +#line 1206 "src/parse/conf_parser.cc" break; case 12: /* list: '[' elems ']' */ #line 86 "../src/parse/conf_parser.ypp" { (yyval.list) = (yyvsp[-1].list); } -#line 1213 "src/parse/conf_parser.cc" +#line 1212 "src/parse/conf_parser.cc" break; case 13: /* elems: CONF_STRING */ @@ -1218,7 +1217,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.list) = in.get_tmp_list(); (yyval.list)->push_back((yyvsp[0].str)); } -#line 1222 "src/parse/conf_parser.cc" +#line 1221 "src/parse/conf_parser.cc" break; case 14: /* elems: elems ',' CONF_STRING */ @@ -1227,15 +1226,15 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.list) = (yyvsp[-2].list); (yyval.list)->push_back((yyvsp[0].str)); } -#line 1231 "src/parse/conf_parser.cc" +#line 1230 "src/parse/conf_parser.cc" break; case 15: /* code_exprs: %empty */ #line 98 "../src/parse/conf_parser.ypp" { - (yyval.codes) = stx.new_code_list(); + (yyval.codes) = opts.new_code_list(); } -#line 1239 "src/parse/conf_parser.cc" +#line 1238 "src/parse/conf_parser.cc" break; case 16: /* code_exprs: code_exprs code_expr */ @@ -1244,7 +1243,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.codes) = (yyvsp[-1].codes); append((yyvsp[-1].codes), (yyvsp[0].code)); } -#line 1248 "src/parse/conf_parser.cc" +#line 1247 "src/parse/conf_parser.cc" break; case 17: /* code_exprs: code_exprs CONF_COND '?' code_exprs ':' code_exprs ')' */ @@ -1253,7 +1252,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.codes) = (yyvsp[-6].codes); append((yyvsp[-6].codes), (yyvsp[-5].cond) ? (yyvsp[-3].codes) : (yyvsp[-1].codes)); } -#line 1257 "src/parse/conf_parser.cc" +#line 1256 "src/parse/conf_parser.cc" break; case 18: /* code_exprs: code_exprs CONF_COND '?' code_exprs ')' */ @@ -1262,75 +1261,75 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.codes) = (yyvsp[-4].codes); if ((yyvsp[-3].cond)) append((yyvsp[-4].codes), (yyvsp[-1].codes)); } -#line 1266 "src/parse/conf_parser.cc" +#line 1265 "src/parse/conf_parser.cc" break; case 19: /* code_expr: CONF_STRING */ #line 112 "../src/parse/conf_parser.ypp" - { (yyval.code) = stx.make_code_str((yyvsp[0].str)); } -#line 1272 "src/parse/conf_parser.cc" + { (yyval.code) = opts.make_code_str((yyvsp[0].str)); } +#line 1271 "src/parse/conf_parser.cc" break; case 20: /* code_expr: CONF_VAR */ #line 113 "../src/parse/conf_parser.ypp" - { (yyval.code) = stx.make_code_var((yyvsp[0].var)); } -#line 1278 "src/parse/conf_parser.cc" + { (yyval.code) = opts.make_code_var((yyvsp[0].var)); } +#line 1277 "src/parse/conf_parser.cc" break; case 23: /* code_opt: opt '?' code_exprs ')' */ #line 118 "../src/parse/conf_parser.ypp" { - (yyval.code) = stx.make_code_cond((yyvsp[-3].opt), (yyvsp[-1].codes), nullptr); + (yyval.code) = opts.make_code_cond((yyvsp[-3].opt), (yyvsp[-1].codes), nullptr); } -#line 1286 "src/parse/conf_parser.cc" +#line 1285 "src/parse/conf_parser.cc" break; case 24: /* code_opt: opt '?' code_exprs ':' code_exprs ')' */ #line 120 "../src/parse/conf_parser.ypp" { - (yyval.code) = stx.make_code_cond((yyvsp[-5].opt), (yyvsp[-3].codes), (yyvsp[-1].codes)); + (yyval.code) = opts.make_code_cond((yyvsp[-5].opt), (yyvsp[-3].codes), (yyvsp[-1].codes)); } -#line 1294 "src/parse/conf_parser.cc" +#line 1293 "src/parse/conf_parser.cc" break; case 25: /* opt: CONF_GOPT */ #line 125 "../src/parse/conf_parser.ypp" - { (yyval.opt) = stx.make_opt_global((yyvsp[0].gopt)); } -#line 1300 "src/parse/conf_parser.cc" + { (yyval.opt) = opts.make_opt_global((yyvsp[0].gopt)); } +#line 1299 "src/parse/conf_parser.cc" break; case 26: /* opt: CONF_LOPT */ #line 126 "../src/parse/conf_parser.ypp" - { (yyval.opt) = stx.make_opt_local((yyvsp[0].lopt)); } -#line 1306 "src/parse/conf_parser.cc" + { (yyval.opt) = opts.make_opt_local((yyvsp[0].lopt)); } +#line 1305 "src/parse/conf_parser.cc" break; case 27: /* code_list: '[' CONF_VAR ':' code_exprs ']' */ #line 129 "../src/parse/conf_parser.ypp" { - (yyval.code) = stx.make_code_list((yyvsp[-3].var), 0, -1, (yyvsp[-1].codes)); + (yyval.code) = opts.make_code_list((yyvsp[-3].var), 0, -1, (yyvsp[-1].codes)); } -#line 1314 "src/parse/conf_parser.cc" +#line 1313 "src/parse/conf_parser.cc" break; case 28: /* code_list: '[' CONF_VAR '{' CONF_NUMBER '}' ':' code_exprs ']' */ #line 131 "../src/parse/conf_parser.ypp" { - (yyval.code) = stx.make_code_list((yyvsp[-6].var), (yyvsp[-4].num), (yyvsp[-4].num), (yyvsp[-1].codes)); + (yyval.code) = opts.make_code_list((yyvsp[-6].var), (yyvsp[-4].num), (yyvsp[-4].num), (yyvsp[-1].codes)); } -#line 1322 "src/parse/conf_parser.cc" +#line 1321 "src/parse/conf_parser.cc" break; case 29: /* code_list: '[' CONF_VAR '{' CONF_NUMBER ':' CONF_NUMBER '}' ':' code_exprs ']' */ #line 133 "../src/parse/conf_parser.ypp" { - (yyval.code) = stx.make_code_list((yyvsp[-8].var), (yyvsp[-6].num), (yyvsp[-4].num), (yyvsp[-1].codes)); + (yyval.code) = opts.make_code_list((yyvsp[-8].var), (yyvsp[-6].num), (yyvsp[-4].num), (yyvsp[-1].codes)); } -#line 1330 "src/parse/conf_parser.cc" +#line 1329 "src/parse/conf_parser.cc" break; -#line 1334 "src/parse/conf_parser.cc" +#line 1333 "src/parse/conf_parser.cc" default: break; } @@ -1377,7 +1376,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); if (!yyerrstatus) { ++yynerrs; - yyerror (in, opts, stx, YY_("syntax error")); + yyerror (in, opts, YY_("syntax error")); } if (yyerrstatus == 3) @@ -1394,7 +1393,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); else { yydestruct ("Error: discarding", - yytoken, &yylval, in, opts, stx); + yytoken, &yylval, in, opts); yychar = CONF_EMPTY; } } @@ -1450,7 +1449,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yydestruct ("Error: popping", - YY_ACCESSING_SYMBOL (yystate), yyvsp, in, opts, stx); + YY_ACCESSING_SYMBOL (yystate), yyvsp, in, opts); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); @@ -1488,7 +1487,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); | yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | `-----------------------------------------------------------*/ yyexhaustedlab: - yyerror (in, opts, stx, YY_("memory exhausted")); + yyerror (in, opts, YY_("memory exhausted")); yyresult = 2; goto yyreturnlab; @@ -1503,7 +1502,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); user semantic actions for why this is necessary. */ yytoken = YYTRANSLATE (yychar); yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, in, opts, stx); + yytoken, &yylval, in, opts); } /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ @@ -1512,7 +1511,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); while (yyssp != yyss) { yydestruct ("Cleanup: popping", - YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, in, opts, stx); + YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, in, opts); YYPOPSTACK (1); } #ifndef yyoverflow @@ -1527,7 +1526,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); extern "C" { - static void yyerror(re2c::Input& in, Opt&, Stx&, const char* s) { + static void yyerror(re2c::Input& in, Opt&, const char* s) { in.error_at_tok("%s", s); } @@ -1545,44 +1544,44 @@ extern const char* DEFAULT_SYNTAX_RUST; namespace re2c { -inline StxCodes* Stx::new_code_list() { +inline StxCodes* Opt::new_code_list() { return new_list(alc); } -inline StxCode* Stx::make_code(StxCodeType type) { +inline StxCode* Opt::make_code(StxCodeType type) { StxCode* x = alc.alloct(1); x->type = type; x->next = nullptr; return x; } -inline StxCode* Stx::make_code_str(const char* str) { +inline StxCode* Opt::make_code_str(const char* str) { StxCode* x = make_code(StxCodeType::STR); x->str = str; return x; } -inline StxCode* Stx::make_code_var(StxVarId var) { +inline StxCode* Opt::make_code_var(StxVarId var) { StxCode* x = make_code(StxCodeType::VAR); x->var = var; return x; } -inline StxOpt* Stx::make_opt_global(StxGOpt opt) { +inline StxOpt* Opt::make_opt_global(StxGOpt opt) { StxOpt* x = alc.alloct(1); x->is_local = false; x->gopt = opt; return x; } -inline StxOpt* Stx::make_opt_local(StxLOpt opt) { +inline StxOpt* Opt::make_opt_local(StxLOpt opt) { StxOpt* x = alc.alloct(1); x->is_local = true; x->lopt = opt; return x; } -inline StxCode* Stx::make_code_cond(StxOpt* opt, StxCodes* then_code, StxCodes* else_code) { +inline StxCode* Opt::make_code_cond(StxOpt* opt, StxCodes* then_code, StxCodes* else_code) { StxCode* x = make_code(StxCodeType::COND); x->cond.opt = opt; x->cond.then_code = then_code; @@ -1590,7 +1589,7 @@ inline StxCode* Stx::make_code_cond(StxOpt* opt, StxCodes* then_code, StxCodes* return x; } -inline StxCode* Stx::make_code_list(StxVarId var, int32_t lbound, int32_t rbound, StxCodes* code) { +inline StxCode* Opt::make_code_list(StxVarId var, int32_t lbound, int32_t rbound, StxCodes* code) { StxCode* x = make_code(StxCodeType::LIST); x->list.var = var; x->list.lbound = lbound; @@ -1649,7 +1648,7 @@ Ret Input::load_syntax_config(Opt& opts, Lang& lang) { } Ret Input::parse_conf(Opt& opts) { - return conf_parse(*this, opts, opts.stx) == 0 ? Ret::OK : Ret::FAIL; + return conf_parse(*this, opts) == 0 ? Ret::OK : Ret::FAIL; } } // namespace re2c diff --git a/bootstrap/src/parse/conf_parser.h b/bootstrap/src/parse/conf_parser.h index 46691fe8c..8bdf330d2 100644 --- a/bootstrap/src/parse/conf_parser.h +++ b/bootstrap/src/parse/conf_parser.h @@ -57,7 +57,7 @@ extern int conf_debug; #include "src/constants.h" -#include "src/options/syntax.h" +#include "src/options/opt.h" #line 64 "src/parse/conf_parser.h" @@ -111,7 +111,7 @@ typedef union CONF_STYPE CONF_STYPE; -int conf_parse (re2c::Input& in, re2c::Opt& opts, re2c::Stx& stx); +int conf_parse (re2c::Input& in, re2c::Opt& opts); #endif /* !YY_CONF_SRC_PARSE_CONF_PARSER_H_INCLUDED */ diff --git a/src/codegen/output.h b/src/codegen/output.h index 7e1057947..c2de8350b 100644 --- a/src/codegen/output.h +++ b/src/codegen/output.h @@ -13,7 +13,7 @@ #include "src/codegen/code.h" #include "src/dfa/tcmd.h" #include "src/msg/location.h" -#include "src/options/syntax.h" +#include "src/options/opt.h" #include "src/util/allocator.h" #include "src/util/attribute.h" diff --git a/src/codegen/pass1_analyze.cc b/src/codegen/pass1_analyze.cc index b912c7256..95e4c1df7 100644 --- a/src/codegen/pass1_analyze.cc +++ b/src/codegen/pass1_analyze.cc @@ -3,6 +3,7 @@ #include "src/adfa/adfa.h" #include "src/codegen/output.h" +#include "src/msg/msg.h" #include "src/options/opt.h" #include "src/dfa/tcmd.h" #include "src/util/check.h" diff --git a/src/codegen/pass2_generate.cc b/src/codegen/pass2_generate.cc index e53dd498d..c845a8d47 100644 --- a/src/codegen/pass2_generate.cc +++ b/src/codegen/pass2_generate.cc @@ -13,7 +13,6 @@ #include "src/msg/location.h" #include "src/msg/msg.h" #include "src/options/opt.h" -#include "src/options/syntax.h" #include "src/regexp/rule.h" #include "src/regexp/tag.h" #include "src/skeleton/skeleton.h" diff --git a/src/codegen/pass4_render.cc b/src/codegen/pass4_render.cc index 7f7abcc95..83965c182 100644 --- a/src/codegen/pass4_render.cc +++ b/src/codegen/pass4_render.cc @@ -5,7 +5,6 @@ #include "src/codegen/output.h" #include "src/msg/msg.h" #include "src/options/opt.h" -#include "src/options/syntax.h" #include "src/util/check.h" #include "src/util/file_utils.h" diff --git a/src/options/opt.cc b/src/options/opt.cc index 0c3ea27c0..04ceb9454 100644 --- a/src/options/opt.cc +++ b/src/options/opt.cc @@ -1,6 +1,6 @@ +#include "src/codegen/output.h" #include "src/msg/msg.h" #include "src/options/opt.h" -#include "src/options/syntax.h" #include "src/parse/input.h" #include "src/util/string_utils.h" @@ -347,15 +347,18 @@ LOCAL_NODISCARD(Ret fix_mutopt( } Opt::Opt(OutAllocator& alc, Msg& msg) - : stx(alc), - glob(stx), - symtab(), - msg(msg), - defaults(), - is_default(), - user(), - real(), - diverge(true) {} + : glob() + , symtab() + , msg(msg) + , alc(alc) + , defaults() + , is_default() + , user() + , real() + , diverge(true) + , stack_code() + , stack_code_list() + {} Ret Opt::fix_global_and_defaults() { // Allow to modify only the global options. @@ -396,7 +399,7 @@ Ret Opt::sync() { Ret Opt::snapshot(const opt_t** opts) { CHECK_RET(sync()); - *opts = new opt_t(stx, glob, real, is_default, symtab); + *opts = new opt_t(glob, real, is_default, symtab); return Ret::OK; } @@ -487,7 +490,7 @@ Ret Opt::check_##name() { \ static const std::unordered_set vs vars; \ static const std::unordered_set lvs list_vars; \ static const std::unordered_set cs conds; \ - return stx.validate_conf_code(glob.name, str, vs, lvs, cs); \ + return validate_conf_code(glob.name, str, vs, lvs, cs); \ } RE2C_CODE_TEMPLATES #undef CODE_TEMPLATE @@ -532,4 +535,207 @@ void Opt::reset_group_label_start() { diverge = true; } +const char* Opt::var_name(StxVarId id) { +#define STX_LOCAL_VAR(id, name) name, +#define STX_GLOBAL_VAR(id, name) name, + static const char* names[] = { + RE2C_STX_LOCAL_VARS + RE2C_STX_GLOBAL_VARS + }; +#undef STX_LOCAL_VAR +#undef STX_GLOBAL_VAR + return names[static_cast(id)]; +} + +// is this a known configuration-specific conditional? +Ret Opt::check_cond(StxLOpt opt, const char* conf, const std::unordered_set& conds) const { + if (conds.find(opt) != conds.end()) return Ret::OK; + RET_FAIL(error("unknown conditional in configuration '%s'", conf)); +} + +Ret Opt::check_var( + StxVarId var, + const char* conf, + const std::unordered_set& vars, + const std::unordered_set& list_vars) const { + // is this a global variable? + static const std::unordered_set global_vars({ +#define STX_GLOBAL_VAR(id, name) StxVarId:: id, + RE2C_STX_GLOBAL_VARS +#undef STX_GLOBAL_VAR + }); + if (global_vars.find(var) != global_vars.end()) return Ret::OK; + + // this may be a list var; in that case it must be on the list stack + bool is_list_var = std::find_if(stack_code_list.begin(), stack_code_list.end(), + [var](const StxCode* x) { return var == x->list.var; }) + != stack_code_list.end(); + + // is this a known configuration-specific variable? + const std::unordered_set& v = is_list_var ? list_vars : vars; + if (std::find(v.begin(), v.end(), var) != v.end()) return Ret::OK; + + RET_FAIL(error("unknown variable '%s' in configuration '%s'", var_name(var), conf)); +} + +// validate that all option and variable names used in the given code do exist +Ret Opt::validate_conf_code( + const StxCodes* code, + const char* conf, + const std::unordered_set& vars, + const std::unordered_set& list_vars, + const std::unordered_set& conds) { + stack_code_list.clear(); + stack_code_t& stack = stack_code; + stack.clear(); + for (const StxCode* x = code->head; x != nullptr; x = x->next) { + stack.push_back({x, 0}); + } + + while (!stack.empty()) { + const StxCode* x = stack.back().first; + uint8_t n = stack.back().second; + stack.pop_back(); + + switch (x->type) { + case StxCodeType::STR: + // no option names to check here + break; + case StxCodeType::VAR: + CHECK_RET(check_var(x->var, conf, vars, list_vars)); + break; + case StxCodeType::COND: + if (n == 0) { // recurse into branches + stack.push_back({x, 1}); + for (const StxCode* y = x->cond.then_code->head; y != nullptr; y = y->next) { + stack.push_back({y, 0}); + } + if (x->cond.else_code != nullptr) { + for (const StxCode* y = x->cond.else_code->head; y != nullptr; y = y->next) { + stack.push_back({y, 0}); + } + } + } else if (x->cond.opt->is_local) { + // no need to check global conditionals, as they are filtered in the lexer + CHECK_RET(check_cond(x->cond.opt->lopt, conf, conds)); + } + break; + case StxCodeType::LIST: + if (n == 0) { // recurse into list body + stack_code_list.push_back(x); + CHECK_RET(check_var(x->list.var, conf, vars, list_vars)); + stack.push_back({x, 1}); + for (const StxCode* y = x->list.code->head; y != nullptr; y = y->next) { + stack.push_back({y, 0}); + } + } else { // check variable name and return + stack_code_list.pop_back(); + } + break; + } + } + + return Ret::OK; +} + +void opt_t::push_list_on_stack(const StxCode* x) const { + if (x == nullptr) return; + push_list_on_stack(x->next); + stack_code.push_back({x, 0}); +} + +static bool eval_cond(const StxOpt* cond, const opt_t* opts, RenderCallback* callback) { + if (cond->is_local) { + DCHECK(callback != nullptr); + return callback->eval_cond(cond->lopt); + } else { + switch (cond->gopt) { + case StxGOpt::API_DEFAULT: + return opts->api == Api::DEFAULT; + case StxGOpt::API_CUSTOM: + return opts->api == Api::CUSTOM; + case StxGOpt::API_STYLE_FUNCTIONS: + return opts->api_style == ApiStyle::FUNCTIONS; + case StxGOpt::API_STYLE_FREEFORM: + return opts->api_style == ApiStyle::FREEFORM; + case StxGOpt::CODE_MODEL_GOTO_LABEL: + return opts->code_model == CodeModel::GOTO_LABEL; + case StxGOpt::CODE_MODEL_LOOP_SWITCH: + return opts->code_model == CodeModel::LOOP_SWITCH; + case StxGOpt::CODE_MODEL_REC_FUNC: + return opts->code_model == CodeModel::REC_FUNC; + case StxGOpt::START_CONDITIONS: + return opts->start_conditions; + case StxGOpt::STORABLE_STATE: + return opts->storable_state; + case StxGOpt::DATE: + return opts->date; + case StxGOpt::VER: + return opts->version; + case StxGOpt::CASE_RANGES: + return opts->case_ranges; + case StxGOpt::UNSAFE: + return opts->unsafe; + case StxGOpt::LOOP_LABEL: + return !opts->label_loop.empty(); + } + } + UNREACHABLE(); + return false; +} + +static inline bool eval_list_bounds(size_t size, int32_t& lbound, int32_t& rbound) { + lbound = lbound >= 0 ? lbound : (std::max(0, static_cast(size) + lbound)); + rbound = rbound >= 0 ? rbound : (static_cast(size) + rbound); + return lbound <= rbound && rbound >= 0; +} + +void opt_t::eval_code_conf(const StxCodes* code, std::ostream& os, RenderCallback& callback) const { + stack_code_t& stack = stack_code; + size_t bottom = stack.size(); + push_list_on_stack(code->head); + + while (stack.size() != bottom) { + const StxCode* x = stack.back().first; + int32_t n = stack.back().second; + stack.pop_back(); + + switch (x->type) { + case StxCodeType::STR: + os << x->str; + break; + case StxCodeType::VAR: + callback.render_var(x->var); + break; + case StxCodeType::COND: + if (eval_cond(x->cond.opt, this, &callback)) { + push_list_on_stack(x->cond.then_code->head); + } else if (x->cond.else_code != nullptr) { + push_list_on_stack(x->cond.else_code->head); + } + break; + case StxCodeType::LIST: + if (n == 0) { + int32_t lbound = x->list.lbound; + int32_t rbound = x->list.rbound; + if (eval_list_bounds(callback.get_list_size(x->list.var), lbound, rbound)) { + callback.start_list( + x->list.var, static_cast(lbound), static_cast(rbound)); + stack.push_back({x, 1}); + push_list_on_stack(x->list.code->head); + } + } else if (callback.next_in_list(x->list.var)) { + stack.push_back({x, 1}); + push_list_on_stack(x->list.code->head); + } + break; + } + } +} + +void opt_t::eval_code_conf(const StxCodes* code, std::ostream& os) const { + RenderCallback dummy; + eval_code_conf(code, os, dummy); +} + } // namespace re2c diff --git a/src/options/opt.h b/src/options/opt.h index 9fb1c42f4..a2d6da967 100644 --- a/src/options/opt.h +++ b/src/options/opt.h @@ -5,12 +5,14 @@ #include #include #include +#include #include "src/constants.h" #include "src/encoding/enc.h" #include "src/options/symtab.h" -#include "src/options/syntax.h" +#include "src/util/allocator.h" #include "src/util/attribute.h" +#include "src/util/containers.h" #include "src/util/forbid_copy.h" namespace re2c { @@ -34,7 +36,9 @@ namespace re2c { class Input; class Msg; -class Stx; +class RenderCallback; +struct StxCode; +using StxCodes = list_t; #define RE2C_SIGIL "@@" #define RE2C_YYFN_SEP ";" @@ -206,6 +210,67 @@ class Stx; StxVarId::TYPECAST}), ({}), ({}) \ ) +// configuration-local variables in syntax files +#define RE2C_STX_LOCAL_VARS \ + STX_LOCAL_VAR(ARG, "arg") \ + STX_LOCAL_VAR(ARGMODS, "argmods") \ + STX_LOCAL_VAR(ARGNAME, "argname") \ + STX_LOCAL_VAR(ARGTYPE, "argtype") \ + STX_LOCAL_VAR(ARRAY, "array") \ + STX_LOCAL_VAR(BACKUP, "backup") \ + STX_LOCAL_VAR(BRANCH, "branch") \ + STX_LOCAL_VAR(CASE, "case") \ + STX_LOCAL_VAR(CHAR, "char") \ + STX_LOCAL_VAR(COND, "cond") \ + STX_LOCAL_VAR(CTYPE, "ctype") \ + STX_LOCAL_VAR(CURSOR, "cursor") \ + STX_LOCAL_VAR(DATE, "date") \ + STX_LOCAL_VAR(DEBUG, "debug") \ + STX_LOCAL_VAR(ELEM, "elem") \ + STX_LOCAL_VAR(EXPR, "expr") \ + STX_LOCAL_VAR(FN, "fn") \ + STX_LOCAL_VAR(FILE, "file") \ + STX_LOCAL_VAR(FNDECL, "fndecl") \ + STX_LOCAL_VAR(FNDEF, "fndef") \ + STX_LOCAL_VAR(INDEX, "index") \ + STX_LOCAL_VAR(INIT, "init") \ + STX_LOCAL_VAR(LABEL, "label") \ + STX_LOCAL_VAR(LHS, "lhs") \ + STX_LOCAL_VAR(LINE, "line") \ + STX_LOCAL_VAR(MARKER, "marker") \ + STX_LOCAL_VAR(NAME, "name") \ + STX_LOCAL_VAR(NUM, "num") \ + STX_LOCAL_VAR(OP, "op") \ + STX_LOCAL_VAR(PEEK, "peek") \ + STX_LOCAL_VAR(RETVAL, "retval") \ + STX_LOCAL_VAR(RHS, "rhs") \ + STX_LOCAL_VAR(ROW, "row") \ + STX_LOCAL_VAR(SIZE, "size") \ + STX_LOCAL_VAR(SKIP, "skip") \ + STX_LOCAL_VAR(STATE, "state") \ + STX_LOCAL_VAR(STMT, "stmt") \ + STX_LOCAL_VAR(TYPE, "type") \ + STX_LOCAL_VAR(TYPECAST, "typecast") \ + STX_LOCAL_VAR(VAL, "val") \ + STX_LOCAL_VAR(VAR, "var") \ + STX_LOCAL_VAR(VER, "version") + +// global variables in syntax files +#define RE2C_STX_GLOBAL_VARS \ + STX_GLOBAL_VAR(NEWLINE, "nl") \ + STX_GLOBAL_VAR(INDENT, "indent") \ + STX_GLOBAL_VAR(DEDENT, "dedent") \ + STX_GLOBAL_VAR(TOPINDENT, "topindent") + +#define STX_LOCAL_VAR(id, name) id, +#define STX_GLOBAL_VAR(id, name) id, +enum class StxVarId : uint32_t { + RE2C_STX_LOCAL_VARS + RE2C_STX_GLOBAL_VARS +}; +#undef STX_LOCAL_VAR +#undef STX_GLOBAL_VAR + #define RE2C_CONSTOPTS \ CONSTOPT(Target, target, Target::CODE) \ CONSTOPT(CodeModel, code_model, CodeModel::GOTO_LABEL) \ @@ -355,12 +420,42 @@ class Stx; MUTOPT(bool, debug, false) \ /* end */ +struct StxOpt { + bool is_local; + union { + StxGOpt gopt; + StxLOpt lopt; + }; +}; + +struct StxCodeCond { + StxOpt* opt; + StxCodes* then_code; + StxCodes* else_code; +}; + +struct StxCodeList { + StxVarId var; + int32_t lbound; + int32_t rbound; + StxCodes* code; +}; + +enum class StxCodeType {STR, VAR, COND, LIST}; + +struct StxCode { + StxCodeType type; + union { + const char* str; + StxVarId var; + StxCodeCond cond; + StxCodeList list; + }; + StxCode* next; +}; + // Constant options. struct conopt_t { - private: - const Stx& stx; - - public: // Global options are public (for easier read access), but constant (to avoid // accidental write access, as this should be done by `set_*` methods that correctly // update `is_default_*` status). @@ -379,8 +474,7 @@ struct conopt_t { #undef CODE_TEMPLATE bool p2067; // until c++ allows trailing comma in macro-expanded ctor-intializer - conopt_t(const Stx& stx) - : stx(stx), + conopt_t() : #define CONSTOPT(type, name, value) name(value), is_default_##name(true), RE2C_CONSTOPTS #undef CONSTOPT @@ -454,7 +548,10 @@ struct mutdef_t { // Union of constant and mutable options and default flags. struct opt_t { private: - const Stx& stx; + using stack_code_t = std::vector>; + + // stack is placed here to avoid reallocating it every time + mutable stack_code_t stack_code; public: #define CONSTOPT(type, name, value) type name; @@ -479,12 +576,8 @@ struct opt_t { #undef MUTOPT symtab_t symtab; - opt_t(const Stx& stx, - const conopt_t& con, - const mutopt_t& mut, - const mutdef_t& def, - const symtab_t& symtab) - : stx(stx), + opt_t(const conopt_t& con, const mutopt_t& mut, const mutdef_t& def, const symtab_t& symtab) + : stack_code(), #define CONSTOPT(type, name, value) name(con.name), RE2C_CONSTOPTS #undef CONSTOPT @@ -510,28 +603,38 @@ struct opt_t { #define CODE_TEMPLATE(name, str, vars, list_vars, conds) \ void render_##name(std::ostream& os, RenderCallback& callback) const { \ - stx.eval_code_conf(name, os, this, callback); \ + eval_code_conf(name, os, callback); \ } \ void render_##name(std::ostream& os) const { \ - stx.eval_code_conf(name, os, this); \ + eval_code_conf(name, os); \ } RE2C_CODE_TEMPLATES #undef CODE_TEMPLATE bool specialize_oneline_if() const { return code_if_then_else_oneline != nullptr; } bool specialize_oneline_switch() const { return code_switch_cases_oneline != nullptr; } + private: + void eval_code_conf(const StxCodes* code, std::ostream& os) const; + void eval_code_conf(const StxCodes* code, std::ostream& os, RenderCallback& callback) const; + void push_list_on_stack(const StxCode* x) const; + FORBID_COPY(opt_t); }; // Options management. struct Opt { + private: + using stack_code_t = std::vector>; + using stack_code_list_t = std::vector; + public: - Stx stx; const conopt_t glob; symtab_t symtab; Msg& msg; private: + OutAllocator& alc; + // Default mutable options. They depend on the global options, such as the language backend, and // are fixed after parsing the global options. const mutopt_t defaults; @@ -554,6 +657,10 @@ struct Opt { // If user-set options have diverged from the real ones and need syncing. bool diverge; + // stacks are placed here to avoid reallocating them every time + stack_code_t stack_code; + stack_code_list_t stack_code_list; + public: Opt(OutAllocator& alc, Msg& msg); const conopt_t& global() const { return glob; } @@ -592,8 +699,32 @@ struct Opt { void reset_group_label_start(); + StxCodes* new_code_list(); + StxCode* make_code_str(const char* str); + StxCode* make_code_var(StxVarId id); + StxCode* make_code_cond(StxOpt* opt, StxCodes* code_then, StxCodes* code_else); + StxCode* make_code_list(StxVarId var, int32_t lbound, int32_t rbound, StxCodes* code); + StxOpt* make_opt_global(StxGOpt opt); + StxOpt* make_opt_local(StxLOpt opt); + + Ret validate_conf_code( + const StxCodes* code, + const char* conf, + const std::unordered_set& vars, + const std::unordered_set& list_vars, + const std::unordered_set& conds) NODISCARD; + private: Ret sync() NODISCARD; + + static const char* var_name(StxVarId id); + + StxCode* make_code(StxCodeType type); + + Ret check_cond(StxLOpt opt, const char* conf, const std::unordered_set& conds) const; + Ret check_var(StxVarId var, const char* conf, const std::unordered_set& vars, + const std::unordered_set& list_vars) const; + FORBID_COPY(Opt); }; diff --git a/src/options/syntax.cc b/src/options/syntax.cc deleted file mode 100644 index 7abc8ff7f..000000000 --- a/src/options/syntax.cc +++ /dev/null @@ -1,220 +0,0 @@ -#include -#include -#include - -#include "src/codegen/output.h" -#include "src/options/opt.h" -#include "src/options/syntax.h" - -namespace re2c { - -Stx::Stx(OutAllocator& alc) - : alc(alc) - , stack_code() - , stack_code_list() {} - -const char* Stx::var_name(StxVarId id) { -#define STX_LOCAL_VAR(id, name) name, -#define STX_GLOBAL_VAR(id, name) name, - static const char* names[] = { - RE2C_STX_LOCAL_VARS - RE2C_STX_GLOBAL_VARS - }; -#undef STX_LOCAL_VAR -#undef STX_GLOBAL_VAR - return names[static_cast(id)]; -} - -// is this a known configuration-specific conditional? -Ret Stx::check_cond(StxLOpt opt, const char* conf, const std::unordered_set& conds) const { - if (conds.find(opt) != conds.end()) return Ret::OK; - RET_FAIL(error("unknown conditional in configuration '%s'", conf)); -} - -Ret Stx::check_var( - StxVarId var, - const char* conf, - const std::unordered_set& vars, - const std::unordered_set& list_vars) const { - // is this a global variable? - static const std::unordered_set global_vars({ -#define STX_GLOBAL_VAR(id, name) StxVarId:: id, - RE2C_STX_GLOBAL_VARS -#undef STX_GLOBAL_VAR - }); - if (global_vars.find(var) != global_vars.end()) return Ret::OK; - - // this may be a list var; in that case it must be on the list stack - bool is_list_var = std::find_if(stack_code_list.begin(), stack_code_list.end(), - [var](const StxCode* x) { return var == x->list.var; }) - != stack_code_list.end(); - - // is this a known configuration-specific variable? - const std::unordered_set& v = is_list_var ? list_vars : vars; - if (std::find(v.begin(), v.end(), var) != v.end()) return Ret::OK; - - RET_FAIL(error("unknown variable '%s' in configuration '%s'", var_name(var), conf)); -} - -// validate that all option and variable names used in the given code do exist -Ret Stx::validate_conf_code( - const StxCodes* code, - const char* conf, - const std::unordered_set& vars, - const std::unordered_set& list_vars, - const std::unordered_set& conds) const { - stack_code_list.clear(); - stack_code_t& stack = stack_code; - stack.clear(); - for (const StxCode* x = code->head; x != nullptr; x = x->next) { - stack.push_back({x, 0}); - } - - while (!stack.empty()) { - const StxCode* x = stack.back().first; - uint8_t n = stack.back().second; - stack.pop_back(); - - switch (x->type) { - case StxCodeType::STR: - // no option names to check here - break; - case StxCodeType::VAR: - CHECK_RET(check_var(x->var, conf, vars, list_vars)); - break; - case StxCodeType::COND: - if (n == 0) { // recurse into branches - stack.push_back({x, 1}); - for (const StxCode* y = x->cond.then_code->head; y != nullptr; y = y->next) { - stack.push_back({y, 0}); - } - if (x->cond.else_code != nullptr) { - for (const StxCode* y = x->cond.else_code->head; y != nullptr; y = y->next) { - stack.push_back({y, 0}); - } - } - } else if (x->cond.opt->is_local) { - // no need to check global conditionals, as they are filtered in the lexer - CHECK_RET(check_cond(x->cond.opt->lopt, conf, conds)); - } - break; - case StxCodeType::LIST: - if (n == 0) { // recurse into list body - stack_code_list.push_back(x); - CHECK_RET(check_var(x->list.var, conf, vars, list_vars)); - stack.push_back({x, 1}); - for (const StxCode* y = x->list.code->head; y != nullptr; y = y->next) { - stack.push_back({y, 0}); - } - } else { // check variable name and return - stack_code_list.pop_back(); - } - break; - } - } - - return Ret::OK; -} - -void Stx::push_list_on_stack(const StxCode* x) const { - if (x == nullptr) return; - push_list_on_stack(x->next); - stack_code.push_back({x, 0}); -} - -static bool eval_cond(const StxOpt* cond, const opt_t* opts, RenderCallback* callback) { - if (cond->is_local) { - DCHECK(callback != nullptr); - return callback->eval_cond(cond->lopt); - } else { - switch (cond->gopt) { - case StxGOpt::API_DEFAULT: - return opts->api == Api::DEFAULT; - case StxGOpt::API_CUSTOM: - return opts->api == Api::CUSTOM; - case StxGOpt::API_STYLE_FUNCTIONS: - return opts->api_style == ApiStyle::FUNCTIONS; - case StxGOpt::API_STYLE_FREEFORM: - return opts->api_style == ApiStyle::FREEFORM; - case StxGOpt::CODE_MODEL_GOTO_LABEL: - return opts->code_model == CodeModel::GOTO_LABEL; - case StxGOpt::CODE_MODEL_LOOP_SWITCH: - return opts->code_model == CodeModel::LOOP_SWITCH; - case StxGOpt::CODE_MODEL_REC_FUNC: - return opts->code_model == CodeModel::REC_FUNC; - case StxGOpt::START_CONDITIONS: - return opts->start_conditions; - case StxGOpt::STORABLE_STATE: - return opts->storable_state; - case StxGOpt::DATE: - return opts->date; - case StxGOpt::VER: - return opts->version; - case StxGOpt::CASE_RANGES: - return opts->case_ranges; - case StxGOpt::UNSAFE: - return opts->unsafe; - case StxGOpt::LOOP_LABEL: - return !opts->label_loop.empty(); - } - } - UNREACHABLE(); - return false; -} - -static inline bool eval_list_bounds(size_t size, int32_t& lbound, int32_t& rbound) { - lbound = lbound >= 0 ? lbound : (std::max(0, static_cast(size) + lbound)); - rbound = rbound >= 0 ? rbound : (static_cast(size) + rbound); - return lbound <= rbound && rbound >= 0; -} - -void Stx::eval_code_conf( - const StxCodes* code, std::ostream& os, const opt_t* opts, RenderCallback& callback) const { - stack_code_t& stack = stack_code; - size_t bottom = stack.size(); - push_list_on_stack(code->head); - - while (stack.size() != bottom) { - const StxCode* x = stack.back().first; - int32_t n = stack.back().second; - stack.pop_back(); - - switch (x->type) { - case StxCodeType::STR: - os << x->str; - break; - case StxCodeType::VAR: - callback.render_var(x->var); - break; - case StxCodeType::COND: - if (eval_cond(x->cond.opt, opts, &callback)) { - push_list_on_stack(x->cond.then_code->head); - } else if (x->cond.else_code != nullptr) { - push_list_on_stack(x->cond.else_code->head); - } - break; - case StxCodeType::LIST: - if (n == 0) { - int32_t lbound = x->list.lbound; - int32_t rbound = x->list.rbound; - if (eval_list_bounds(callback.get_list_size(x->list.var), lbound, rbound)) { - callback.start_list( - x->list.var, static_cast(lbound), static_cast(rbound)); - stack.push_back({x, 1}); - push_list_on_stack(x->list.code->head); - } - } else if (callback.next_in_list(x->list.var)) { - stack.push_back({x, 1}); - push_list_on_stack(x->list.code->head); - } - break; - } - } -} - -void Stx::eval_code_conf(const StxCodes* code, std::ostream& os, const opt_t* opts) const { - RenderCallback dummy; - eval_code_conf(code, os, opts, dummy); -} - -} // namespace re2c diff --git a/src/options/syntax.h b/src/options/syntax.h deleted file mode 100644 index 6f563f84c..000000000 --- a/src/options/syntax.h +++ /dev/null @@ -1,178 +0,0 @@ -#ifndef _RE2C_CODEGEN_SYNTAX_ -#define _RE2C_CODEGEN_SYNTAX_ - -#include -#include -#include -#include -#include -#include -#include - -#include "src/constants.h" -#include "src/msg/location.h" -#include "src/msg/msg.h" -#include "src/util/allocator.h" -#include "src/util/check.h" -#include "src/util/containers.h" -#include "src/util/forbid_copy.h" - -namespace re2c { - -class RenderCallback; -struct StxCode; -struct opt_t; - -// configuration-local variables in syntax files -#define RE2C_STX_LOCAL_VARS \ - STX_LOCAL_VAR(ARG, "arg") \ - STX_LOCAL_VAR(ARGMODS, "argmods") \ - STX_LOCAL_VAR(ARGNAME, "argname") \ - STX_LOCAL_VAR(ARGTYPE, "argtype") \ - STX_LOCAL_VAR(ARRAY, "array") \ - STX_LOCAL_VAR(BACKUP, "backup") \ - STX_LOCAL_VAR(BRANCH, "branch") \ - STX_LOCAL_VAR(CASE, "case") \ - STX_LOCAL_VAR(CHAR, "char") \ - STX_LOCAL_VAR(COND, "cond") \ - STX_LOCAL_VAR(CTYPE, "ctype") \ - STX_LOCAL_VAR(CURSOR, "cursor") \ - STX_LOCAL_VAR(DATE, "date") \ - STX_LOCAL_VAR(DEBUG, "debug") \ - STX_LOCAL_VAR(ELEM, "elem") \ - STX_LOCAL_VAR(EXPR, "expr") \ - STX_LOCAL_VAR(FN, "fn") \ - STX_LOCAL_VAR(FILE, "file") \ - STX_LOCAL_VAR(FNDECL, "fndecl") \ - STX_LOCAL_VAR(FNDEF, "fndef") \ - STX_LOCAL_VAR(INDEX, "index") \ - STX_LOCAL_VAR(INIT, "init") \ - STX_LOCAL_VAR(LABEL, "label") \ - STX_LOCAL_VAR(LHS, "lhs") \ - STX_LOCAL_VAR(LINE, "line") \ - STX_LOCAL_VAR(MARKER, "marker") \ - STX_LOCAL_VAR(NAME, "name") \ - STX_LOCAL_VAR(NUM, "num") \ - STX_LOCAL_VAR(OP, "op") \ - STX_LOCAL_VAR(PEEK, "peek") \ - STX_LOCAL_VAR(RETVAL, "retval") \ - STX_LOCAL_VAR(RHS, "rhs") \ - STX_LOCAL_VAR(ROW, "row") \ - STX_LOCAL_VAR(SIZE, "size") \ - STX_LOCAL_VAR(SKIP, "skip") \ - STX_LOCAL_VAR(STATE, "state") \ - STX_LOCAL_VAR(STMT, "stmt") \ - STX_LOCAL_VAR(TYPE, "type") \ - STX_LOCAL_VAR(TYPECAST, "typecast") \ - STX_LOCAL_VAR(VAL, "val") \ - STX_LOCAL_VAR(VAR, "var") \ - STX_LOCAL_VAR(VER, "version") - -// global variables in syntax files -#define RE2C_STX_GLOBAL_VARS \ - STX_GLOBAL_VAR(NEWLINE, "nl") \ - STX_GLOBAL_VAR(INDENT, "indent") \ - STX_GLOBAL_VAR(DEDENT, "dedent") \ - STX_GLOBAL_VAR(TOPINDENT, "topindent") - -#define STX_LOCAL_VAR(id, name) id, -#define STX_GLOBAL_VAR(id, name) id, -enum class StxVarId : uint32_t { - RE2C_STX_LOCAL_VARS - RE2C_STX_GLOBAL_VARS -}; -#undef STX_LOCAL_VAR -#undef STX_GLOBAL_VAR - -using StxCodes = list_t; - -struct StxOpt { - bool is_local; - union { - StxGOpt gopt; - StxLOpt lopt; - }; -}; - -struct StxCodeCond { - StxOpt* opt; - StxCodes* then_code; - StxCodes* else_code; -}; - -struct StxCodeList { - StxVarId var; - int32_t lbound; - int32_t rbound; - StxCodes* code; -}; - -enum class StxCodeType {STR, VAR, COND, LIST}; - -struct StxCode { - StxCodeType type; - union { - const char* str; - StxVarId var; - StxCodeCond cond; - StxCodeList list; - }; - StxCode* next; -}; - -class Stx { - using stack_code_t = std::vector>; - using stack_code_list_t = std::vector; - - constexpr static const char* DEFAULT_EMPTY = ""; // default value for undefined configurations - - public: - OutAllocator& alc; - - private: - // stacks are placed here to avoid reallocating them every time - // (they can be mutated when evaluating configurations in a constant syntax object) - mutable stack_code_t stack_code; - mutable stack_code_list_t stack_code_list; - - static const char* var_name(StxVarId id); - - StxCode* make_code(StxCodeType type); - - Ret check_cond(StxLOpt opt, const char* conf, const std::unordered_set& conds) const; - Ret check_var(StxVarId var, const char* conf, const std::unordered_set& vars, - const std::unordered_set& list_vars) const; - - void push_list_on_stack(const StxCode* x) const; - - public: - explicit Stx(OutAllocator& alc); - - // functions that construct AST when parsing syntax configurations - StxCodes* new_code_list(); - StxCode* make_code_str(const char* str); - StxCode* make_code_var(StxVarId id); - StxCode* make_code_cond(StxOpt* opt, StxCodes* code_then, StxCodes* code_else); - StxCode* make_code_list(StxVarId var, int32_t lbound, int32_t rbound, StxCodes* code); - StxOpt* make_opt_global(StxGOpt opt); - StxOpt* make_opt_local(StxLOpt opt); - - // functions that validate configuration and variable names in the AST - Ret validate_conf_code( - const StxCodes* code, - const char* conf, - const std::unordered_set& vars, - const std::unordered_set& list_vars, - const std::unordered_set& conds) const; - - // functions that check or evaluate configurations - void eval_code_conf(const StxCodes* code, std::ostream& os, const opt_t* opts) const; - void eval_code_conf( - const StxCodes* code, std::ostream& os, const opt_t* opts, RenderCallback& callback) const; - - friend class opt_t; -}; - -} // namespace re2c - -#endif // _RE2C_CODEGEN_SYNTAX_ diff --git a/src/parse/conf_lexer.re b/src/parse/conf_lexer.re index 224a358de..8fd83c7f8 100644 --- a/src/parse/conf_lexer.re +++ b/src/parse/conf_lexer.re @@ -651,7 +651,7 @@ start: "backtick_quoted_strings" { SAVE_CONF_BOOL(backtick_quoted_strings); } "standalone_single_quotes" { SAVE_CONF_BOOL(standalone_single_quotes); } - "" / "code:" { if (conf_parse(*this, opts, opts.stx) != 0) return Ret::FAIL; goto start; } + "" / "code:" { if (conf_parse(*this, opts) != 0) return Ret::FAIL; goto start; } * { RET_FAIL(error_at_tok("unexpected character: '%c'", cur[-1])); } */ diff --git a/src/parse/conf_parser.ypp b/src/parse/conf_parser.ypp index 009bf3089..b22b2f9a5 100644 --- a/src/parse/conf_parser.ypp +++ b/src/parse/conf_parser.ypp @@ -1,12 +1,13 @@ %code requires { #include "src/constants.h" -#include "src/options/syntax.h" +#include "src/options/opt.h" } %{ +#include "src/msg/msg.h" #include "src/options/opt.h" #include "src/parse/input.h" #include "src/parse/conf_parser.h" @@ -14,7 +15,7 @@ using namespace re2c; extern "C" { - static void yyerror(Input& in, Opt& opts, Stx& stx, const char* s); + static void yyerror(Input& in, Opt& opts, const char* s); static int yylex(CONF_STYPE* yylval, Input& in, Opt& opts); } @@ -28,7 +29,6 @@ extern "C" { %lex-param {re2c::Opt& opts} %parse-param {re2c::Input& in} %parse-param {re2c::Opt& opts} -%parse-param {re2c::Stx& stx} %union { const char* str; @@ -96,7 +96,7 @@ elems code_exprs : %empty { - $$ = stx.new_code_list(); + $$ = opts.new_code_list(); } | code_exprs code_expr { $$ = $1; append($1, $2); @@ -109,35 +109,35 @@ code_exprs }; code_expr -: CONF_STRING { $$ = stx.make_code_str($1); } -| CONF_VAR { $$ = stx.make_code_var($1); } +: CONF_STRING { $$ = opts.make_code_str($1); } +| CONF_VAR { $$ = opts.make_code_var($1); } | code_opt | code_list; code_opt : opt '?' code_exprs ')' { - $$ = stx.make_code_cond($1, $3, nullptr); + $$ = opts.make_code_cond($1, $3, nullptr); } | opt '?' code_exprs ':' code_exprs ')' { - $$ = stx.make_code_cond($1, $3, $5); + $$ = opts.make_code_cond($1, $3, $5); }; opt -: CONF_GOPT { $$ = stx.make_opt_global($1); } -| CONF_LOPT { $$ = stx.make_opt_local($1); }; +: CONF_GOPT { $$ = opts.make_opt_global($1); } +| CONF_LOPT { $$ = opts.make_opt_local($1); }; code_list : '[' CONF_VAR ':' code_exprs ']' { - $$ = stx.make_code_list($2, 0, -1, $4); + $$ = opts.make_code_list($2, 0, -1, $4); } | '[' CONF_VAR '{' CONF_NUMBER '}' ':' code_exprs ']' { - $$ = stx.make_code_list($2, $4, $4, $7); + $$ = opts.make_code_list($2, $4, $4, $7); } | '[' CONF_VAR '{' CONF_NUMBER ':' CONF_NUMBER '}' ':' code_exprs ']' { - $$ = stx.make_code_list($2, $4, $6, $9); + $$ = opts.make_code_list($2, $4, $6, $9); }; %% extern "C" { - static void yyerror(re2c::Input& in, Opt&, Stx&, const char* s) { + static void yyerror(re2c::Input& in, Opt&, const char* s) { in.error_at_tok("%s", s); } @@ -155,44 +155,44 @@ extern const char* DEFAULT_SYNTAX_RUST; namespace re2c { -inline StxCodes* Stx::new_code_list() { +inline StxCodes* Opt::new_code_list() { return new_list(alc); } -inline StxCode* Stx::make_code(StxCodeType type) { +inline StxCode* Opt::make_code(StxCodeType type) { StxCode* x = alc.alloct(1); x->type = type; x->next = nullptr; return x; } -inline StxCode* Stx::make_code_str(const char* str) { +inline StxCode* Opt::make_code_str(const char* str) { StxCode* x = make_code(StxCodeType::STR); x->str = str; return x; } -inline StxCode* Stx::make_code_var(StxVarId var) { +inline StxCode* Opt::make_code_var(StxVarId var) { StxCode* x = make_code(StxCodeType::VAR); x->var = var; return x; } -inline StxOpt* Stx::make_opt_global(StxGOpt opt) { +inline StxOpt* Opt::make_opt_global(StxGOpt opt) { StxOpt* x = alc.alloct(1); x->is_local = false; x->gopt = opt; return x; } -inline StxOpt* Stx::make_opt_local(StxLOpt opt) { +inline StxOpt* Opt::make_opt_local(StxLOpt opt) { StxOpt* x = alc.alloct(1); x->is_local = true; x->lopt = opt; return x; } -inline StxCode* Stx::make_code_cond(StxOpt* opt, StxCodes* then_code, StxCodes* else_code) { +inline StxCode* Opt::make_code_cond(StxOpt* opt, StxCodes* then_code, StxCodes* else_code) { StxCode* x = make_code(StxCodeType::COND); x->cond.opt = opt; x->cond.then_code = then_code; @@ -200,7 +200,7 @@ inline StxCode* Stx::make_code_cond(StxOpt* opt, StxCodes* then_code, StxCodes* return x; } -inline StxCode* Stx::make_code_list(StxVarId var, int32_t lbound, int32_t rbound, StxCodes* code) { +inline StxCode* Opt::make_code_list(StxVarId var, int32_t lbound, int32_t rbound, StxCodes* code) { StxCode* x = make_code(StxCodeType::LIST); x->list.var = var; x->list.lbound = lbound; @@ -259,7 +259,7 @@ Ret Input::load_syntax_config(Opt& opts, Lang& lang) { } Ret Input::parse_conf(Opt& opts) { - return conf_parse(*this, opts, opts.stx) == 0 ? Ret::OK : Ret::FAIL; + return conf_parse(*this, opts) == 0 ? Ret::OK : Ret::FAIL; } } // namespace re2c diff --git a/src/parse/input.h b/src/parse/input.h index 29deb1a29..d623f9fe3 100644 --- a/src/parse/input.h +++ b/src/parse/input.h @@ -32,7 +32,6 @@ struct BlockNameList; struct conopt_t; struct opt_t; struct Opt; -class Stx; struct StxCode; using StxCodes = list_t;