@@ -3298,18 +3298,15 @@ using Rules = std::unordered_map<std::string, std::shared_ptr<Ope>>;
3298
3298
3299
3299
class ParserGenerator {
3300
3300
public:
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
+ };
3307
3306
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));
3313
3310
}
3314
3311
3315
3312
// For debugging purpose
@@ -3989,9 +3986,8 @@ class ParserGenerator {
3989
3986
return true ;
3990
3987
}
3991
3988
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) {
3995
3991
Data data;
3996
3992
auto &grammar = *data.grammar ;
3997
3993
@@ -4023,7 +4019,7 @@ class ParserGenerator {
4023
4019
log (line.first , line.second , " syntax error" , r.error_info .label );
4024
4020
}
4025
4021
}
4026
- return nullptr ;
4022
+ return {} ;
4027
4023
}
4028
4024
4029
4025
// User provided rules
@@ -4081,7 +4077,25 @@ class ParserGenerator {
4081
4077
}
4082
4078
4083
4079
// 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];
4085
4099
4086
4100
// Check if the start rule has ignore operator
4087
4101
{
@@ -4096,7 +4110,7 @@ class ParserGenerator {
4096
4110
}
4097
4111
}
4098
4112
4099
- if (!ret) { return nullptr ; }
4113
+ if (!ret) { return {} ; }
4100
4114
4101
4115
// Check missing definitions
4102
4116
auto referenced = std::unordered_set<std::string>{
@@ -4129,7 +4143,7 @@ class ParserGenerator {
4129
4143
}
4130
4144
}
4131
4145
4132
- if (!ret) { return nullptr ; }
4146
+ if (!ret) { return {} ; }
4133
4147
4134
4148
// Link references
4135
4149
for (auto &x : grammar) {
@@ -4153,10 +4167,10 @@ class ParserGenerator {
4153
4167
}
4154
4168
}
4155
4169
4156
- if (!ret) { return nullptr ; }
4170
+ if (!ret) { return {} ; }
4157
4171
4158
4172
// Check infinite loop
4159
- if (detect_infiniteLoop (data, start_rule, log , s)) { return nullptr ; }
4173
+ if (detect_infiniteLoop (data, start_rule, log , s)) { return {} ; }
4160
4174
4161
4175
// Automatic whitespace skipping
4162
4176
if (grammar.count (WHITESPACE_DEFINITION_NAME)) {
@@ -4169,15 +4183,15 @@ class ParserGenerator {
4169
4183
auto &rule = grammar[WHITESPACE_DEFINITION_NAME];
4170
4184
start_rule.whitespaceOpe = wsp (rule.get_core_operator ());
4171
4185
4172
- if (detect_infiniteLoop (data, rule, log , s)) { return nullptr ; }
4186
+ if (detect_infiniteLoop (data, rule, log , s)) { return {} ; }
4173
4187
}
4174
4188
4175
4189
// Word expression
4176
4190
if (grammar.count (WORD_DEFINITION_NAME)) {
4177
4191
auto &rule = grammar[WORD_DEFINITION_NAME];
4178
4192
start_rule.wordOpe = rule.get_core_operator ();
4179
4193
4180
- if (detect_infiniteLoop (data, rule, log , s)) { return nullptr ; }
4194
+ if (detect_infiniteLoop (data, rule, log , s)) { return {} ; }
4181
4195
}
4182
4196
4183
4197
// Apply instructions
@@ -4189,9 +4203,7 @@ class ParserGenerator {
4189
4203
const auto &info =
4190
4204
std::any_cast<PrecedenceClimbing::BinOpeInfo>(instruction.data );
4191
4205
4192
- if (!apply_precedence_instruction (rule, info, s, log )) {
4193
- return nullptr ;
4194
- }
4206
+ if (!apply_precedence_instruction (rule, info, s, log )) { return {}; }
4195
4207
} else if (instruction.type == " error_message" ) {
4196
4208
rule.error_message = std::any_cast<std::string>(instruction.data );
4197
4209
} else if (instruction.type == " no_ast_opt" ) {
@@ -4200,11 +4212,7 @@ class ParserGenerator {
4200
4212
}
4201
4213
}
4202
4214
4203
- // Set root definition
4204
- start = data.start ;
4205
- enablePackratParsing = data.enablePackratParsing ;
4206
-
4207
- return data.grammar ;
4215
+ return {data.grammar , start, data.enablePackratParsing };
4208
4216
}
4209
4217
4210
4218
bool detect_infiniteLoop (const Data &data, Definition &rule, const Log &log,
@@ -4530,43 +4538,52 @@ class parser {
4530
4538
public:
4531
4539
parser () = default ;
4532
4540
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);
4535
4544
}
4536
4545
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) {}
4538
4548
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 ) {}
4541
4551
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) {}
4543
4554
4544
4555
#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) {}
4547
4559
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) {}
4550
4563
#endif
4551
4564
4552
4565
operator bool () { return grammar_ != nullptr ; }
4553
4566
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 ;
4557
4573
return grammar_ != nullptr ;
4558
4574
}
4559
4575
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 );
4562
4578
}
4563
4579
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);
4566
4583
}
4567
4584
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 );
4570
4587
}
4571
4588
4572
4589
bool parse_n (const char *s, size_t n, const char *path = nullptr ) const {
@@ -4671,7 +4688,7 @@ class parser {
4671
4688
void enable_packrat_parsing () {
4672
4689
if (grammar_ != nullptr ) {
4673
4690
auto &rule = (*grammar_)[start_];
4674
- rule.enablePackratParsing = enablePackratParsing_ && true ;
4691
+ rule.enablePackratParsing = enablePackratParsing_;
4675
4692
}
4676
4693
}
4677
4694
0 commit comments