KLL Compiler
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

context.py 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #!/usr/bin/env python3
  2. '''
  3. KLL Context Definitions
  4. * Generic (auto-detected)
  5. * Configuration
  6. * BaseMap
  7. * DefaultMap
  8. * PartialMap
  9. '''
  10. # Copyright (C) 2016 by Jacob Alexander
  11. #
  12. # This file is free software: you can redistribute it and/or modify
  13. # it under the terms of the GNU General Public License as published by
  14. # the Free Software Foundation, either version 3 of the License, or
  15. # (at your option) any later version.
  16. #
  17. # This file is distributed in the hope that it will be useful,
  18. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. # GNU General Public License for more details.
  21. #
  22. # You should have received a copy of the GNU General Public License
  23. # along with this file. If not, see <http://www.gnu.org/licenses/>.
  24. ### Imports ###
  25. import copy
  26. import os
  27. import common.organization as organization
  28. ### Decorators ###
  29. ## Print Decorator Variables
  30. ERROR = '\033[5;1;31mERROR\033[0m:'
  31. WARNING = '\033[5;1;33mWARNING\033[0m:'
  32. ### Classes ###
  33. class Context:
  34. '''
  35. Base KLL Context Class
  36. '''
  37. def __init__( self ):
  38. '''
  39. Context initialization
  40. '''
  41. # Each context may have one or more included kll files
  42. # And each of these files will have at least 1 Context
  43. self.kll_files = []
  44. # File data assigned to each context
  45. # This info is populated during the PreprocessorStage
  46. self.lines = []
  47. self.data = ""
  48. self.parent = None
  49. # Tokenized data sets
  50. self.classification_token_data = []
  51. self.expressions = []
  52. # Organized Expression Datastructure
  53. self.organization = organization.Organization()
  54. def __repr__( self ):
  55. # Build list of all the info
  56. return "(kll_files={0}, lines={1}, data='''{2}''')".format(
  57. self.kll_files,
  58. self.lines,
  59. self.data,
  60. )
  61. def initial_context( self, lines, data, parent ):
  62. '''
  63. Used in the PreprocessorStage to update the initial line and kll file data
  64. @param lines: Data split per line
  65. @param data: Entire context in a single string
  66. @param parent: Parent node, always a KLLFile
  67. '''
  68. self.lines = lines
  69. self.data = data
  70. self.parent = parent
  71. def query( self, kll_expression, kll_type ):
  72. '''
  73. Query
  74. Returns a dictionary of the specified property.
  75. Most queries should use this.
  76. See organization.py:Organization for property_type details.
  77. @param kll_expression: String name of expression type
  78. @param kll_type: String name of the expression sub-type
  79. @return: context_name: (dictionary)
  80. '''
  81. return self.organization.data_mapping[ kll_expression ][ kll_type ]
  82. class GenericContext( Context ):
  83. '''
  84. Generic KLL Context Class
  85. '''
  86. class ConfigurationContext( Context ):
  87. '''
  88. Configuration KLL Context Class
  89. '''
  90. class BaseMapContext( Context ):
  91. '''
  92. Base Map KLL Context Class
  93. '''
  94. class DefaultMapContext( Context ):
  95. '''
  96. Default Map KLL Context Class
  97. '''
  98. class PartialMapContext( Context ):
  99. '''
  100. Partial Map KLL Context Class
  101. '''
  102. def __init__( self, layer ):
  103. '''
  104. Partial Map Layer Context Initialization
  105. @param: Layer associated with Partial Map
  106. '''
  107. super().__init__()
  108. self.layer = layer
  109. class MergeContext( Context ):
  110. '''
  111. Container class for a merged Context
  112. Has references to the original contexts merged in
  113. '''
  114. def __init__( self, base_context ):
  115. '''
  116. Initialize the MergeContext with the base context
  117. Another MergeContext can be used as the base_context
  118. @param base_context: Context used to seed the MergeContext
  119. '''
  120. super().__init__()
  121. # List of context, in the order of merging, starting from the base
  122. self.contexts = [ base_context ]
  123. # Copy the base context Organization into the MergeContext
  124. self.organization = copy.copy( base_context.organization )
  125. # Set the layer if the base is a PartialMapContext
  126. if base_context.__class__.__name__ == 'PartialMapContext':
  127. self.layer = base_context.layer
  128. def merge( self, merge_in, debug ):
  129. '''
  130. Merge in context
  131. Another MergeContext can be merged into a MergeContext
  132. @param merge_in: Context to merge in to this one
  133. @param debug: Enable debug out
  134. '''
  135. # Append to context list
  136. self.contexts.append( merge_in )
  137. # Merge context
  138. self.organization.merge(
  139. merge_in.organization,
  140. debug
  141. )
  142. # Set the layer if the base is a PartialMapContext
  143. if merge_in.__class__.__name__ == 'PartialMapContext':
  144. self.layer = merge_in.layer
  145. def reduction( self ):
  146. '''
  147. Simplifies datastructure
  148. NOTE: This will remove data, therefore, context is lost
  149. '''
  150. self.organization.reduction()
  151. def paths( self ):
  152. '''
  153. Returns list of file paths used to generate this context
  154. '''
  155. file_paths = []
  156. for kll_context in self.contexts:
  157. # If context is a MergeContext then we have to recursively search
  158. if kll_context.__class__.__name__ is 'MergeContext':
  159. file_paths.extend( kll_context.paths() )
  160. else:
  161. file_paths.append( kll_context.parent.path )
  162. return file_paths
  163. def files( self ):
  164. '''
  165. Short form list of file paths used to generate this context
  166. '''
  167. file_paths = []
  168. for file_path in self.paths():
  169. file_paths.append( os.path.basename( file_path ) )
  170. return file_paths
  171. def __repr__( self ):
  172. return "(kll_files={0}, organization={1})".format(
  173. self.files(),
  174. self.organization,
  175. )
  176. def query_contexts( self, kll_expression, kll_type ):
  177. '''
  178. Context Query
  179. Returns a list of tuples (dictionary, kll_context) doing a deep search to the context leaf nodes.
  180. This results in pre-merge data and is useful for querying information about files used during compilation.
  181. See organization.py:Organization for property_type details.
  182. @param kll_expression: String name of expression type
  183. @param kll_type: String name of the expression sub-type
  184. @return: context_name: (dictionary, kll_context)
  185. '''
  186. # Build list of leaf contexts
  187. leaf_contexts = []
  188. for kll_context in self.contexts:
  189. # Recursively search if necessary
  190. if kll_context.__class__.__name__ == 'MergeContext':
  191. leaf_contexts.extend( kll_context.query_contexts( kll_expression, kll_type ) )
  192. else:
  193. leaf_contexts.append( ( kll_context.query( kll_expression, kll_type ), kll_context ) )
  194. return leaf_contexts