GBNF generation implementation
| 1247 | |
| 1248 | // GBNF generation implementation |
| 1249 | void common_peg_arena::build_grammar(const common_grammar_builder & builder, bool lazy) const { |
| 1250 | // Generate GBNF for a parser |
| 1251 | std::function<std::string(common_peg_parser_id)> to_gbnf = [&](common_peg_parser_id id) -> std::string { |
| 1252 | const auto & parser = parsers_.at(id); |
| 1253 | |
| 1254 | return std::visit([&](const auto & p) -> std::string { |
| 1255 | using T = std::decay_t<decltype(p)>; |
| 1256 | |
| 1257 | if constexpr (std::is_same_v<T, common_peg_epsilon_parser> || |
| 1258 | std::is_same_v<T, common_peg_start_parser> || |
| 1259 | std::is_same_v<T, common_peg_end_parser>) { |
| 1260 | return ""; |
| 1261 | } else if constexpr (std::is_same_v<T, common_peg_literal_parser>) { |
| 1262 | return gbnf_format_literal(p.literal); |
| 1263 | } else if constexpr (std::is_same_v<T, common_peg_sequence_parser>) { |
| 1264 | std::string s; |
| 1265 | for (const auto & child : p.children) { |
| 1266 | if (!s.empty()) { |
| 1267 | s += " "; |
| 1268 | } |
| 1269 | auto child_gbnf = to_gbnf(child); |
| 1270 | const auto & child_parser = parsers_.at(child); |
| 1271 | if (std::holds_alternative<common_peg_choice_parser>(child_parser) || |
| 1272 | std::holds_alternative<common_peg_sequence_parser>(child_parser)) { |
| 1273 | s += "(" + child_gbnf + ")"; |
| 1274 | } else { |
| 1275 | s += child_gbnf; |
| 1276 | } |
| 1277 | } |
| 1278 | return s; |
| 1279 | } else if constexpr (std::is_same_v<T, common_peg_choice_parser>) { |
| 1280 | std::string s; |
| 1281 | for (const auto & child : p.children) { |
| 1282 | if (!s.empty()) { |
| 1283 | s += " | "; |
| 1284 | } |
| 1285 | auto child_gbnf = to_gbnf(child); |
| 1286 | const auto & child_parser = parsers_.at(child); |
| 1287 | if (std::holds_alternative<common_peg_choice_parser>(child_parser)) { |
| 1288 | s += "(" + child_gbnf + ")"; |
| 1289 | } else { |
| 1290 | s += child_gbnf; |
| 1291 | } |
| 1292 | } |
| 1293 | return s; |
| 1294 | } else if constexpr (std::is_same_v<T, common_peg_repetition_parser>) { |
| 1295 | auto child_gbnf = to_gbnf(p.child); |
| 1296 | const auto & child_parser = parsers_.at(p.child); |
| 1297 | if (std::holds_alternative<common_peg_choice_parser>(child_parser) || |
| 1298 | std::holds_alternative<common_peg_sequence_parser>(child_parser)) { |
| 1299 | child_gbnf = "(" + child_gbnf + ")"; |
| 1300 | } |
| 1301 | if (p.min_count == 0 && p.max_count == 1) { |
| 1302 | return child_gbnf + "?"; |
| 1303 | } |
| 1304 | if (p.min_count == 0 && p.max_count == -1) { |
| 1305 | return child_gbnf + "*"; |
| 1306 | } |