bpo-40334: use the TOKENS file when checking dangling rules by pablogsal · Pull Request #19849 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions Tools/peg_generator/pegen/build.py
3 changes: 2 additions & 1 deletion Tools/peg_generator/pegen/c_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,14 @@ class CParserGenerator(ParserGenerator, GrammarVisitor):
def __init__(
self,
grammar: grammar.Grammar,
tokens: Dict[int, str],
exact_tokens: Dict[str, int],
non_exact_tokens: Set[str],
file: Optional[IO[Text]],
debug: bool = False,
skip_actions: bool = False,
):
super().__init__(grammar, file)
super().__init__(grammar, tokens, file)
self.callmakervisitor: CCallMakerVisitor = CCallMakerVisitor(
self, exact_tokens, non_exact_tokens
)
Expand Down
11 changes: 6 additions & 5 deletions Tools/peg_generator/pegen/parser_generator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import contextlib
import token
from abc import abstractmethod

from typing import AbstractSet, Dict, IO, Iterator, List, Optional, Set, Text, Tuple
Expand All @@ -19,11 +18,12 @@


class RuleCheckingVisitor(GrammarVisitor):
def __init__(self, rules: Dict[str, Rule]):
def __init__(self, rules: Dict[str, Rule], tokens: Dict[int, str]):
self.rules = rules
self.tokens = tokens

def visit_NameLeaf(self, node: NameLeaf) -> None:
if node.value not in self.rules and node.value not in token.tok_name.values():
if node.value not in self.rules and node.value not in self.tokens.values():
# TODO: Add line/col info to (leaf) nodes
raise GrammarError(f"Dangling reference to rule {node.value!r}")

Expand All @@ -32,12 +32,13 @@ class ParserGenerator:

callmakervisitor: GrammarVisitor

def __init__(self, grammar: Grammar, file: Optional[IO[Text]]):
def __init__(self, grammar: Grammar, tokens: Dict[int, str], file: Optional[IO[Text]]):
self.grammar = grammar
self.tokens = tokens
self.rules = grammar.rules
if "trailer" not in grammar.metas and "start" not in self.rules:
raise GrammarError("Grammar without a trailer must have a 'start' rule")
checker = RuleCheckingVisitor(self.rules)
checker = RuleCheckingVisitor(self.rules, self.tokens)
for rule in self.rules.values():
checker.visit(rule)
self.file = file
Expand Down
10 changes: 8 additions & 2 deletions Tools/peg_generator/pegen/python_generator.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import token
from typing import Any, Dict, Optional, IO, Text, Tuple

from pegen.grammar import (
Expand Down Expand Up @@ -123,8 +124,13 @@ def visit_Cut(self, node: Cut) -> Tuple[str, str]:


class PythonParserGenerator(ParserGenerator, GrammarVisitor):
def __init__(self, grammar: grammar.Grammar, file: Optional[IO[Text]]):
super().__init__(grammar, file)
def __init__(
self,
grammar: grammar.Grammar,
file: Optional[IO[Text]],
tokens: Dict[int, str] = token.tok_name,
):
super().__init__(grammar, tokens, file)
self.callmakervisitor = PythonCallMakerVisitor(self)

def generate(self, filename: str) -> None:
Expand Down
7 changes: 5 additions & 2 deletions Tools/peg_generator/pegen/testutil.py