33import typing
44import markdown
55from typedecorator import params , returns , Nullable
6+ from typing import Any , List , TypedDict
67
8+ class TableDict (TypedDict ):
9+ columns : List [str ]
10+ values : List [List [Any ]]
711
812class ParameterDoc (object ):
913 """The documentation data of a parameter or return value for an ALE method."""
@@ -65,13 +69,24 @@ def __init__(self, name, data_type, description, default_value=None):
6569
6670class MethodDoc (object ):
6771 """The documentation data of an ALE method."""
68- @params (self = object , name = str , description = str , prototypes = [str ], parameters = [ParameterDoc ], returned = [ParameterDoc ])
69- def __init__ (self , name , description , prototypes , parameters , returned ):
72+ @params (self = object , name = str , description = str , table = TableDict , prototypes = [str ], parameters = [ParameterDoc ], returned = [ParameterDoc ])
73+ def __init__ (self , name , description , table , prototypes , parameters , returned ):
7074 self .name = name
7175 self .prototypes = prototypes
76+ self .table = table
7277 self .parameters = parameters
7378 self .returned = returned
7479
80+ if table :
81+ # Generate Markdown Table
82+ md_table = '| ' + ' | ' .join (table ['columns' ]) + ' |\n ' # Header
83+ md_table += '| ' + ' | ' .join (['---' ] * len (table ['columns' ])) + ' |\n ' # Separator
84+
85+ for row in table ['values' ]:
86+ md_table += '| ' + ' | ' .join (row ) + ' |\n ' # Rows
87+
88+ self .table = markdown .markdown (md_table , extensions = ['tables' ])
89+
7590 # Parse the description as Markdown.
7691 self .description = markdown .markdown (description )
7792 # Pull the first paragraph out of the description as the short description.
@@ -123,6 +138,11 @@ class ClassParser(object):
123138 body_regex = re .compile (r"\s*\s?\*\s?(.*)" ) # The "body", i.e. a * and optionally some descriptive text.
124139 # An extra optional space (\s?) was thrown in to make it different from `class_body_regex`.
125140
141+ # Regular expressions for parsing a table.
142+ table_regex = re .compile (r"\s*\*\s@table" )
143+ table_columns_regex = re .compile (r"\s*\*\s@columns\s*\[(.+)\]" )
144+ table_values_regex = re .compile (r"\s*\*\s@values\s*\[(.+)\]" )
145+
126146 param_regex = re .compile (r"""\s*\*\s@param\s # The @param tag starts with opt. whitespace followed by "* @param ".
127147 ([^\s]+)\s(\w+)? # The data type, a space, and the name of the param.
128148 (?:\s=\s(\w+))? # The default value: a = surrounded by spaces, followed by text.
@@ -163,6 +183,7 @@ def reset(self):
163183 self .returned = []
164184 self .method_name = None
165185 self .prototypes = []
186+ self .table = {}
166187
167188 def handle_class_body (self , match ):
168189 text = match .group (1 )
@@ -171,6 +192,21 @@ def handle_class_body(self, match):
171192 def handle_body (self , match ):
172193 text = match .group (1 )
173194 self .description += text + '\n '
195+
196+ def handle_table (self , line ):
197+ self .table = {
198+ "columns" : [],
199+ "values" : []
200+ }
201+
202+ def handle_table_columns (self , match ):
203+ if self .table :
204+ self .table ["columns" ] = match .group (1 ).split (", " )
205+
206+ def handle_table_values (self , match ):
207+ if self .table :
208+ values = re .findall (r'(?:[^,"]|"(?:\\.|[^"])*")+' , match .group (1 ))
209+ self .table ["values" ].append ([v .strip (' "' ) for v in values ])
174210
175211 def handle_param (self , match ):
176212 data_type , name , default , description = match .group (1 ), match .group (2 ), match .group (3 ), match .group (4 )
@@ -247,7 +283,7 @@ def make_prototype(parameters):
247283 # Format the method name into each prototype.
248284 self .prototypes = [proto .format (self .method_name ) for proto in self .prototypes ]
249285
250- self .methods .append (MethodDoc (self .method_name , self .description , self .prototypes , self .params , self .returned ))
286+ self .methods .append (MethodDoc (self .method_name , self .description , self .table , self . prototypes , self .params , self .returned ))
251287
252288 # Table of which handler is used to handle each regular expressions.
253289 regex_handlers = {
@@ -256,6 +292,9 @@ def make_prototype(parameters):
256292 class_end_regex : None ,
257293 start_regex : None ,
258294 body_regex : handle_body ,
295+ table_regex : handle_table ,
296+ table_columns_regex : handle_table_columns ,
297+ table_values_regex : handle_table_values ,
259298 param_regex : handle_param ,
260299 return_regex : handle_return ,
261300 proto_regex : handle_proto ,
@@ -270,10 +309,13 @@ def make_prototype(parameters):
270309 class_start_regex : [class_end_regex , class_body_regex ],
271310 class_body_regex : [class_end_regex , class_body_regex ],
272311 class_end_regex : [],
273- start_regex : [param_regex , return_regex , proto_regex , comment_end_regex , body_regex ],
274- body_regex : [param_regex , return_regex , proto_regex , comment_end_regex , body_regex ],
275- proto_regex : [param_regex , return_regex , proto_regex , comment_end_regex , body_regex ],
276- param_regex : [param_regex , return_regex , comment_end_regex , body_regex ],
312+ start_regex : [table_regex , param_regex , return_regex , proto_regex , comment_end_regex , body_regex ],
313+ body_regex : [table_regex , param_regex , return_regex , proto_regex , comment_end_regex , body_regex ],
314+ proto_regex : [table_regex , param_regex , return_regex , proto_regex , comment_end_regex , body_regex ],
315+ table_regex : [table_regex , table_columns_regex , param_regex , return_regex , comment_end_regex , body_regex ],
316+ table_columns_regex : [table_values_regex , param_regex , return_regex , comment_end_regex , body_regex ],
317+ table_values_regex : [table_values_regex , param_regex , return_regex , comment_end_regex , body_regex ],
318+ param_regex : [table_regex , param_regex , return_regex , comment_end_regex , body_regex ],
277319 return_regex : [return_regex , comment_end_regex ],
278320 comment_end_regex : [end_regex ],
279321 end_regex : [],
0 commit comments