Minor fixes in LifxLightBulb driver (not fully tested yet)
[iot2.git] / iotjava / iotpolicy / tree / ParseTreeHandler.java
1 package iotpolicy.tree;
2
3 import java_cup.runtime.ComplexSymbolFactory;
4 import java_cup.runtime.ScannerBuffer;
5 import java.io.*;
6 import iotpolicy.tree.ParseNodeVector;
7 import iotpolicy.tree.ParseNode;
8
9 import java.util.List;
10 import java.util.ArrayList;
11
12 /** Class ParseTreeHandler handles the parse tree generated by the 
13  *  parser (and lexer) from the policy file. 
14  *  This class accepts the AST in the form of ParseNode and
15  *  ParseNodeVector class objects.
16  *  It gives interfaces to extract the 4 types of policy file:
17  *  1) Interface and capabilities definition
18  *  2) Generated interface list ("requires" statements)
19  *  3) Enum declaration
20  *  4) Struct declaration
21  *
22  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
23  * @version     1.0
24  * @since       2016-09-20
25  */
26 public final class ParseTreeHandler {
27
28         /**
29          * Class properties
30          */
31         private ParseNode pnPol;                // Policy: interface and capabilities
32         private ParseNode pnReq;                // Policy: "requires" statements
33         private InterfaceDecl intDecl;
34         private CapabilityDecl capDecl;
35         private RequiresDecl reqDecl;
36         private EnumDecl enumDecl;
37         private StructDecl structDecl;
38
39
40         /**
41          * Class constructors
42          */
43         public ParseTreeHandler() {
44
45                 pnPol = null;
46                 pnReq = null;
47                 intDecl = new InterfaceDecl();
48                 capDecl = new CapabilityDecl();
49                 reqDecl = new RequiresDecl();
50                 enumDecl = new EnumDecl();
51                 structDecl = new StructDecl();
52         }
53
54
55         public ParseTreeHandler(String _intFace, ParseNode _pnPol, ParseNode _pnReq) {
56
57                 pnPol = _pnPol;
58                 pnReq = _pnReq;
59                 intDecl = new InterfaceDecl(_intFace);
60                 capDecl = new CapabilityDecl(_intFace);
61                 reqDecl = new RequiresDecl(_intFace);
62                 enumDecl = new EnumDecl();
63                 structDecl = new StructDecl();
64         }
65
66
67         /**
68          * processInterfaceDecl() processes interface declaration part
69          */
70         public void processInterfaceDecl() {
71
72                 ParseNodeVector pnv = pnPol.getChildren();
73                 ParseNode pnRoot = pnv.elementAt(0);
74                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
75                 if (pnvGen2.size() == 0) {
76                         throw new Error("ParseTreeHandler: Interface declaration is missing! Please check your policy file...");
77                 }
78                 ParseNode pnGen2 = pnvGen2.elementAt(1);
79                 ParseNodeVector pnvGen3 = pnGen2.getChildren();
80                 for(int i = 0; i < pnvGen3.size(); i++) { // Loop on methods
81
82                         ParseNode pnGen3 = pnvGen3.elementAt(i);
83                         ParseNodeVector pnvGen4 = pnGen3.getChildren();
84                         // Method type, identifier, and param node
85                         ParseNode pnGen4_type = pnvGen4.elementAt(0);
86                         ParseNode pnGen4_ident  = pnvGen4.elementAt(1);
87                         ParseNode pnGen4_params  = pnvGen4.elementAt(2);
88                         ParseNodeVector pnvGen5 = pnGen4_params.getChildren();
89                         // First loop - create a key without spaces, e.g. MethodA(intA,SpeakerB)
90                         String methodKey = pnGen4_ident.getLiteral().toString() + "(";
91                         List<String> paramTypes = new ArrayList<String>();
92                         List<String> params = new ArrayList<String>();
93                         for(int j = 0; j < pnvGen5.size(); j++) { // Loop on params
94
95                                 ParseNode pnGen5 = pnvGen5.elementAt(j);
96                                 ParseNodeVector pnvGen6 = pnGen5.getChildren();
97                                 // Param type and identifier
98                                 ParseNode pnGen6_type = pnvGen6.elementAt(0);
99                                 ParseNode pnGen6_ident = pnvGen6.elementAt(1);
100                                 methodKey = methodKey + pnGen6_type.getLiteral().toString();
101                                 methodKey = methodKey + pnGen6_ident.getLiteral().toString();
102                                 // Keep the parameters temporarily
103                                 paramTypes.add(pnGen6_type.getLiteral().toString());
104                                 params.add(pnGen6_ident.getLiteral().toString());
105                                 // Don't add comma for the last parameter
106                                 if (j != pnvGen5.size() - 1) {
107                                         methodKey = methodKey + ",";
108                                 }
109                         }
110                         methodKey = methodKey + ")";
111                         // Add a new method (signature key, identifier, and type)
112                         intDecl.addNewMethod(methodKey, pnGen4_ident.getLiteral().toString(), 
113                                 pnGen4_type.getLiteral().toString());
114                         // Second loop - add the method parameters
115                         for(int j = 0; j < params.size(); j++) {
116                                 intDecl.addMethodParam(methodKey, params.get(j), paramTypes.get(j));
117                         }
118                 }
119         }
120
121
122         /**
123          * processCapabilityDecl() processes capability declaration part
124          */
125         public void processCapabilityDecl() {
126
127                 // Get the root - capability list (element 1)
128                 ParseNodeVector pnv = pnPol.getChildren();
129                 ParseNode pnRoot = pnv.elementAt(0);
130                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
131                 // Get the third child of root for "capab_list"
132                 ParseNode pnGen2 = pnvGen2.elementAt(2);
133                 ParseNodeVector pnvGen3 = pnGen2.getChildren();
134                 if (pnvGen3.size() == 0) {
135                         throw new Error("ParseTreeHandler: Capability declaration is missing! Please check your policy file...");
136                 }
137                 // Iterate over the list of capabilities
138                 for(int i = 0; i < pnvGen3.size(); i++) {
139
140                         ParseNode pnGen3 = pnvGen3.elementAt(i);
141                         // Get the next level child for capabilities
142                         ParseNodeVector pnvGen4 = pnGen3.getChildren();
143                         // Get the capability name, e.g. ImageCapture for Camera.ImageCapture
144                         ParseNode pnGen4_capab = pnvGen4.elementAt(0);
145                         // Add new capability
146                         capDecl.addNewCapability(pnGen4_capab.getLiteral().toString());
147                         // Get the capability contents, i.e. descriptions and methods
148                         ParseNode pnGen4_capab_cont = pnvGen4.elementAt(1);
149                         ParseNodeVector pnvGen5 = pnGen4_capab_cont.getChildren();
150                         // Iterate over the list of capability contents
151                         for(int j = 0; j < pnvGen5.size(); j++) {
152
153                                 ParseNode pnGen5 = pnvGen5.elementAt(j);
154                                 ParseNodeVector pnvGen6 = pnGen5.getChildren();
155                                 ParseNode pnGen6 = pnvGen6.elementAt(0);
156                                 // Check the label and separate between description (capab_desc)
157                                 // and method name (capab_ident)
158                                 String label = pnGen6.getLabel().toString();
159                                 if (label.equals("capab_desc")) {
160                                         capDecl.addNewDescription(pnGen4_capab.getLiteral().toString(),
161                                                 pnGen6.getLiteral().toString());
162                                 } else if (label.equals("capab_meth")) {
163                                         capDecl.addNewMethod(pnGen4_capab.getLiteral().toString(),
164                                                 pnGen6.getLiteral().toString().replaceAll("\\s+",""));
165                                 } else
166                                         throw new Error("ParseTreeHandler: Unknown label '" + label + "' while operating on parse tree!");
167
168                         }
169                 }
170         }
171
172
173         /**
174          * processRequiresDecl() processes "requires" declaration part
175          */
176         public void processRequiresDecl() {
177
178                 // Get the root - requires list (element 2)
179                 ParseNodeVector pnv = pnReq.getChildren();
180                 ParseNode pnRoot = pnv.elementAt(0);
181                 // Get the second child of root for "reqlist"
182                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
183                 if (pnvGen2.size() == 0) {
184                         throw new Error("ParseTreeHandler: 'Requires' declaration is missing! Please check your policy file...");
185                 }
186                 // Iterate over the list of requires statements
187                 for(int i = 0; i < pnvGen2.size(); i++) {
188
189                         ParseNode pnGen2 = pnvGen2.elementAt(i);
190                         ParseNodeVector pnvGen3 = pnGen2.getChildren();
191                         // Get the new interface that we want to generate
192                         ParseNode pnGen3_intface = pnvGen3.elementAt(2);
193                         reqDecl.addNewIntface(pnGen3_intface.getLiteral().toString());
194                         // Get capability list at element 1
195                         ParseNode pnGen3_capab_list = pnvGen3.elementAt(1);
196                         ParseNodeVector pnvGen4 = pnGen3_capab_list.getChildren();
197                         // Browse through capabilities
198                         for (int j = 0; j < pnvGen4.size(); j++) {
199                                 ParseNode pnGen4 = pnvGen4.elementAt(j);
200                                 reqDecl.addNewCapability(pnGen3_intface.getLiteral().toString(),
201                                         pnGen4.getLiteral().toString());
202                         }
203                 }
204         }
205
206
207         /**
208          * processEnumDecl() processes "enum" declaration part
209          */
210         public void processEnumDecl() {
211
212                 ParseNodeVector pnv = pnPol.getChildren();
213                 ParseNode pnRoot = pnv.elementAt(0);
214                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
215                 // Get the third child of root for "enum"
216                 ParseNode pnGen2 = pnvGen2.elementAt(3);
217                 ParseNodeVector pnvGen3 = pnGen2.getChildren();
218                 // Iterate over a list of enum declaration - can be empty too
219                 for(int i = 0; i < pnvGen3.size(); i++) {
220
221                         ParseNode pnGen4 = pnvGen3.elementAt(i);
222                         ParseNodeVector pnvGen5 = pnGen4.getChildren();
223                         // Get the type of the enum
224                         ParseNode pnGen5_enum_ident = pnvGen5.elementAt(0);
225                         ParseNode pnGen5_enum_list = pnvGen5.elementAt(1);
226                         ParseNodeVector pnvGen6_members = pnGen5_enum_list.getChildren();
227                         // Browse through enum declarations
228                         for (int j = 0; j < pnvGen6_members.size(); j++) {
229                                 ParseNode pnGen6 = pnvGen6_members.elementAt(j);
230                                 ParseNodeVector pnvGen7 = pnGen6.getChildren();
231                                 ParseNode pnGen7 = pnvGen7.elementAt(0);
232                                 enumDecl.addNewMember(pnGen5_enum_ident.getLiteral().toString(),
233                                         pnGen7.getLiteral().toString());
234                         }
235                 }
236         }
237
238
239         /**
240          * processStructDecl() processes "struct" declaration part
241          */
242         public void processStructDecl() {
243
244                 ParseNodeVector pnv = pnPol.getChildren();
245                 ParseNode pnRoot = pnv.elementAt(0);
246                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
247                 // Get the fourth child of root for "struct"
248                 ParseNode pnGen2 = pnvGen2.elementAt(4);
249                 ParseNodeVector pnvGen3 = pnGen2.getChildren();
250                 // Iterate over a list of struct declaration - can be empty too
251                 for(int i = 0; i < pnvGen3.size(); i++) {
252
253                         ParseNode pnGen4 = pnvGen3.elementAt(i);
254                         ParseNodeVector pnvGen5 = pnGen4.getChildren();
255                         // Get the type of the enum
256                         ParseNode pnGen5_enum_ident = pnvGen5.elementAt(0);
257                         ParseNode pnGen5_enum_list = pnvGen5.elementAt(1);
258                         ParseNodeVector pnvGen6_members = pnGen5_enum_list.getChildren();
259                         // Browse through enum declarations
260                         for (int j = 0; j < pnvGen6_members.size(); j++) {
261                                 ParseNode pnGen6 = pnvGen6_members.elementAt(j);
262                                 ParseNodeVector pnvGen7 = pnGen6.getChildren();
263                                 ParseNode pnGen7_type = pnvGen7.elementAt(0);
264                                 ParseNode pnGen7_ident = pnvGen7.elementAt(1);
265                                 structDecl.addNewMember(pnGen5_enum_ident.getLiteral().toString(),
266                                         pnGen7_type.getLiteral().toString(), pnGen7_ident.getLiteral().toString());
267                         }
268                 }
269         }
270
271
272         /**
273          * getInterfaceDecl() returns InterfaceDecl object
274          */
275         public InterfaceDecl getInterfaceDecl() {
276
277                 return intDecl;
278         }
279
280
281         /**
282          * getCapabilityDecl() returns CapabilityDecl object
283          */
284         public CapabilityDecl getCapabilityDecl() {
285
286                 return capDecl;
287         }
288
289
290         /**
291          * getRequiresDecl() returns RequiresDecl object
292          */
293         public RequiresDecl getRequiresDecl() {
294
295                 return reqDecl;
296         }
297
298
299         /**
300          * getEnumDecl() returns EnumDecl object
301          */
302         public EnumDecl getEnumDecl() {
303
304                 return enumDecl;
305         }
306
307
308         /**
309          * getStructDecl() returns StructDecl object
310          */
311         public StructDecl getStructDecl() {
312
313                 return structDecl;
314         }
315
316
317         /**
318          * getOrigIntface() returns the original interface in policy, e.g. Camera
319          * <p>
320          * The ParseNode object should be the one returned from <Parser>.parse().value
321          */
322         public static String getOrigIntface(ParseNode pn) {
323
324                 // Get the root: just keyword "interface"
325                 ParseNodeVector pnv = pn.getChildren();
326                 ParseNode pnRoot = pnv.elementAt(0);
327                 // Get the child: intface_ident = original interface identifier, e.g. Camera
328                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
329                 if (pnvGen2.size() == 0) {
330                         throw new Error("ParseTreeHandler: Interface declaration is missing! Please check your policy file...");
331                 }
332                 // Get "intface_def"
333                 ParseNode pnGen2 = pnvGen2.elementAt(0);
334                 // Confirm that this is "intface_ident"
335                 if (pnGen2.getLabel().equals("intface_ident")) {
336                         if (pnGen2.getLiteral() != null) {
337                                 return pnGen2.getLiteral().toString();
338                         } else
339                                 throw new Error("ParseTreeHandler: No interface name found! Please fix policy file!");
340                 } else
341                         throw new Error("ParseTreeHandler: Label 'intface_ident' is not found! Instead, '" + pnGen2.getLabel() + "' was found...");
342         }
343 }