| 453 | self.print("}") |
| 454 | |
| 455 | def generate(self, filename: str) -> None: |
| 456 | self.collect_rules() |
| 457 | basename = os.path.basename(filename) |
| 458 | self.print(f"// @generated by pegen from {basename}") |
| 459 | header = self.grammar.metas.get("header", EXTENSION_PREFIX) |
| 460 | if header: |
| 461 | self.print(header.rstrip("\n")) |
| 462 | subheader = self.grammar.metas.get("subheader", "") |
| 463 | if subheader: |
| 464 | self.print(subheader) |
| 465 | self._setup_keywords() |
| 466 | self._setup_soft_keywords() |
| 467 | for i, (rulename, rule) in enumerate(self.all_rules.items(), 1000): |
| 468 | comment = " // Left-recursive" if rule.left_recursive else "" |
| 469 | self.print(f"#define {rulename}_type {i}{comment}") |
| 470 | self.print() |
| 471 | for rulename, rule in self.all_rules.items(): |
| 472 | if rule.is_loop() or rule.is_gather(): |
| 473 | type = "asdl_seq *" |
| 474 | elif rule.type: |
| 475 | type = rule.type + " " |
| 476 | else: |
| 477 | type = "void *" |
| 478 | self.print(f"static {type}{rulename}_rule(Parser *p);") |
| 479 | self.print() |
| 480 | for rulename, rule in list(self.all_rules.items()): |
| 481 | self.print() |
| 482 | if rule.left_recursive: |
| 483 | self.print("// Left-recursive") |
| 484 | self.visit(rule) |
| 485 | if self.skip_actions: |
| 486 | mode = 0 |
| 487 | else: |
| 488 | mode = int(self.rules["start"].type == "mod_ty") if "start" in self.rules else 1 |
| 489 | if mode == 1 and self.grammar.metas.get("bytecode"): |
| 490 | mode += 1 |
| 491 | modulename = self.grammar.metas.get("modulename", "parse") |
| 492 | trailer = self.grammar.metas.get("trailer", EXTENSION_SUFFIX) |
| 493 | if trailer: |
| 494 | self.print(trailer.rstrip("\n") % dict(mode=mode, modulename=modulename)) |
| 495 | |
| 496 | def _group_keywords_by_length(self) -> dict[int, list[tuple[str, int]]]: |
| 497 | groups: dict[int, list[tuple[str, int]]] = {} |