comparison Resources/CodeGeneration/stonegentool.py @ 473:628941d63b8c bgo-commands-codegen

Ongoing work. Parsing tests work
author bgo-osimis
date Wed, 13 Feb 2019 12:07:00 +0100
parents 3db3289e1c25
children 38997ceb9bc6
comparison
equal deleted inserted replaced
472:3db3289e1c25 473:628941d63b8c
1 from typing import List,Dict,Set
2 import sys
3 import json 1 import json
4 import re 2 import re
3 import sys
4 from typing import Dict, List, Set
5
5 6
6 """ 7 """
7 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7
8 12345678901234567890123456789012345678901234567890123456789012345678901234567890 9 12345678901234567890123456789012345678901234567890123456789012345678901234567890
9 """ 10 """
10 11
11 def LoadSchema(file_path : str): 12 import json
12 with open(file_path, 'r') as fp: 13 import re
13 obj = json.load(fp) 14
14 return obj 15 """A set of utilities to perform JSON operation"""
16
17 class JsonHelpers:
18 @staticmethod
19 def removeCommentsFromJsonContent(string):
20 """
21 remove comments from a JSON file
22
23 Comments are not allowed in JSON but, i.e., Orthanc configuration files contains C++ like comments that we need to remove before python can parse the file
24 """
25 string = re.sub(re.compile("/\*.*?\*/", re.DOTALL), "",
26 string) # remove all occurance streamed comments (/*COMMENT */) from string
27 string = re.sub(re.compile("//.*?\n"), "",
28 string) # remove all occurance singleline comments (//COMMENT\n ) from string
29 return string
30
31 @staticmethod
32 def loadJsonWithComments(path):
33 """
34 reads a JSON file that may contain C++ like comments
35 """
36 with open(path, 'r') as fp:
37 fileContent = fp.read()
38 fileContent = JsonHelpers.removeCommentsFromJsonContent(fileContent)
39 return json.loads(fileContent)
40
41
42 def LoadSchema(filePath : str):
43 return JsonHelpers.loadJsonWithComments(filePath)
15 44
16 # class Type: 45 # class Type:
17 # def __init__(self, canonicalTypeName:str, kind:str): 46 # def __init__(self, canonicalTypeName:str, kind:str):
18 # allowedTypeKinds = ["primitive","enum","struct","collection"] 47 # allowedTypeKinds = ["primitive","enum","struct","collection"]
19 # """dependent type is the list of canonical types this type depends on. 48 # """dependent type is the list of canonical types this type depends on.
61 # self.rootName : str = root_prefix 90 # self.rootName : str = root_prefix
62 # self.definedTypes : str = defined_types 91 # self.definedTypes : str = defined_types
63 92
64 def CheckTypeSchema(definedType : Dict) -> None: 93 def CheckTypeSchema(definedType : Dict) -> None:
65 allowedDefinedTypeKinds = ["enum","struct"] 94 allowedDefinedTypeKinds = ["enum","struct"]
66 if not definedType.has_key('name'): 95 if not 'name' in definedType:
67 raise Exception("type lacks the 'name' key") 96 raise Exception("type lacks the 'name' key")
68 name = definedType['name'] 97 name = definedType['name']
69 if not definedType.has_key('kind'): 98 if not 'kind' in definedType:
70 raise Exception(f"type {name} lacks the 'kind' key") 99 raise Exception(f"type {name} lacks the 'kind' key")
71 kind = definedType['kind'] 100 kind = definedType['kind']
72 if not (kind in allowedDefinedTypeKinds): 101 if not (kind in allowedDefinedTypeKinds):
73 raise Exception(f"type {name} : kind {kind} is not allowed. " + 102 raise Exception(f"type {name} : kind {kind} is not allowed. " +
74 f"It must be one of {allowedDefinedTypeKinds}") 103 f"It must be one of {allowedDefinedTypeKinds}")
75 104
76 if not definedType.has_key('fields'): 105 if not 'fields' in definedType:
77 raise Exception("type {name} lacks the 'fields' key") 106 raise Exception("type {name} lacks the 'fields' key")
78 107
79 # generic check on all kinds of types 108 # generic check on all kinds of types
80 fields = definedType['fields'] 109 fields = definedType['fields']
81 for field in fields: 110 for field in fields:
82 fieldName = field['name'] 111 fieldName = field['name']
83 if not field.has_key('name'): 112 if not 'name' in field:
84 raise Exception("field in type {name} lacks the 'name' key") 113 raise Exception("field in type {name} lacks the 'name' key")
85 114
86 # fields in struct must have types 115 # fields in struct must have types
87 if kind == 'struct': 116 if kind == 'struct':
88 for field in fields: 117 for field in fields:
89 fieldName = field['name'] 118 fieldName = field['name']
90 if not field.has_key('type'): 119 if not 'type' in field:
91 raise Exception(f"field {fieldName} in type {name} " 120 raise Exception(f"field {fieldName} in type {name} "
92 + "lacks the 'type' key") 121 + "lacks the 'type' key")
93 122
94 def CheckSchemaSchema(schema : Dict) -> None: 123 def CheckSchemaSchema(schema : Dict) -> None:
95 if not schema.has_key('root_name'): 124 if not 'root_name' in schema:
96 raise Exception("schema lacks the 'root_name' key") 125 raise Exception("schema lacks the 'root_name' key")
97 if not schema.has_key('types'): 126 if not 'types' in schema:
98 raise Exception("schema lacks the 'types' key") 127 raise Exception("schema lacks the 'types' key")
99 for definedType in schema['types']: 128 for definedType in schema['types']:
100 CheckTypeSchema(definedType) 129 CheckTypeSchema(definedType)
101 130
102 # def CreateAndCacheTypeObject(allTypes : Dict[str,Type], typeDict : Dict) -> None: 131 # def CreateAndCacheTypeObject(allTypes : Dict[str,Type], typeDict : Dict) -> None:
103 # """This does not set the dependentTypes field""" 132 # """This does not set the dependentTypes field"""
104 # typeName : str = typeDict['name'] 133 # typeName : str = typeDict['name']
105 # if allTypes.has_key(typeName): 134 # if typeName in allTypes:
106 # raise Exception(f'Type {typeName} is defined more than once!') 135 # raise Exception(f'Type {typeName} is defined more than once!')
107 # else: 136 # else:
108 # typeObject = Type(typeName, typeDict['kind']) 137 # typeObject = Type(typeName, typeDict['kind'])
109 # allTypes[typeName] = typeObject 138 # allTypes[typeName] = typeObject
110 139
117 raise Exception(f"Error in the partial template type list {sentence}." 146 raise Exception(f"Error in the partial template type list {sentence}."
118 + " The number of < and > do not match!") 147 + " The number of < and > do not match!")
119 148
120 # the template level we're currently in 149 # the template level we're currently in
121 templateLevel = 0 150 templateLevel = 0
122 for i in len(sentence): 151 for i in range(len(sentence)):
123 if (sentence[i] == ",") and (templateLevel == 0): 152 if (sentence[i] == ",") and (templateLevel == 0):
124 return (sentence[0:i],sentence[i+1:]) 153 return (sentence[0:i],sentence[i+1:])
125 elif (sentence[i] == "<"): 154 elif (sentence[i] == "<"):
126 templateLevel += 1 155 templateLevel += 1
127 elif (sentence[i] == ">"): 156 elif (sentence[i] == ">"):
142 tokenList = [] 171 tokenList = []
143 restOfString = typeName 172 restOfString = typeName
144 while stillStuffToEat: 173 while stillStuffToEat:
145 firstToken,restOfString = EatToken(restOfString) 174 firstToken,restOfString = EatToken(restOfString)
146 tokenList.append(firstToken) 175 tokenList.append(firstToken)
176 if restOfString == "":
177 stillStuffToEat = False
147 return tokenList 178 return tokenList
148 179
149 templateRegex = \ 180 templateRegex = \
150 re.compile(r"([a-zA-Z0-9_]*[a-zA-Z0-9_]*)<([a-zA-Z0-9_,:<>]+)>") 181 re.compile(r"([a-zA-Z0-9_]*[a-zA-Z0-9_]*)<([a-zA-Z0-9_,:<>]+)>")
151 182
165 # we need to split with the commas that are outside of the defined types 196 # we need to split with the commas that are outside of the defined types
166 # simply splitting at commas won't work 197 # simply splitting at commas won't work
167 listOfDependentTypes = SplitListOfTypes(matches.group(2)) 198 listOfDependentTypes = SplitListOfTypes(matches.group(2))
168 return (True,matches.group(1),listOfDependentTypes) 199 return (True,matches.group(1),listOfDependentTypes)
169 200
170
171 # def GetPrimitiveType(typeName : str) -> Type: 201 # def GetPrimitiveType(typeName : str) -> Type:
172 # if allTypes.has_key(typeName): 202 # if typeName in allTypes:
173 # return allTypes[typeName] 203 # return allTypes[typeName]
174 # else: 204 # else:
175 # primitiveTypes = ['int32', 'float32', 'float64', 'string'] 205 # primitiveTypes = ['int32', 'float32', 'float64', 'string']
176 # if not (typeName in primitiveTypes): 206 # if not (typeName in primitiveTypes):
177 # raise Exception(f"Type {typeName} is unknown.") 207 # raise Exception(f"Type {typeName} is unknown.")
200 # childAncestors = ancestors.copy() NO TEMPLATE ANCESTOR!!! 230 # childAncestors = ancestors.copy() NO TEMPLATE ANCESTOR!!!
201 # childAncestors.append(typeName) 231 # childAncestors.append(typeName)
202 ProcessTypeTree(ancestors, genOrderQueue, 232 ProcessTypeTree(ancestors, genOrderQueue,
203 structTypes, dependentTypeName) 233 structTypes, dependentTypeName)
204 else: 234 else:
205 if structTypes.has_key(typeName): 235 if typeName in structTypes:
206 ProcessStructType_DepthFirstRecursive(genOrderQueue, structTypes, 236 ProcessStructType_DepthFirstRecursive(genOrderQueue, structTypes,
207 structTypes[typeName]) 237 structTypes[typeName])
208 238
209 def ProcessStructType_DepthFirstRecursive( 239 def ProcessStructType_DepthFirstRecursive(
210 genOrderQueue : List[str], structTypes : Dict[str,Dict] 240 genOrderQueue : List[str], structTypes : Dict[str,Dict]