Skip to content

Commit c9e68c7

Browse files
committed
better classdef parsing including changes to MATLAB-language-grammar prs #86, #88, and #90
1 parent 90a5cd2 commit c9e68c7

File tree

1 file changed

+93
-44
lines changed

1 file changed

+93
-44
lines changed

sphinxcontrib/mat_textmate_parser.py

Lines changed: 93 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from textmate_grammar.parsers.matlab import MatlabParser
22

3-
rpath = "../tests/test_data/ClassWithPropertyValidators.m"
3+
rpath = "../../../syscop/software/nosnoc/+nosnoc/Options.m"
44

55

66
def find_first_child(curr, tok):
@@ -49,71 +49,119 @@ def __init__(self, path):
4949
pdb.set_trace()
5050

5151
def _find_class_docstring(self):
52-
if self.cls.children[1].token == "comment.line.percentage.matlab":
52+
try:
53+
possible_comment_tok = self.cls.children[1]
54+
except IndexError:
55+
print("found no docstring")
56+
return
57+
58+
if possible_comment_tok.token == "comment.line.percentage.matlab":
5359
self._docstring_lines()
54-
elif self.cls.children[1].token == "comment.block.percentage.matlab":
55-
self.docstring = (
56-
self.cls.children[1].content.strip()[2:-2].strip()
57-
) # [2,-2] strips out block comment delimiters
60+
elif possible_comment_tok.token == "comment.block.percentage.matlab":
61+
self.docstring = possible_comment_tok.content.strip()[
62+
2:-2
63+
].strip() # [2,-2] strips out block comment delimiters
5864
else:
5965
print("found no docstring")
6066

6167
def _docstring_lines(self):
6268
idx = 1
63-
while self.cls.children[idx].token == "comment.line.percentage.matlab":
69+
cls_children = self.cls.children
70+
71+
while (
72+
idx < len(cls_children)
73+
and cls_children[idx].token == "comment.line.percentage.matlab"
74+
):
6475
self.docstring += (
65-
self.cls.children[idx].content[1:] + "\n"
76+
cls_children[idx].content[1:] + "\n"
6677
) # [1:] strips out percent sign
6778
idx += 1
6879
self.docstring = self.docstring.strip()
6980

7081
def _parse_clsdef(self):
71-
for child in self.clsdef.children:
72-
child.print()
82+
# Try parsing attrs
83+
attrs_tok_gen = self.clsdef.find(tokens="storage.modifier.section.class.matlab")
84+
try:
85+
attrs_tok, _ = next(attrs_tok_gen)
86+
self._parse_class_attributes(attrs_tok)
87+
except StopIteration:
88+
pass
7389

90+
# Parse classname
91+
classname_tok_gen = self.clsdef.find(tokens="entity.name.type.class.matlab")
92+
try:
93+
classname_tok, _ = next(classname_tok_gen)
94+
self.name = classname_tok.content
95+
except StopIteration:
96+
print("ClassName not found") # TODO this is probably fatal
97+
98+
# Parse interited classes
99+
parent_class_toks = self.clsdef.findall(tokens="meta.inherited-class.matlab")
100+
101+
for parent_class_tok, _ in parent_class_toks:
102+
sections = parent_class_tok.findall(
103+
tokens=[
104+
"entity.name.namespace.matlab",
105+
"entity.other.inherited-class.matlab",
106+
]
107+
)
108+
super_cls = tuple([sec.content for sec, _ in sections])
109+
self.supers.append(super_cls)
74110
# Parse Attributes TODO maybe there is a smarter way to do this?
75111
idx = 0
76112
while self.clsdef.children[idx].token == "storage.modifier.class.matlab":
77-
attr = self.clsdef.children[idx].content
113+
attr_tok = self.clsdef.children[idx]
114+
attr = atter_tok.content
78115
val = None # TODO maybe do some typechecking here or we can assume that you give us valid Matlab
79116
idx += 1
80-
if (
81-
self.clsdef.children[idx].token == "keyword.operator.assignment.matlab"
82-
): # pull out r.h.s
117+
if attr_tok.token == "keyword.operator.assignment.matlab": # pull out r.h.s
83118
idx += 1
84119
val = self.clsdef.children[idx].content
85120
idx += 1
86121
if (
87-
self.clsdef.children[idx].token
88-
== "punctuation.separator.modifier.comma.matlab"
122+
attr_tok.token == "punctuation.separator.modifier.comma.matlab"
89123
): # skip commas
90124
idx += 1
91125
self.attrs[attr] = val
92126

93-
if (
94-
self.clsdef.children[idx].token == "punctuation.section.parens.end.matlab"
95-
): # Skip end of attrs
96-
idx += 1
97-
98-
# name must be next
99-
self.name = self.clsdef.children[idx].content
100-
idx += 1
101-
102-
while idx < len(
103-
self.clsdef.children
104-
): # No children we care about after this except inherited classes
105-
if self.clsdef.children[idx].token == "meta.inherited-class.matlab":
106-
super_cls_tok = self.clsdef.children[idx]
107-
# collect superclass as a tuple
108-
super_cls = tuple(
109-
[
110-
child.content
111-
for child in super_cls_tok.children
112-
if not child.token.startswith("punctuation")
113-
]
114-
)
115-
self.supers.append(super_cls)
116-
idx += 1
127+
def _parse_class_attributes(self, attrs_tok):
128+
# walk down child list and parse manually
129+
# TODO perhaps contribute a delimited list find to textmate-grammar-python
130+
children = attrs_tok.children
131+
idx = 0
132+
while idx < len(children):
133+
child_tok = children[idx]
134+
if child_tok.token == "storage.modifier.class.matlab":
135+
attr = child_tok.content
136+
val = None
137+
idx += 1 # walk to next token
138+
maybe_assign_tok = children[idx]
139+
if maybe_assign_tok.token == "keyword.operator.assignment.matlab":
140+
idx += 1
141+
rhs_tok = children[idx] # parse right hand side
142+
if rhs_tok.token == "meta.cell.literal.matlab":
143+
# A cell. For now just take the whole cell as value.
144+
# TODO parse out the cell array of metaclass literals.
145+
val = "{" + rhs_tok.content + "}"
146+
idx += 1
147+
elif rhs_tok.token == "constant.language.boolean.matlab":
148+
val = rhs_tok.content
149+
idx += 1
150+
elif rhs_tok.token == "keyword.operator.other.question.matlab":
151+
idx += 1
152+
metaclass_tok = children[idx]
153+
metaclass_components = metaclass_tok.findall(
154+
tokens=[
155+
"entity.name.namespace.matlab",
156+
"entity.other.class.matlab",
157+
]
158+
)
159+
val = tuple([comp.content for comp, _ in metaclass_components])
160+
else:
161+
pass
162+
self.attrs[attr] = val
163+
else: # Comma or continuation therefore skip
164+
idx += 1
117165

118166
def _parse_property_section(self, section):
119167
# TODO parse property section attrs
@@ -241,12 +289,13 @@ def _parse_property_validation(self, prop_name, prop):
241289
# Now find list of validators
242290
validator_gen = prop.find(tokens="meta.block.validation.matlab", depth=1)
243291
try:
244-
import pdb
245-
246-
pdb.set_trace()
247292
validator_tok, _ = next(validator_gen)
248293
validator_toks = validator_tok.findall(
249-
tokens="variable.other.readwrite.matlab", depth=1
294+
tokens=[
295+
"variable.other.readwrite.matlab",
296+
"meta.function-call.parens.matlab",
297+
],
298+
depth=1,
250299
) # TODO Probably bug here in MATLAB-Language-grammar
251300
self.properties[prop_name]["validators"] = [
252301
tok[0].content for tok in validator_toks

0 commit comments

Comments
 (0)