1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
from weakref import WeakKeyDictionary
from sphinx_a4doc.model.model import RuleBase, LexerRule, ParserRule
from typing import *
__all__ = [
'RuleContentVisitor',
'CachedRuleContentVisitor',
]
T = TypeVar('T')
class RuleContentVisitor(Generic[T]):
"""
Generic visitor for rule contents.
"""
def visit(self, r: RuleBase.RuleContent) -> T:
return getattr(self, r.__meta__.visitor_relay, self.visit_default)(r)
def visit_default(self, r: RuleBase.RuleContent) -> T:
raise RuntimeError(f'no visitor for {r.__class__.__name__!r}')
# Lexer
def visit_lexer_literal(self, r: LexerRule.Literal) -> T:
return self.visit_literal(r)
def visit_lexer_range(self, r: LexerRule.Range) -> T:
return self.visit_range(r)
def visit_lexer_charset(self, r: LexerRule.CharSet) -> T:
return self.visit_charset(r)
def visit_lexer_reference(self, r: LexerRule.Reference) -> T:
return self.visit_reference(r)
def visit_lexer_doc(self, r: LexerRule.Doc) -> T:
return self.visit_doc(r)
def visit_lexer_wildcard(self, r: LexerRule.Wildcard) -> T:
return self.visit_wildcard(r)
def visit_lexer_negation(self, r: LexerRule.Negation) -> T:
return self.visit_negation(r)
def visit_lexer_zero_plus(self, r: LexerRule.ZeroPlus) -> T:
return self.visit_zero_plus(r)
def visit_lexer_one_plus(self, r: LexerRule.OnePlus) -> T:
return self.visit_one_plus(r)
def visit_lexer_maybe(self, r: LexerRule.Maybe) -> T:
return self.visit_maybe(r)
def visit_lexer_sequence(self, r: LexerRule.Sequence) -> T:
return self.visit_sequence(r)
def visit_lexer_alternative(self, r: LexerRule.Alternative) -> T:
return self.visit_alternative(r)
# Parser
def visit_parser_reference(self, r: ParserRule.Reference) -> T:
return self.visit_reference(r)
def visit_parser_doc(self, r: ParserRule.Doc) -> T:
return self.visit_doc(r)
def visit_parser_wildcard(self, r: ParserRule.Wildcard) -> T:
return self.visit_wildcard(r)
def visit_parser_negation(self, r: ParserRule.Negation) -> T:
return self.visit_negation(r)
def visit_parser_zero_plus(self, r: ParserRule.ZeroPlus) -> T:
return self.visit_zero_plus(r)
def visit_parser_one_plus(self, r: ParserRule.OnePlus) -> T:
return self.visit_one_plus(r)
def visit_parser_maybe(self, r: ParserRule.Maybe) -> T:
return self.visit_maybe(r)
def visit_parser_sequence(self, r: ParserRule.Sequence) -> T:
return self.visit_sequence(r)
def visit_parser_alternative(self, r: ParserRule.Alternative) -> T:
return self.visit_alternative(r)
# Common
def visit_literal(self, r: LexerRule.Literal) -> T:
return self.visit_default(r)
def visit_range(self, r: LexerRule.Range) -> T:
return self.visit_default(r)
def visit_charset(self, r: LexerRule.CharSet) -> T:
return self.visit_default(r)
def visit_reference(self, r: RuleBase.Reference) -> T:
return self.visit_default(r)
def visit_doc(self, r: RuleBase.Doc) -> T:
return self.visit_default(r)
def visit_wildcard(self, r: RuleBase.Wildcard) -> T:
return self.visit_default(r)
def visit_negation(self, r: RuleBase.Negation) -> T:
return self.visit_default(r)
def visit_zero_plus(self, r: RuleBase.ZeroPlus) -> T:
return self.visit_default(r)
def visit_one_plus(self, r: RuleBase.OnePlus) -> T:
return self.visit_default(r)
def visit_maybe(self, r: RuleBase.Maybe) -> T:
return self.visit_default(r)
def visit_sequence(self, r: RuleBase.Sequence) -> T:
return self.visit_default(r)
def visit_alternative(self, r: RuleBase.Alternative) -> T:
return self.visit_default(r)
class CachedRuleContentVisitor(RuleContentVisitor[T]):
def __init__(self):
self._cache: Dict[RuleBase.RuleContent, T] = WeakKeyDictionary()
def visit(self, r: RuleBase.RuleContent) -> T:
if r not in self._cache:
self._cache[r] = super().visit(r)
return self._cache[r]
|