blob: f1dc9598d1515710b12df3de5b2878327ad7b59f [file] [log] [blame]
Matteo Scandolod2044a42017-08-07 16:08:28 -07001# Copyright 2017-present Open Networking Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020016import plyxproto.model as m
Sapan Bhatiadb183c22017-06-23 02:47:42 -070017from plyxproto.helpers import Visitor
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070018import pdb
19import argparse
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020020import plyxproto.parser as plyxproto
Sapan Bhatiaea6ff752017-07-14 01:52:18 -040021from plyxproto.logicparser import FOLParser, FOLLexer
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070022import traceback
23import sys
24import jinja2
25import os
Sapan Bhatiaea6ff752017-07-14 01:52:18 -040026import ply.lex as lex
27import ply.yacc as yacc
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070028
Zack Williams045b63d2019-01-22 16:30:57 -070029
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070030class Stack(list):
Zack Williams045b63d2019-01-22 16:30:57 -070031 def push(self, x):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070032 self.append(x)
33
Zack Williams045b63d2019-01-22 16:30:57 -070034
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020035def str_to_dict(s):
Zack Williams045b63d2019-01-22 16:30:57 -070036 lst = s.rsplit(".", 1)
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020037 name = lst[-1]
38
Zack Williams045b63d2019-01-22 16:30:57 -070039 if len(lst) == 2:
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020040 package = lst[0]
41 else:
Zack Williams045b63d2019-01-22 16:30:57 -070042 package = ""
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020043
Zack Williams045b63d2019-01-22 16:30:57 -070044 return {"name": name, "package": package, "fqn": s}
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020045
Sapan Bhatiaea6ff752017-07-14 01:52:18 -040046
Sapan Bhatiaae9645c2017-05-05 15:35:54 +020047def replace_link(obj):
Zack Williams045b63d2019-01-22 16:30:57 -070048 try:
49 link = obj.link
Sapan Bhatiaae9645c2017-05-05 15:35:54 +020050 try:
Zack Williams045b63d2019-01-22 16:30:57 -070051 through = link["through"]
52 except KeyError:
53 through = None
Sapan Bhatiaae9645c2017-05-05 15:35:54 +020054
Zack Williams045b63d2019-01-22 16:30:57 -070055 try:
56 through_str = through[1:-1]
57 except TypeError:
58 through_str = None
Sapan Bhatiaae9645c2017-05-05 15:35:54 +020059
Zack Williams045b63d2019-01-22 16:30:57 -070060 if through_str:
61 through_dict = str_to_dict(through_str)
62 else:
63 through_dict = {}
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020064
Zack Williams045b63d2019-01-22 16:30:57 -070065 model_dict = str_to_dict(link["model"][1:-1])
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020066
Zack Williams045b63d2019-01-22 16:30:57 -070067 ls = m.LinkSpec(
68 obj,
69 m.LinkDefinition(
70 link["link"][1:-1],
71 obj.name,
72 model_dict,
73 link["port"][1:-1],
74 through_dict,
75 ),
76 )
77 return ls
78 except BaseException:
79 return obj
80
Sapan Bhatiaae9645c2017-05-05 15:35:54 +020081
Sapan Bhatiadb183c22017-06-23 02:47:42 -070082class Proto2XProto(Visitor):
Sapan Bhatiaea6ff752017-07-14 01:52:18 -040083 fol_lexer = lex.lex(module=FOLLexer())
Zack Williams045b63d2019-01-22 16:30:57 -070084 fol_parser = yacc.yacc(module=FOLParser(), start="goal", debug=0, outputdir="/tmp")
Sapan Bhatiaea6ff752017-07-14 01:52:18 -040085
Matteo Scandolo67654fa2017-06-09 09:33:17 -070086 def __init__(self):
87 super(Proto2XProto, self).__init__()
88
89 self.stack = Stack()
90 self.count_stack = Stack()
Zack Williams045b63d2019-01-22 16:30:57 -070091 self.content = ""
92 self.offset = 0
93 self.statementsChanged = 0
Matteo Scandolo67654fa2017-06-09 09:33:17 -070094 self.message_options = {}
95 self.options = {}
96 self.current_message_name = None
97
Zack Williams045b63d2019-01-22 16:30:57 -070098 self.xproto_message_options = ["bases"]
99 self.xproto_field_options = ["model"]
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700100 self.verbose = 0
101 self.first_field = True
102 self.first_method = True
Zack Williams045b63d2019-01-22 16:30:57 -0700103
Sapan Bhatiaea6ff752017-07-14 01:52:18 -0400104 def replace_policy(self, obj):
105 if isinstance(obj, m.OptionStatement):
106 rhs = obj.value.value.pval
107 if rhs.startswith('"') and rhs.endswith('"'):
108 rhs = rhs[1:-1]
109
Zack Williams045b63d2019-01-22 16:30:57 -0700110 if rhs.startswith("policy:"):
111 str = rhs.split(":", 1)[1]
112 val = self.fol_parser.parse(str, lexer=self.fol_lexer)
Sapan Bhatiaea6ff752017-07-14 01:52:18 -0400113
114 return m.PolicyDefinition(obj.name, val)
115
116 return obj
117
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200118 def proto_to_xproto_field(self, obj):
119 try:
120 opts = {}
121 for fd in obj.fieldDirective:
122 k = fd.pval.name.value.pval
123 v = fd.pval.value.value.pval
Zack Williams045b63d2019-01-22 16:30:57 -0700124 opts[k] = v
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200125
Zack Williams045b63d2019-01-22 16:30:57 -0700126 if "model" in opts and "link" in opts and "port" in opts:
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200127 obj.link = opts
128 pass
129 except KeyError:
130 raise
131
132 def proto_to_xproto_message(self, obj):
133 try:
Sapan Bhatiaea6ff752017-07-14 01:52:18 -0400134 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700135 bases = self.message_options["bases"].split(",")
Sapan Bhatiaea6ff752017-07-14 01:52:18 -0400136 except KeyError:
137 bases = []
138
Zack Williams045b63d2019-01-22 16:30:57 -0700139 bases = map(lambda x: str_to_dict(x[1:-1]), bases)
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200140 obj.bases = bases
141 except KeyError:
142 raise
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700143
144 def map_field(self, obj, s):
Zack Williams045b63d2019-01-22 16:30:57 -0700145 if "model" in s:
146 link = m.LinkDefinition(
147 "onetoone", "src", "name", "dst", obj.linespan, obj.lexspan, obj.p
148 )
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700149 lspec = m.LinkSpec(link, obj)
150 else:
151 lspec = obj
152 return lspec
153
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700154 def get_stack(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700155 return self.stack
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700156
157 def visit_PackageStatement(self, obj):
Zack Williams045b63d2019-01-22 16:30:57 -0700158 """Ignore"""
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700159 return True
160
161 def visit_ImportStatement(self, obj):
Zack Williams045b63d2019-01-22 16:30:57 -0700162 """Ignore"""
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700163 return True
164
165 def visit_OptionStatement(self, obj):
Zack Williams045b63d2019-01-22 16:30:57 -0700166 if self.current_message_name:
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200167 k = obj.name.value.pval
168 self.message_options[k] = obj.value.value.pval
Zack Williams045b63d2019-01-22 16:30:57 -0700169 if k in self.xproto_message_options:
170 obj.mark_for_deletion = True
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200171 else:
172 self.options[obj.name.value.pval] = obj.value.value.pval
173
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700174 return True
175
176 def visit_LU(self, obj):
177 return True
178
179 def visit_default(self, obj):
180 return True
181
182 def visit_FieldDirective(self, obj):
183 return True
184
185 def visit_FieldDirective_post(self, obj):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700186 return True
187
188 def visit_FieldType(self, obj):
189 return True
190
191 def visit_LinkDefinition(self, obj):
192 return True
193
194 def visit_FieldDefinition(self, obj):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700195 return True
196
197 def visit_FieldDefinition_post(self, obj):
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200198 self.proto_to_xproto_field(obj)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700199 return True
200
201 def visit_EnumFieldDefinition(self, obj):
202 return True
203
204 def visit_EnumDefinition(self, obj):
205 return True
206
207 def visit_MessageDefinition(self, obj):
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200208 self.current_message_name = obj.name.value.pval
209 self.message_options = {}
210
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700211 return True
Zack Williams045b63d2019-01-22 16:30:57 -0700212
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700213 def visit_MessageDefinition_post(self, obj):
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200214 self.proto_to_xproto_message(obj)
Zack Williams045b63d2019-01-22 16:30:57 -0700215 obj.body = filter(lambda x: not hasattr(x, "mark_for_deletion"), obj.body)
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200216 obj.body = map(replace_link, obj.body)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700217
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200218 self.current_message_name = None
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700219 return True
220
221 def visit_MessageExtension(self, obj):
222 return True
223
224 def visit_MethodDefinition(self, obj):
225 return True
226
227 def visit_ServiceDefinition(self, obj):
228 return True
229
230 def visit_ExtensionsDirective(self, obj):
231 return True
232
233 def visit_Literal(self, obj):
234 return True
235
236 def visit_Name(self, obj):
237 return True
238
239 def visit_DotName(self, obj):
240 return True
241
242 def visit_Proto(self, obj):
243 self.count_stack.push(len(obj.body))
244 return True
Zack Williams045b63d2019-01-22 16:30:57 -0700245
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700246 def visit_Proto_post(self, obj):
Sapan Bhatiaea6ff752017-07-14 01:52:18 -0400247
248 obj.body = [self.replace_policy(o) for o in obj.body]
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700249 return True
250
251 def visit_LinkSpec(self, obj):
252 return False