@@ -3298,18 +3298,15 @@ using Rules = std::unordered_map<std::string, std::shared_ptr<Ope>>;
32983298
32993299class ParserGenerator {
33003300public:
3301- static std::shared_ptr<Grammar> parse (const char *s, size_t n,
3302- const Rules &rules, std::string &start,
3303- bool &enablePackratParsing, Log log) {
3304- return get_instance ().perform_core (s, n, rules, start, enablePackratParsing,
3305- log);
3306- }
3301+ struct ParserContext {
3302+ std::shared_ptr<Grammar> grammar;
3303+ std::string start;
3304+ bool enablePackratParsing = false ;
3305+ };
33073306
3308- static std::shared_ptr<Grammar> parse (const char *s, size_t n,
3309- std::string &start,
3310- bool &enablePackratParsing, Log log) {
3311- Rules dummy;
3312- return parse (s, n, dummy, start, enablePackratParsing, log);
3307+ static ParserContext parse (const char *s, size_t n, const Rules &rules,
3308+ Log log, std::string_view start) {
3309+ return get_instance ().perform_core (s, n, rules, log, std::string (start));
33133310 }
33143311
33153312 // For debugging purpose
@@ -3989,9 +3986,8 @@ class ParserGenerator {
39893986 return true ;
39903987 }
39913988
3992- std::shared_ptr<Grammar> perform_core (const char *s, size_t n,
3993- const Rules &rules, std::string &start,
3994- bool &enablePackratParsing, Log log) {
3989+ ParserContext perform_core (const char *s, size_t n, const Rules &rules,
3990+ Log log, std::string requested_start) {
39953991 Data data;
39963992 auto &grammar = *data.grammar ;
39973993
@@ -4023,7 +4019,7 @@ class ParserGenerator {
40234019 log (line.first , line.second , " syntax error" , r.error_info .label );
40244020 }
40254021 }
4026- return nullptr ;
4022+ return {} ;
40274023 }
40284024
40294025 // User provided rules
@@ -4081,7 +4077,25 @@ class ParserGenerator {
40814077 }
40824078
40834079 // Set root definition
4084- auto &start_rule = grammar[data.start ];
4080+ auto start = data.start ;
4081+
4082+ if (!requested_start.empty ()) {
4083+ if (grammar.count (requested_start)) {
4084+ start = requested_start;
4085+ } else {
4086+ if (log) {
4087+ auto line = line_info (s, s);
4088+ log (line.first , line.second ,
4089+ " The specified start rule '" + requested_start + " ' is undefined." ,
4090+ " " );
4091+ }
4092+ ret = false ;
4093+ }
4094+ }
4095+
4096+ if (!ret) { return {}; }
4097+
4098+ auto &start_rule = grammar[start];
40854099
40864100 // Check if the start rule has ignore operator
40874101 {
@@ -4096,7 +4110,7 @@ class ParserGenerator {
40964110 }
40974111 }
40984112
4099- if (!ret) { return nullptr ; }
4113+ if (!ret) { return {} ; }
41004114
41014115 // Check missing definitions
41024116 auto referenced = std::unordered_set<std::string>{
@@ -4129,7 +4143,7 @@ class ParserGenerator {
41294143 }
41304144 }
41314145
4132- if (!ret) { return nullptr ; }
4146+ if (!ret) { return {} ; }
41334147
41344148 // Link references
41354149 for (auto &x : grammar) {
@@ -4153,10 +4167,10 @@ class ParserGenerator {
41534167 }
41544168 }
41554169
4156- if (!ret) { return nullptr ; }
4170+ if (!ret) { return {} ; }
41574171
41584172 // Check infinite loop
4159- if (detect_infiniteLoop (data, start_rule, log, s)) { return nullptr ; }
4173+ if (detect_infiniteLoop (data, start_rule, log, s)) { return {} ; }
41604174
41614175 // Automatic whitespace skipping
41624176 if (grammar.count (WHITESPACE_DEFINITION_NAME)) {
@@ -4169,15 +4183,15 @@ class ParserGenerator {
41694183 auto &rule = grammar[WHITESPACE_DEFINITION_NAME];
41704184 start_rule.whitespaceOpe = wsp (rule.get_core_operator ());
41714185
4172- if (detect_infiniteLoop (data, rule, log, s)) { return nullptr ; }
4186+ if (detect_infiniteLoop (data, rule, log, s)) { return {} ; }
41734187 }
41744188
41754189 // Word expression
41764190 if (grammar.count (WORD_DEFINITION_NAME)) {
41774191 auto &rule = grammar[WORD_DEFINITION_NAME];
41784192 start_rule.wordOpe = rule.get_core_operator ();
41794193
4180- if (detect_infiniteLoop (data, rule, log, s)) { return nullptr ; }
4194+ if (detect_infiniteLoop (data, rule, log, s)) { return {} ; }
41814195 }
41824196
41834197 // Apply instructions
@@ -4189,9 +4203,7 @@ class ParserGenerator {
41894203 const auto &info =
41904204 std::any_cast<PrecedenceClimbing::BinOpeInfo>(instruction.data );
41914205
4192- if (!apply_precedence_instruction (rule, info, s, log)) {
4193- return nullptr ;
4194- }
4206+ if (!apply_precedence_instruction (rule, info, s, log)) { return {}; }
41954207 } else if (instruction.type == " error_message" ) {
41964208 rule.error_message = std::any_cast<std::string>(instruction.data );
41974209 } else if (instruction.type == " no_ast_opt" ) {
@@ -4200,11 +4212,7 @@ class ParserGenerator {
42004212 }
42014213 }
42024214
4203- // Set root definition
4204- start = data.start ;
4205- enablePackratParsing = data.enablePackratParsing ;
4206-
4207- return data.grammar ;
4215+ return {data.grammar , start, data.enablePackratParsing };
42084216 }
42094217
42104218 bool detect_infiniteLoop (const Data &data, Definition &rule, const Log &log,
@@ -4530,43 +4538,52 @@ class parser {
45304538public:
45314539 parser () = default ;
45324540
4533- parser (const char *s, size_t n, const Rules &rules) {
4534- load_grammar (s, n, rules);
4541+ parser (const char *s, size_t n, const Rules &rules,
4542+ std::string_view start = {}) {
4543+ load_grammar (s, n, rules, start);
45354544 }
45364545
4537- parser (const char *s, size_t n) : parser (s, n, Rules ()) {}
4546+ parser (const char *s, size_t n, std::string_view start = {})
4547+ : parser (s, n, Rules (), start) {}
45384548
4539- parser (std::string_view sv, const Rules &rules)
4540- : parser (sv.data (), sv.size (), rules) {}
4549+ parser (std::string_view sv, const Rules &rules, std::string_view start = {} )
4550+ : parser (sv.data (), sv.size (), rules, start ) {}
45414551
4542- parser (std::string_view sv) : parser (sv.data (), sv.size (), Rules ()) {}
4552+ parser (std::string_view sv, std::string_view start = {})
4553+ : parser (sv.data (), sv.size (), Rules (), start) {}
45434554
45444555#if defined(__cpp_lib_char8_t)
4545- parser (std::u8string_view sv, const Rules &rules)
4546- : parser (reinterpret_cast <const char *>(sv.data ()), sv.size (), rules) {}
4556+ parser (std::u8string_view sv, const Rules &rules, std::string_view start = {})
4557+ : parser (reinterpret_cast <const char *>(sv.data ()), sv.size (), rules,
4558+ start) {}
45474559
4548- parser (std::u8string_view sv)
4549- : parser (reinterpret_cast <const char *>(sv.data ()), sv.size (), Rules ()) {}
4560+ parser (std::u8string_view sv, std::string_view start = {})
4561+ : parser (reinterpret_cast <const char *>(sv.data ()), sv.size (), Rules (),
4562+ start) {}
45504563#endif
45514564
45524565 operator bool () { return grammar_ != nullptr ; }
45534566
4554- bool load_grammar (const char *s, size_t n, const Rules &rules) {
4555- grammar_ = ParserGenerator::parse (s, n, rules, start_,
4556- enablePackratParsing_, log_);
4567+ bool load_grammar (const char *s, size_t n, const Rules &rules,
4568+ std::string_view start = {}) {
4569+ auto cxt = ParserGenerator::parse (s, n, rules, log_, start);
4570+ grammar_ = cxt.grammar ;
4571+ start_ = cxt.start ;
4572+ enablePackratParsing_ = cxt.enablePackratParsing ;
45574573 return grammar_ != nullptr ;
45584574 }
45594575
4560- bool load_grammar (const char *s, size_t n) {
4561- return load_grammar (s, n, Rules ());
4576+ bool load_grammar (const char *s, size_t n, std::string_view start = {} ) {
4577+ return load_grammar (s, n, Rules (), start );
45624578 }
45634579
4564- bool load_grammar (std::string_view sv, const Rules &rules) {
4565- return load_grammar (sv.data (), sv.size (), rules);
4580+ bool load_grammar (std::string_view sv, const Rules &rules,
4581+ std::string_view start = {}) {
4582+ return load_grammar (sv.data (), sv.size (), rules, start);
45664583 }
45674584
4568- bool load_grammar (std::string_view sv) {
4569- return load_grammar (sv.data (), sv.size ());
4585+ bool load_grammar (std::string_view sv, std::string_view start = {} ) {
4586+ return load_grammar (sv.data (), sv.size (), start );
45704587 }
45714588
45724589 bool parse_n (const char *s, size_t n, const char *path = nullptr ) const {
@@ -4671,7 +4688,7 @@ class parser {
46714688 void enable_packrat_parsing () {
46724689 if (grammar_ != nullptr ) {
46734690 auto &rule = (*grammar_)[start_];
4674- rule.enablePackratParsing = enablePackratParsing_ && true ;
4691+ rule.enablePackratParsing = enablePackratParsing_;
46754692 }
46764693 }
46774694
0 commit comments