interface_parser/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 Any, Iterable, List, Union
14 
15 from pyparsing import Literal, Optional, ZeroOrMore # type: ignore
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: Union[Template, Any],
52  name: str,
53  return_type: ReturnType,
54  args: ArgumentList,
55  is_const: str,
56  parent: Union["Class", Any] = ''):
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 to_cpp(self) -> str:
66  """Generate the C++ code for wrapping."""
67  return self.name
68 
69  def __repr__(self) -> str:
70  return "Method: {} {} {}({}){}".format(
71  self.template,
72  self.return_type,
73  self.name,
74  self.args,
75  self.is_const,
76  )
77 
78 
80  """
81  Rule to parse all the static methods in a class.
82 
83  E.g.
84  ```
85  class Hello {
86  static void changeGreeting();
87  };
88  ```
89  """
90  rule = (
91  Optional(Template.rule("template")) #
92  + STATIC #
93  + ReturnType.rule("return_type") #
94  + IDENT("name") #
95  + LPAREN #
96  + ArgumentList.rule("args_list") #
97  + RPAREN #
98  + SEMI_COLON # BR
99  ).setParseAction(
100  lambda t: StaticMethod(t.name, t.return_type, t.args_list, t.template))
101 
102  def __init__(self,
103  name: str,
104  return_type: ReturnType,
105  args: ArgumentList,
106  template: Union[Template, Any] = None,
107  parent: Union["Class", Any] = ''):
108  self.name = name
109  self.return_type = return_type
110  self.args = args
111  self.template = template
112 
113  self.parent = parent
114 
115  def __repr__(self) -> str:
116  return "static {} {}{}".format(self.return_type, self.name, self.args)
117 
118  def to_cpp(self) -> str:
119  """Generate the C++ code for wrapping."""
120  return self.name
121 
122 
124  """
125  Rule to parse the class constructor.
126  Can have 0 or more arguments.
127  """
128  rule = (
129  Optional(Template.rule("template")) #
130  + IDENT("name") #
131  + LPAREN #
132  + ArgumentList.rule("args_list") #
133  + RPAREN #
134  + SEMI_COLON # BR
135  ).setParseAction(lambda t: Constructor(t.name, t.args_list, t.template))
136 
137  def __init__(self,
138  name: str,
139  args: ArgumentList,
140  template: Union[Template, Any],
141  parent: Union["Class", Any] = ''):
142  self.name = name
143  self.args = args
144  self.template = template
145 
146  self.parent = parent
147 
148  def __repr__(self) -> str:
149  return "Constructor: {}{}".format(self.name, self.args)
150 
151 
152 class Operator:
153  """
154  Rule for parsing operator overloads.
155 
156  E.g.
157  ```
158  class Overload {
159  Vector2 operator+(const Vector2 &v) const;
160  };
161  """
162  rule = (
163  ReturnType.rule("return_type") #
164  + Literal("operator")("name") #
165  + OPERATOR("operator") #
166  + LPAREN #
167  + ArgumentList.rule("args_list") #
168  + RPAREN #
169  + CONST("is_const") #
170  + SEMI_COLON # BR
171  ).setParseAction(lambda t: Operator(t.name, t.operator, t.return_type, t.
172  args_list, t.is_const))
173 
174  def __init__(self,
175  name: str,
176  operator: str,
177  return_type: ReturnType,
178  args: ArgumentList,
179  is_const: str,
180  parent: Union["Class", Any] = ''):
181  self.name = name
182  self.operator = operator
183  self.return_type = return_type
184  self.args = args
185  self.is_const = is_const
186  self.is_unary = len(args) == 0
187 
188  self.parent = parent
189 
190  # Check for valid unary operators
191  if self.is_unary and self.operator not in ('+', '-'):
192  raise ValueError("Invalid unary operator {} used for {}".format(
193  self.operator, self))
194 
195  # Check that number of arguments are either 0 or 1
196  assert 0 <= len(args) < 2, \
197  "Operator overload should be at most 1 argument, " \
198  "{} arguments provided".format(len(args))
199 
200  # Check to ensure arg and return type are the same.
201  if len(args) == 1 and self.operator not in ("()", "[]"):
202  assert args.list()[0].ctype.typename.name == return_type.type1.typename.name, \
203  "Mixed type overloading not supported. Both arg and return type must be the same."
204 
205  def __repr__(self) -> str:
206  return "Operator: {}{}{}({}) {}".format(
207  self.return_type,
208  self.name,
209  self.operator,
210  self.args,
211  self.is_const,
212  )
213 
214 
215 class Class:
216  """
217  Rule to parse a class defined in the interface file.
218 
219  E.g.
220  ```
221  class Hello {
222  ...
223  };
224  ```
225  """
226  class Members:
227  """
228  Rule for all the members within a class.
229  """
230  rule = ZeroOrMore(Constructor.rule #
231  ^ Method.rule #
232  ^ StaticMethod.rule #
233  ^ Variable.rule #
234  ^ Operator.rule #
235  ^ Enum.rule #
236  ).setParseAction(lambda t: Class.Members(t.asList()))
237 
238  def __init__(self,
239  members: List[Union[Constructor, Method, StaticMethod,
240  Variable, Operator]]):
241  self.ctors = []
242  self.methods = []
243  self.static_methods = []
244  self.properties = []
245  self.operators = []
246  self.enums: List[Enum] = []
247  for m in members:
248  if isinstance(m, Constructor):
249  self.ctors.append(m)
250  elif isinstance(m, Method):
251  self.methods.append(m)
252  elif isinstance(m, StaticMethod):
253  self.static_methods.append(m)
254  elif isinstance(m, Variable):
255  self.properties.append(m)
256  elif isinstance(m, Operator):
257  self.operators.append(m)
258  elif isinstance(m, Enum):
259  self.enums.append(m)
260 
261  _parent = COLON + (TemplatedType.rule ^ Typename.rule)("parent_class")
262  rule = (
263  Optional(Template.rule("template")) #
264  + Optional(VIRTUAL("is_virtual")) #
265  + CLASS #
266  + IDENT("name") #
267  + Optional(_parent) #
268  + LBRACE #
269  + Members.rule("members") #
270  + RBRACE #
271  + SEMI_COLON # BR
272  ).setParseAction(lambda t: Class(
273  t.template, t.is_virtual, t.name, t.parent_class, t.members.ctors, t.
274  members.methods, t.members.static_methods, t.members.properties, t.
275  members.operators, t.members.enums))
276 
277  def __init__(
278  self,
279  template: Union[Template, None],
280  is_virtual: str,
281  name: str,
282  parent_class: list,
283  ctors: List[Constructor],
284  methods: List[Method],
285  static_methods: List[StaticMethod],
286  properties: List[Variable],
287  operators: List[Operator],
288  enums: List[Enum],
289  parent: Any = '',
290  ):
291  self.template = template
292  self.is_virtual = is_virtual
293  self.name = name
294  if parent_class:
295  # If it is in an iterable, extract the parent class.
296  if isinstance(parent_class, Iterable):
297  parent_class = parent_class[0] # type: ignore
298 
299  # If the base class is a TemplatedType,
300  # we want the instantiated Typename
301  if isinstance(parent_class, TemplatedType):
302  pass # Note: this must get handled in InstantiatedClass
303 
304  self.parent_class = parent_class
305  else:
306  self.parent_class = '' # type: ignore
307 
308  self.ctors = ctors
309  self.methods = methods
310  self.static_methods = static_methods
311  self.properties = properties
312  self.operators = operators
313  self.enums = enums
314 
315  self.parent = parent
316 
317  # Make sure ctors' names and class name are the same.
318  for ctor in self.ctors:
319  if ctor.name != self.name:
320  raise ValueError("Error in constructor name! {} != {}".format(
321  ctor.name, self.name))
322 
323  for ctor in self.ctors:
324  ctor.parent = self
325  for method in self.methods:
326  method.parent = self
327  for static_method in self.static_methods:
328  static_method.parent = self
329  for _property in self.properties:
330  _property.parent = self
331 
332  def namespaces(self) -> list:
333  """Get the namespaces which this class is nested under as a list."""
334  return collect_namespaces(self)
335 
336  def __repr__(self):
337  return "Class: {self.name}".format(self=self)
bool isinstance(handle obj)
Definition: pytypes.h:700
std::string format(const std::string &str, const std::vector< std::string > &find, const std::vector< std::string > &replace)
size_t len(handle h)
Get the length of a Python object.
Definition: pytypes.h:2244


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:34:01