Matteo Scandolo | d2044a4 | 2017-08-07 16:08:28 -0700 | [diff] [blame] | 1 | # 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 Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 16 | import plyxproto.model as m |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 17 | from plyxproto.helpers import Visitor |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 18 | import pdb |
| 19 | import argparse |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 20 | import plyxproto.parser as plyxproto |
Sapan Bhatia | ea6ff75 | 2017-07-14 01:52:18 -0400 | [diff] [blame] | 21 | from plyxproto.logicparser import FOLParser, FOLLexer |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 22 | import traceback |
| 23 | import sys |
| 24 | import jinja2 |
| 25 | import os |
Sapan Bhatia | ea6ff75 | 2017-07-14 01:52:18 -0400 | [diff] [blame] | 26 | import ply.lex as lex |
| 27 | import ply.yacc as yacc |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 28 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 29 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 30 | class Stack(list): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 31 | def push(self, x): |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 32 | self.append(x) |
| 33 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 34 | |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 35 | def str_to_dict(s): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 36 | lst = s.rsplit(".", 1) |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 37 | name = lst[-1] |
| 38 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 39 | if len(lst) == 2: |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 40 | package = lst[0] |
| 41 | else: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 42 | package = "" |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 43 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 44 | return {"name": name, "package": package, "fqn": s} |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 45 | |
Sapan Bhatia | ea6ff75 | 2017-07-14 01:52:18 -0400 | [diff] [blame] | 46 | |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 47 | def replace_link(obj): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 48 | try: |
| 49 | link = obj.link |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 50 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 51 | through = link["through"] |
| 52 | except KeyError: |
| 53 | through = None |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 54 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 55 | try: |
| 56 | through_str = through[1:-1] |
| 57 | except TypeError: |
| 58 | through_str = None |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 59 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 60 | if through_str: |
| 61 | through_dict = str_to_dict(through_str) |
| 62 | else: |
| 63 | through_dict = {} |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 64 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 65 | model_dict = str_to_dict(link["model"][1:-1]) |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 66 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 67 | 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 Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 81 | |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 82 | class Proto2XProto(Visitor): |
Sapan Bhatia | ea6ff75 | 2017-07-14 01:52:18 -0400 | [diff] [blame] | 83 | fol_lexer = lex.lex(module=FOLLexer()) |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 84 | fol_parser = yacc.yacc(module=FOLParser(), start="goal", debug=0, outputdir="/tmp") |
Sapan Bhatia | ea6ff75 | 2017-07-14 01:52:18 -0400 | [diff] [blame] | 85 | |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 86 | def __init__(self): |
| 87 | super(Proto2XProto, self).__init__() |
| 88 | |
| 89 | self.stack = Stack() |
| 90 | self.count_stack = Stack() |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 91 | self.content = "" |
| 92 | self.offset = 0 |
| 93 | self.statementsChanged = 0 |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 94 | self.message_options = {} |
| 95 | self.options = {} |
| 96 | self.current_message_name = None |
| 97 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 98 | self.xproto_message_options = ["bases"] |
| 99 | self.xproto_field_options = ["model"] |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 100 | self.verbose = 0 |
| 101 | self.first_field = True |
| 102 | self.first_method = True |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 103 | |
Sapan Bhatia | ea6ff75 | 2017-07-14 01:52:18 -0400 | [diff] [blame] | 104 | 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 Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 110 | if rhs.startswith("policy:"): |
| 111 | str = rhs.split(":", 1)[1] |
| 112 | val = self.fol_parser.parse(str, lexer=self.fol_lexer) |
Sapan Bhatia | ea6ff75 | 2017-07-14 01:52:18 -0400 | [diff] [blame] | 113 | |
| 114 | return m.PolicyDefinition(obj.name, val) |
| 115 | |
| 116 | return obj |
| 117 | |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 118 | 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 Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 124 | opts[k] = v |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 125 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 126 | if "model" in opts and "link" in opts and "port" in opts: |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 127 | obj.link = opts |
| 128 | pass |
| 129 | except KeyError: |
| 130 | raise |
| 131 | |
| 132 | def proto_to_xproto_message(self, obj): |
| 133 | try: |
Sapan Bhatia | ea6ff75 | 2017-07-14 01:52:18 -0400 | [diff] [blame] | 134 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 135 | bases = self.message_options["bases"].split(",") |
Sapan Bhatia | ea6ff75 | 2017-07-14 01:52:18 -0400 | [diff] [blame] | 136 | except KeyError: |
| 137 | bases = [] |
| 138 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 139 | bases = map(lambda x: str_to_dict(x[1:-1]), bases) |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 140 | obj.bases = bases |
| 141 | except KeyError: |
| 142 | raise |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 143 | |
| 144 | def map_field(self, obj, s): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 145 | if "model" in s: |
| 146 | link = m.LinkDefinition( |
| 147 | "onetoone", "src", "name", "dst", obj.linespan, obj.lexspan, obj.p |
| 148 | ) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 149 | lspec = m.LinkSpec(link, obj) |
| 150 | else: |
| 151 | lspec = obj |
| 152 | return lspec |
| 153 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 154 | def get_stack(self): |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 155 | return self.stack |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 156 | |
| 157 | def visit_PackageStatement(self, obj): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 158 | """Ignore""" |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 159 | return True |
| 160 | |
| 161 | def visit_ImportStatement(self, obj): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 162 | """Ignore""" |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 163 | return True |
| 164 | |
| 165 | def visit_OptionStatement(self, obj): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 166 | if self.current_message_name: |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 167 | k = obj.name.value.pval |
| 168 | self.message_options[k] = obj.value.value.pval |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 169 | if k in self.xproto_message_options: |
| 170 | obj.mark_for_deletion = True |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 171 | else: |
| 172 | self.options[obj.name.value.pval] = obj.value.value.pval |
| 173 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 174 | 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 Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 186 | 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 Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 195 | return True |
| 196 | |
| 197 | def visit_FieldDefinition_post(self, obj): |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 198 | self.proto_to_xproto_field(obj) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 199 | 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 Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 208 | self.current_message_name = obj.name.value.pval |
| 209 | self.message_options = {} |
| 210 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 211 | return True |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 212 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 213 | def visit_MessageDefinition_post(self, obj): |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 214 | self.proto_to_xproto_message(obj) |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 215 | obj.body = filter(lambda x: not hasattr(x, "mark_for_deletion"), obj.body) |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 216 | obj.body = map(replace_link, obj.body) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 217 | |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 218 | self.current_message_name = None |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 219 | 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 Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 245 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 246 | def visit_Proto_post(self, obj): |
Sapan Bhatia | ea6ff75 | 2017-07-14 01:52:18 -0400 | [diff] [blame] | 247 | |
| 248 | obj.body = [self.replace_policy(o) for o in obj.body] |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 249 | return True |
| 250 | |
| 251 | def visit_LinkSpec(self, obj): |
| 252 | return False |