PageRenderTime 139ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/basil/lang/asdl/AST.py

https://github.com/tylergreen/mython
Python | 116 lines | 67 code | 12 blank | 37 comment | 19 complexity | f8dda2ec3c109efc2a8b2ab71f8b9add MD5 | raw file
  1. #! /usr/bin/env python
  2. # ______________________________________________________________________
  3. """Module AST
  4. Defines a set of base classes for ASDL abstract syntax data types.
  5. Jonathan Riehl"""
  6. # ______________________________________________________________________
  7. # Class definition(s)
  8. class ASTError (Exception):
  9. """Base class for AST related exceptions."""
  10. # ______________________________________________________________________
  11. class ASTFieldMappingError (ASTError):
  12. """Exception class for problems related to instantiating a sequence of
  13. fields."""
  14. # ______________________________________________________________________
  15. class ASTInitError (Exception):
  16. """Exception class for AST instantiation violations."""
  17. # ______________________________________________________________________
  18. class AST (object):
  19. """Abstract base class for reprenting abstract syntax."""
  20. # ____________________________________________________________
  21. __asdl_meta__ = None
  22. # ____________________________________________________________
  23. # XXX This seems like taking the long road to get there. My
  24. # options are to just stick with the original plan (generate
  25. # custom code for each constructor), or refine this.
  26. def map_fields (self, field_list, match_tup, mapping = None):
  27. if mapping is None:
  28. mapping = {}
  29. field_len = len(field_list)
  30. match_len = len(match_tup)
  31. if field_len == 0:
  32. if match_len > 0:
  33. raise ASTFieldMappingError()
  34. else:
  35. field_name, field_type, field_opt, field_seq = field_list[0]
  36. if field_opt == 0:
  37. if len(match_tup) == 0:
  38. raise ASTFieldMappingError()
  39. mapping[field_name] = match_tup[0]
  40. mapping = self.map_fields(field_list[1:], match_tup[1:],
  41. mapping)
  42. else:
  43. try:
  44. mapping = mapping.copy()
  45. mapping[field_name] = match_tup[0]
  46. mapping = self.map_fields(field_list[1:], match_tup[1:],
  47. mapping)
  48. except ASTFieldMappingError:
  49. mapping = self.map_fields(field_list[1:], match_tup,
  50. mapping)
  51. return mapping
  52. # ____________________________________________________________
  53. def get_attributes (self):
  54. ret_val = []
  55. md = self.__asdl_meta__
  56. if "attributes" not in md:
  57. # ASSUMES: super type is either this class or a sum type.
  58. md = super(type(self), self).__asdl_meta__
  59. if "attributes" in md:
  60. ret_val = md["attributes"]
  61. return ret_val
  62. # ____________________________________________________________
  63. def __init__ (self, *args, **kws):
  64. if "types" in self.__asdl_meta__:
  65. raise ASTInitError("Can not directly instantiate a sum type "
  66. "(trying to create a %s)." %
  67. type(self).__name__)
  68. # Come up with a plausible map from fields to arguments.
  69. if "fields" in self.__asdl_meta__:
  70. field_map = self.map_fields(self.__asdl_meta__["fields"], args)
  71. for key, val in field_map.items():
  72. setattr(self, key, val)
  73. # Now handle attributes.
  74. attributes = self.get_attributes()
  75. for key, val in kws.items():
  76. if key not in attributes:
  77. raise ASTInitError("Not an attribute of %s: %s." %
  78. (type(self).__name__, key))
  79. setattr(self, key, val)
  80. # ____________________________________________________________
  81. def __eq__ (self, other):
  82. return ((type(self) == type(other)) and
  83. (self.__dict__ == other.__dict__))
  84. # ____________________________________________________________
  85. def __repr__ (self):
  86. if "fields" in self.__asdl_meta__:
  87. fields = self.__asdl_meta__["fields"]
  88. fields_str = ", ".join([repr(getattr(self,field[0]))
  89. for field in fields])
  90. return "%s(%s)" % (type(self).__name__, fields_str)
  91. # ______________________________________________________________________
  92. # Main (self-test) routine
  93. def main ():
  94. # XXX Would like the property that eval(repr(a)) == a, given the
  95. # definitions of AST.__eq__ and AST.__repr__. Write some tests
  96. # for that.
  97. pass
  98. # ______________________________________________________________________
  99. if __name__ == "__main__":
  100. main()
  101. # ______________________________________________________________________
  102. # End of AST.py