classes.py
Go to the documentation of this file.
1 """
2 GTSAM Copyright 2010-2020, Georgia Tech Research Corporation,
3 Atlanta, Georgia 30332-0415
4 All Rights Reserved
5 
6 See LICENSE for the license information
7 
8 Parser classes and rules for parsing C++ classes.
9 
10 Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert
11 """
12 
13 from typing import Iterable, List, Union
14 
15 from pyparsing import Literal, Optional, ZeroOrMore
16 
17 from .enum import Enum
18 from .function import ArgumentList, ReturnType
19 from .template import Template
20 from .tokens import (CLASS, COLON, CONST, IDENT, LBRACE, LPAREN, OPERATOR,
21  RBRACE, RPAREN, SEMI_COLON, STATIC, VIRTUAL)
22 from .type import TemplatedType, Typename
23 from .utils import collect_namespaces
24 from .variable import Variable
25 
26 
27 class Method:
28  """
29  Rule to parse a method in a class.
30 
31  E.g.
32  ```
33  class Hello {
34  void sayHello() const;
35  };
36  ```
37  """
38  rule = (
39  Optional(Template.rule("template")) #
40  + ReturnType.rule("return_type") #
41  + IDENT("name") #
42  + LPAREN #
43  + ArgumentList.rule("args_list") #
44  + RPAREN #
45  + Optional(CONST("is_const")) #
46  + SEMI_COLON # BR
47  ).setParseAction(lambda t: Method(t.template, t.name, t.return_type, t.
48  args_list, t.is_const))
49 
50  def __init__(self,
51  template: str,
52  name: str,
53  return_type: ReturnType,
54  args: ArgumentList,
55  is_const: str,
56  parent: Union[str, "Class"] = ''):
57  self.template = template
58  self.name = name
59  self.return_type = return_type
60  self.args = args
61  self.is_const = is_const
62 
63  self.parent = parent
64 
65  def __repr__(self) -> str:
66  return "Method: {} {} {}({}){}".format(
67  self.template,
68  self.return_type,
69  self.name,
70  self.args,
71  self.is_const,
72  )
73 
74 
76  """
77  Rule to parse all the static methods in a class.
78 
79  E.g.
80  ```
81  class Hello {
82  static void changeGreeting();
83  };
84  ```
85  """
86  rule = (
87  STATIC #
88  + ReturnType.rule("return_type") #
89  + IDENT("name") #
90  + LPAREN #
91  + ArgumentList.rule("args_list") #
92  + RPAREN #
93  + SEMI_COLON # BR
94  ).setParseAction(
95  lambda t: StaticMethod(t.name, t.return_type, t.args_list))
96 
97  def __init__(self,
98  name: str,
99  return_type: ReturnType,
100  args: ArgumentList,
101  parent: Union[str, "Class"] = ''):
102  self.name = name
103  self.return_type = return_type
104  self.args = args
105 
106  self.parent = parent
107 
108  def __repr__(self) -> str:
109  return "static {} {}{}".format(self.return_type, self.name, self.args)
110 
111  def to_cpp(self) -> str:
112  """Generate the C++ code for wrapping."""
113  return self.name
114 
115 
117  """
118  Rule to parse the class constructor.
119  Can have 0 or more arguments.
120  """
121  rule = (
122  IDENT("name") #
123  + LPAREN #
124  + ArgumentList.rule("args_list") #
125  + RPAREN #
126  + SEMI_COLON # BR
127  ).setParseAction(lambda t: Constructor(t.name, t.args_list))
128 
129  def __init__(self,
130  name: str,
131  args: ArgumentList,
132  parent: Union["Class", str] = ''):
133  self.name = name
134  self.args = args
135 
136  self.parent = parent
137 
138  def __repr__(self) -> str:
139  return "Constructor: {}".format(self.name)
140 
141 
142 class Operator:
143  """
144  Rule for parsing operator overloads.
145 
146  E.g.
147  ```
148  class Overload {
149  Vector2 operator+(const Vector2 &v) const;
150  };
151  """
152  rule = (
153  ReturnType.rule("return_type") #
154  + Literal("operator")("name") #
155  + OPERATOR("operator") #
156  + LPAREN #
157  + ArgumentList.rule("args_list") #
158  + RPAREN #
159  + CONST("is_const") #
160  + SEMI_COLON # BR
161  ).setParseAction(lambda t: Operator(t.name, t.operator, t.return_type, t.
162  args_list, t.is_const))
163 
164  def __init__(self,
165  name: str,
166  operator: str,
167  return_type: ReturnType,
168  args: ArgumentList,
169  is_const: str,
170  parent: Union[str, "Class"] = ''):
171  self.name = name
172  self.operator = operator
173  self.return_type = return_type
174  self.args = args
175  self.is_const = is_const
176  self.is_unary = len(args) == 0
177 
178  self.parent = parent
179 
180  # Check for valid unary operators
181  if self.is_unary and self.operator not in ('+', '-'):
182  raise ValueError("Invalid unary operator {} used for {}".format(
183  self.operator, self))
184 
185  # Check that number of arguments are either 0 or 1
186  assert 0 <= len(args) < 2, \
187  "Operator overload should be at most 1 argument, " \
188  "{} arguments provided".format(len(args))
189 
190  # Check to ensure arg and return type are the same.
191  if len(args) == 1 and self.operator not in ("()", "[]"):
192  assert args.args_list[0].ctype.typename.name == return_type.type1.typename.name, \
193  "Mixed type overloading not supported. Both arg and return type must be the same."
194 
195  def __repr__(self) -> str:
196  return "Operator: {}{}{}({}) {}".format(
197  self.return_type,
198  self.name,
199  self.operator,
200  self.args,
201  self.is_const,
202  )
203 
204 
205 class Class:
206  """
207  Rule to parse a class defined in the interface file.
208 
209  E.g.
210  ```
211  class Hello {
212  ...
213  };
214  ```
215  """
216  class Members:
217  """
218  Rule for all the members within a class.
219  """
220  rule = ZeroOrMore(Constructor.rule #
221  ^ StaticMethod.rule #
222  ^ Method.rule #
223  ^ Variable.rule #
224  ^ Operator.rule #
225  ^ Enum.rule #
226  ).setParseAction(lambda t: Class.Members(t.asList()))
227 
228  def __init__(self,
229  members: List[Union[Constructor, Method, StaticMethod,
230  Variable, Operator]]):
231  self.ctors = []
232  self.methods = []
233  self.static_methods = []
234  self.properties = []
235  self.operators = []
236  self.enums = []
237  for m in members:
238  if isinstance(m, Constructor):
239  self.ctors.append(m)
240  elif isinstance(m, Method):
241  self.methods.append(m)
242  elif isinstance(m, StaticMethod):
243  self.static_methods.append(m)
244  elif isinstance(m, Variable):
245  self.properties.append(m)
246  elif isinstance(m, Operator):
247  self.operators.append(m)
248  elif isinstance(m, Enum):
249  self.enums.append(m)
250 
251  _parent = COLON + (TemplatedType.rule ^ Typename.rule)("parent_class")
252  rule = (
253  Optional(Template.rule("template")) #
254  + Optional(VIRTUAL("is_virtual")) #
255  + CLASS #
256  + IDENT("name") #
257  + Optional(_parent) #
258  + LBRACE #
259  + Members.rule("members") #
260  + RBRACE #
261  + SEMI_COLON # BR
262  ).setParseAction(lambda t: Class(
263  t.template,
264  t.is_virtual,
265  t.name,
266  t.parent_class,
267  t.members.ctors,
268  t.members.methods,
269  t.members.static_methods,
270  t.members.properties,
271  t.members.operators,
272  t.members.enums
273  ))
274 
275  def __init__(
276  self,
277  template: Template,
278  is_virtual: str,
279  name: str,
280  parent_class: list,
281  ctors: List[Constructor],
282  methods: List[Method],
283  static_methods: List[StaticMethod],
284  properties: List[Variable],
285  operators: List[Operator],
286  enums: List[Enum],
287  parent: str = '',
288  ):
289  self.template = template
290  self.is_virtual = is_virtual
291  self.name = name
292  if parent_class:
293  # If it is in an iterable, extract the parent class.
294  if isinstance(parent_class, Iterable):
295  parent_class = parent_class[0]
296 
297  # If the base class is a TemplatedType,
298  # we want the instantiated Typename
299  if isinstance(parent_class, TemplatedType):
300  parent_class = parent_class.typename
301 
302  self.parent_class = parent_class
303  else:
304  self.parent_class = ''
305 
306  self.ctors = ctors
307  self.methods = methods
308  self.static_methods = static_methods
309  self.properties = properties
310  self.operators = operators
311  self.enums = enums
312 
313  self.parent = parent
314 
315  # Make sure ctors' names and class name are the same.
316  for ctor in self.ctors:
317  if ctor.name != self.name:
318  raise ValueError("Error in constructor name! {} != {}".format(
319  ctor.name, self.name))
320 
321  for ctor in self.ctors:
322  ctor.parent = self
323  for method in self.methods:
324  method.parent = self
325  for static_method in self.static_methods:
326  static_method.parent = self
327  for _property in self.properties:
328  _property.parent = self
329 
330  def namespaces(self) -> list:
331  """Get the namespaces which this class is nested under as a list."""
332  return collect_namespaces(self)
333 
334  def __repr__(self):
335  return "Class: {self.name}".format(self=self)
bool isinstance(handle obj)
Definition: pytypes.h:384
size_t len(handle h)
Definition: pytypes.h:1514


gtsam
Author(s):
autogenerated on Sat May 8 2021 02:41:47