blob: d2bde67634a51a3fed822eb89cef9fe809bbf071 [file] [log] [blame]
Matteo Scandolod2044a42017-08-07 16:08:28 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020017import plyxproto.model as m
Sapan Bhatiadb183c22017-06-23 02:47:42 -070018from plyxproto.helpers import Visitor
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070019import pdb
20import argparse
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020021import plyxproto.parser as plyxproto
Sapan Bhatiaea6ff752017-07-14 01:52:18 -040022from plyxproto.logicparser import FOLParser, FOLLexer
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070023import traceback
24import sys
25import jinja2
26import os
Sapan Bhatiaea6ff752017-07-14 01:52:18 -040027import ply.lex as lex
28import ply.yacc as yacc
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070029
30class Stack(list):
31 def push(self,x):
32 self.append(x)
33
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020034def str_to_dict(s):
35 lst = s.rsplit('.',1)
36 name = lst[-1]
37
38 if len(lst)==2:
39 package = lst[0]
40 else:
41 package = ''
42
43 return {'name': name, 'package': package, 'fqn': s}
44
Sapan Bhatiaea6ff752017-07-14 01:52:18 -040045
Sapan Bhatiaae9645c2017-05-05 15:35:54 +020046def replace_link(obj):
47 try:
48 link = obj.link
49 try:
50 through = link['through']
51 except KeyError:
52 through = None
53
54 try:
55 through_str = through[1:-1]
56 except TypeError:
57 through_str = None
58
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020059 if through_str:
60 through_dict = str_to_dict(through_str)
61 else:
62 through_dict = {}
63
64 model_dict = str_to_dict(link['model'][1:-1])
65
66 ls = m.LinkSpec(obj, m.LinkDefinition(link['link'][1:-1],obj.name,model_dict,link['port'][1:-1],through_dict))
Sapan Bhatiaae9645c2017-05-05 15:35:54 +020067 return ls
68 except:
69 return obj
70
Sapan Bhatiadb183c22017-06-23 02:47:42 -070071class Proto2XProto(Visitor):
Sapan Bhatiaea6ff752017-07-14 01:52:18 -040072 fol_lexer = lex.lex(module=FOLLexer())
Sapan Bhatia6e346832018-01-12 12:08:21 -050073 fol_parser = yacc.yacc(module=FOLParser(), start='goal', debug=0, outputdir='/tmp')
Sapan Bhatiaea6ff752017-07-14 01:52:18 -040074
Matteo Scandolo67654fa2017-06-09 09:33:17 -070075 def __init__(self):
76 super(Proto2XProto, self).__init__()
77
78 self.stack = Stack()
79 self.count_stack = Stack()
80 self.content=""
81 self.offset=0
82 self.statementsChanged=0
83 self.message_options = {}
84 self.options = {}
85 self.current_message_name = None
86
87 self.xproto_message_options = ['bases']
88 self.xproto_field_options = ['model']
89 self.verbose = 0
90 self.first_field = True
91 self.first_method = True
Sapan Bhatiaae9645c2017-05-05 15:35:54 +020092
Sapan Bhatiaea6ff752017-07-14 01:52:18 -040093 def replace_policy(self, obj):
94 if isinstance(obj, m.OptionStatement):
95 rhs = obj.value.value.pval
96 if rhs.startswith('"') and rhs.endswith('"'):
97 rhs = rhs[1:-1]
98
99 if rhs.startswith('policy:'):
Sapan Bhatia5a684762018-01-17 00:56:07 -0500100 str = rhs.split(':',1)[1]
Sapan Bhatiaea6ff752017-07-14 01:52:18 -0400101 val = self.fol_parser.parse(str, lexer = self.fol_lexer)
102
103 return m.PolicyDefinition(obj.name, val)
104
105 return obj
106
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200107 def proto_to_xproto_field(self, obj):
108 try:
109 opts = {}
110 for fd in obj.fieldDirective:
111 k = fd.pval.name.value.pval
112 v = fd.pval.value.value.pval
113 opts[k]=v
114
115 if ('model' in opts and 'link' in opts and 'port' in opts):
116 obj.link = opts
117 pass
118 except KeyError:
119 raise
120
121 def proto_to_xproto_message(self, obj):
122 try:
Sapan Bhatiaea6ff752017-07-14 01:52:18 -0400123 try:
124 bases = self.message_options['bases'].split(',')
125 except KeyError:
126 bases = []
127
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200128 bases = map(lambda x:str_to_dict(x[1:-1]), bases)
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200129 obj.bases = bases
130 except KeyError:
131 raise
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700132
133 def map_field(self, obj, s):
134 if 'model' in s:
135 link = m.LinkDefinition('onetoone','src','name','dst', obj.linespan, obj.lexspan, obj.p)
136 lspec = m.LinkSpec(link, obj)
137 else:
138 lspec = obj
139 return lspec
140
141
142 def get_stack(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700143 return self.stack
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700144
145 def visit_PackageStatement(self, obj):
146 '''Ignore'''
147 return True
148
149 def visit_ImportStatement(self, obj):
150 '''Ignore'''
151 return True
152
153 def visit_OptionStatement(self, obj):
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200154 if (self.current_message_name):
155 k = obj.name.value.pval
156 self.message_options[k] = obj.value.value.pval
157 if (k in self.xproto_message_options):
158 obj.mark_for_deletion = True
159 else:
160 self.options[obj.name.value.pval] = obj.value.value.pval
161
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700162 return True
163
164 def visit_LU(self, obj):
165 return True
166
167 def visit_default(self, obj):
168 return True
169
170 def visit_FieldDirective(self, obj):
171 return True
172
173 def visit_FieldDirective_post(self, obj):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700174 return True
175
176 def visit_FieldType(self, obj):
177 return True
178
179 def visit_LinkDefinition(self, obj):
180 return True
181
182 def visit_FieldDefinition(self, obj):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700183 return True
184
185 def visit_FieldDefinition_post(self, obj):
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200186 self.proto_to_xproto_field(obj)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700187 return True
188
189 def visit_EnumFieldDefinition(self, obj):
190 return True
191
192 def visit_EnumDefinition(self, obj):
193 return True
194
195 def visit_MessageDefinition(self, obj):
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200196 self.current_message_name = obj.name.value.pval
197 self.message_options = {}
198
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700199 return True
200
201 def visit_MessageDefinition_post(self, obj):
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200202 self.proto_to_xproto_message(obj)
203 obj.body = filter(lambda x:not hasattr(x, 'mark_for_deletion'), obj.body)
204 obj.body = map(replace_link, obj.body)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700205
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200206 self.current_message_name = None
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700207 return True
208
209 def visit_MessageExtension(self, obj):
210 return True
211
212 def visit_MethodDefinition(self, obj):
213 return True
214
215 def visit_ServiceDefinition(self, obj):
216 return True
217
218 def visit_ExtensionsDirective(self, obj):
219 return True
220
221 def visit_Literal(self, obj):
222 return True
223
224 def visit_Name(self, obj):
225 return True
226
227 def visit_DotName(self, obj):
228 return True
229
230 def visit_Proto(self, obj):
231 self.count_stack.push(len(obj.body))
232 return True
233
234 def visit_Proto_post(self, obj):
Sapan Bhatiaea6ff752017-07-14 01:52:18 -0400235
236 obj.body = [self.replace_policy(o) for o in obj.body]
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700237 return True
238
239 def visit_LinkSpec(self, obj):
240 return False