diff options
Diffstat (limited to 'tools/pyang_plugins/bgpyang2golang.py')
-rw-r--r-- | tools/pyang_plugins/bgpyang2golang.py | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/tools/pyang_plugins/bgpyang2golang.py b/tools/pyang_plugins/bgpyang2golang.py new file mode 100644 index 00000000..bf2ce2eb --- /dev/null +++ b/tools/pyang_plugins/bgpyang2golang.py @@ -0,0 +1,157 @@ +# Copyright (C) 2013,2014 Nippon Telegraph and Telephone Corporation. +# Copyright (C) 2013,2014 YAMAMOTO Takashi <yamamoto at valinux co jp> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# this is a pyang plugin to generate ryu/lib/of_config/generated_classes.py +# usage example: +# PYTHONPATH=. ./bin/pyang --plugindir ~/git/ryu/tools/pyang_plugins -f ryu ~/git/ryu/tools/of-config1.1.1.yang > ~/git/ryu/lib/of_config/generated_classes.py + + +_COPYRIGHT_NOTICE = """ +// Copyright (C) 2013,2014 Nippon Telegraph and Telephone Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. +// See the License for the specific language governing permissions and +// limitations under the License. +""" + + +import sys +import StringIO +import pyang +from pyang import plugin + +struct_map = {} + +def pyang_plugin_init(): + plugin.register_plugin(GolangPlugin()) + + +class GolangPlugin(plugin.PyangPlugin): + def add_output_format(self, fmts): + fmts['golang'] = self + + def emit(self, ctx, modules, fd): + emit_golang(ctx, modules[0], fd) + + +def emit_golang(ctx, module, fd): + ctx.golang_struct_def = [] + visit_children(ctx, module, fd, module.i_children) + ctx.golang_struct_def.reverse() + done = set() + + generate_header(ctx) + for struct in ctx.golang_struct_def: + struct_name = struct.arg + if struct_name in done: + continue + emit_class_def(struct, struct_name) + done.add(struct_name) + + # generate_header(ctx) + + +def emit_class_def(c, struct_name): + + o = StringIO.StringIO() + struct_name_org = struct_name + struct_name = convert_to_gostruct(struct_name) + struct_map[struct_name_org] = struct_name + print >> o, '//struct for container %s' % struct_name_org + print >> o, 'type %s struct {' % struct_name + for child in c.i_children: + val_name_org = child.arg + val_name = convert_to_golang(child.arg) + + if is_leaf(child): + type_obj = child.search_one('type') + #if type_obj.arg == 'leafref': + # print type_obj.search_one('path').arg + type_name = type_obj.arg if type_obj is not None else None + else: + if is_list(child): + assert val_name_org in struct_map + type_name = '[]'+ struct_map[val_name_org] + val_name = val_name + 'List' + if is_container(child): + type_name = struct_map[val_name_org] + val_name = val_name + + print >> o, ' %s\t%s' % (val_name, translate_type(type_name)) + print >> o, '}' + print o.getvalue() + + +def visit_children(ctx, module, fd, children, prefix=''): + for c in children: + t = c.search_one('type') + type_name = t.arg if t is not None else None + #print '%skeyword->%s, arg->%s, type->%s' % (prefix, c.keyword, c.arg, type_name) + if is_list(c) or is_container(c): + ctx.golang_struct_def.append(c) + if hasattr(c, 'i_children'): + visit_children(ctx, module, fd, c.i_children, prefix + ' ') + + +def is_leaf(s): + return s.keyword in ['leaf', 'leaf-list'] + +def is_list(s): + return s.keyword in ['list'] + +def is_container(s): + return s.keyword in ['container'] + +def generate_header(ctx): + print _COPYRIGHT_NOTICE + print 'package config' + print '' + + +_type_translation_map = { + 'decimal64' : 'float64', + 'inet:ip-address': '*net.IP', + 'inet:ipv4-address': '*net.IP', + 'inet:as-number' : 'uint32', + 'rr-cluster-id-type' : 'uint32', +} + +def translate_type(key): + if _type_translation_map.has_key(key): + return _type_translation_map[key] + else: + return key + + +def convert_to_gostruct(type_string): + return convert_to_golang(type_string) + 'Type' + + +# 'hoge-hoge' -> 'HogeHoge' +def convert_to_golang(type_string): + a = type_string.split('-') + a = map(lambda x: x.capitalize(), a) # XXX locale sensitive + return ''.join(a) + |