This repository has been archived by the owner on Dec 16, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 40
/
new_sphinx.py
171 lines (150 loc) · 4.57 KB
/
new_sphinx.py
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
from typing import (
List,
)
from functools import (
reduce,
)
from ..token import (
Token,
TokenType,
KEYWORDS,
)
from .cyk import (
CykNode,
parse as cyk_parse,
)
from .combinator import (
parser_combinator,
)
from .grammars.sphinx_arguments_section import ArgumentsGrammar
from .grammars.sphinx_argument_type_section import ArgumentTypeGrammar
from .grammars.sphinx_long_description import LongDescriptionGrammar
from .grammars.sphinx_variables_section import VariablesSectionGrammar
from .grammars.sphinx_variable_type_section import VariableTypeGrammar
from .grammars.sphinx_raises_section import RaisesGrammar
from .grammars.sphinx_returns_section import ReturnsGrammar
from .grammars.sphinx_return_type_section import ReturnTypeGrammar
from .grammars.sphinx_short_description import ShortDescriptionGrammar
from .grammars.sphinx_yields_section import YieldsGrammar
from .grammars.sphinx_yield_type_section import YieldTypeGrammar
def two_newline_separated_or_keyword(tokens, i):
# type: (List[Token], int) -> int
newline_count = 0
j = i
while j < len(tokens):
if tokens[j].token_type == TokenType.NEWLINE:
newline_count += 1
else:
break
j += 1
if newline_count >= 2:
return j
if (j + 1 < len(tokens)
and tokens[j].token_type == TokenType.COLON
and tokens[j + 1].token_type in KEYWORDS):
return j
return 0
def top_parse(tokens):
# type: (List[Token]) -> List[List[Token]]
all_sections = list()
curr = 0
# Strip leading newlines.
while curr < len(tokens) and tokens[curr].token_type == TokenType.NEWLINE:
curr += 1
prev = curr
while curr < len(tokens):
split_end = two_newline_separated_or_keyword(tokens, curr)
if split_end > curr:
if tokens[prev:curr]:
all_sections.append(
tokens[prev:curr]
)
curr = split_end
prev = curr
else:
curr += 1
last_section = tokens[prev:curr]
if last_section:
all_sections.append(last_section)
return all_sections
def _match(token):
"""Match the given token from the given section to a set of grammars.
Args:
token: The token to match. This should hint at what sections
could possibly be here.
Returns:
A list of grammars to be tried in order.
"""
tt_lookup = {
TokenType.VARIABLES: [
VariablesSectionGrammar,
LongDescriptionGrammar,
],
TokenType.ARGUMENTS: [
ArgumentsGrammar,
LongDescriptionGrammar,
],
TokenType.ARGUMENT_TYPE: [
ArgumentTypeGrammar,
LongDescriptionGrammar,
],
TokenType.VARIABLE_TYPE: [
VariableTypeGrammar,
LongDescriptionGrammar,
],
TokenType.RAISES: [
RaisesGrammar,
LongDescriptionGrammar,
],
TokenType.YIELDS: [
YieldsGrammar,
LongDescriptionGrammar,
],
TokenType.YIELD_TYPE: [
YieldTypeGrammar,
LongDescriptionGrammar,
],
TokenType.RETURNS: [
ReturnsGrammar,
LongDescriptionGrammar,
],
TokenType.RETURN_TYPE: [
ReturnTypeGrammar,
LongDescriptionGrammar,
],
}
return tt_lookup.get(token.token_type, [LongDescriptionGrammar])
def lookup(section, section_index=-1):
assert len(section) > 0
if (section[0].token_type == TokenType.COLON
and len(section) > 1):
grammars = _match(section[1])
else:
grammars = [LongDescriptionGrammar]
if section_index == 0:
return [ShortDescriptionGrammar] + grammars
return grammars
def combinator(*args):
def inner(*nodes):
if len(nodes) == 1:
return CykNode(
symbol='docstring',
lchild=nodes[0],
)
elif len(nodes) == 2:
return CykNode(
symbol='docstring',
lchild=nodes[0],
rchild=nodes[1],
)
if args:
return reduce(inner, args)
else:
# The arguments are empty, so we return an
# empty docstring.
return CykNode(symbol='docstring')
def parse(tokens):
def mapped_lookup(section, section_index=-1):
for grammar in lookup(section, section_index):
yield lambda x: cyk_parse(grammar, x)
return parser_combinator(top_parse, mapped_lookup, combinator, tokens)