import sys
import os
import random
import re
sys.path += os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../pylib")),
from simplerpcgen.lang_cpp import emit_rpc_source_cpp
from simplerpcgen.lang_python import emit_rpc_source_python

def error(msg, ctx):
    from yapps import runtime
    err = runtime.SyntaxError(None, msg, ctx)
    runtime.print_error(err, ctx.scanner)
    sys.exit(1)


class pack:
    def __init__(self, **kv):
        self.__dict__.update(kv)
    def __str__(self):
        return str(self.__dict__)

def std_rename(t):
    if t in ["pair", "string", "map", "list", "set", "vector", "unordered_map", "unordered_set"]:
        t = "std::" + t
    return t

def forbid_reserved_names(name):
    if re.match("__([^_]+.*[^_]+|[^_])__$", name):
        raise Exception("bad name '%s', __NAME__ format names are reserved" % name)


# Begin -- grammar generated by Yapps
import sys, re
from yapps import runtime

class RpcScanner(runtime.Scanner):
    patterns = [
        ('"0"', re.compile('0')),
        ('"="', re.compile('=')),
        ('"\\)"', re.compile('\\)')),
        ('"\\|"', re.compile('\\|')),
        ('"\\("', re.compile('\\(')),
        ('"defer"', re.compile('defer')),
        ('"raw"', re.compile('raw')),
        ('"fast"', re.compile('fast')),
        ('"service"', re.compile('service')),
        ('"abstract"', re.compile('abstract')),
        ('"long"', re.compile('long')),
        ('"unsigned"', re.compile('unsigned')),
        ('"int"', re.compile('int')),
        ('"bool"', re.compile('bool')),
        ('">"', re.compile('>')),
        ('","', re.compile(',')),
        ('"<"', re.compile('<')),
        ('"v64"', re.compile('v64')),
        ('"v32"', re.compile('v32')),
        ('"i64"', re.compile('i64')),
        ('"i32"', re.compile('i32')),
        ('"i16"', re.compile('i16')),
        ('"i8"', re.compile('i8')),
        ('"}"', re.compile('}')),
        ('"{"', re.compile('{')),
        ('"struct"', re.compile('struct')),
        ('"::"', re.compile('::')),
        ('"namespace"', re.compile('namespace')),
        ('\\s+', re.compile('\\s+')),
        ('//[^\\n]+', re.compile('//[^\\n]+')),
        (';', re.compile(';')),
        ('EOF', re.compile('($|%%)')),
        ('SYMBOL', re.compile('[a-zA-Z_][a-zA-Z0-9_]*')),
    ]
    def __init__(self, str,*args,**kw):
        runtime.Scanner.__init__(self,None,{';':None,'\\s+':None,'//[^\\n]+':None,},str,*args,**kw)

class Rpc(runtime.Parser):
    Context = runtime.Context
    def rpc_source(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'rpc_source', [])
        namespace = None
        if self._peek('"namespace"', 'EOF', '"struct"', '"abstract"', '"service"', context=_context) == '"namespace"':
            namespace_decl = self.namespace_decl(_context)
            namespace = namespace_decl
        structs_and_services = self.structs_and_services(_context)
        EOF = self._scan('EOF', context=_context)
        return pack(namespace=namespace, structs=structs_and_services.structs, services=structs_and_services.services)

    def namespace_decl(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'namespace_decl', [])
        self._scan('"namespace"', context=_context)
        SYMBOL = self._scan('SYMBOL', context=_context)
        namespace = [SYMBOL]
        while self._peek('"::"', 'EOF', '"struct"', '"abstract"', '"service"', context=_context) == '"::"':
            self._scan('"::"', context=_context)
            SYMBOL = self._scan('SYMBOL', context=_context)
            namespace += SYMBOL,
        return namespace

    def structs_and_services(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'structs_and_services', [])
        structs = []; services = []
        while self._peek('"struct"', '"abstract"', '"service"', 'EOF', context=_context) != 'EOF':
            _token = self._peek('"struct"', '"abstract"', '"service"', context=_context)
            if _token == '"struct"':
                struct_decl = self.struct_decl(_context)
                structs += struct_decl,
            else: # in ['"abstract"', '"service"']
                service_decl = self.service_decl(_context)
                services += service_decl,
        return pack(structs=structs, services=services)

    def struct_decl(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'struct_decl', [])
        self._scan('"struct"', context=_context)
        SYMBOL = self._scan('SYMBOL', context=_context)
        self._scan('"{"', context=_context)
        struct_fields = self.struct_fields(_context)
        self._scan('"}"', context=_context)
        return pack(name=SYMBOL, fields=struct_fields)

    def struct_fields(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'struct_fields', [])
        fields = []
        while self._peek('"}"', '"i8"', '"i16"', '"i32"', '"i64"', '"v32"', '"v64"', '"bool"', '"int"', '"unsigned"', '"long"', '"::"', 'SYMBOL', context=_context) != '"}"':
            struct_field = self.struct_field(_context)
            fields += struct_field,
        return fields

    def struct_field(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'struct_field', [])
        type = self.type(_context)
        SYMBOL = self._scan('SYMBOL', context=_context)
        return pack(name=SYMBOL, type=type)

    def type(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'type', [])
        _token = self._peek('"i8"', '"i16"', '"i32"', '"i64"', '"v32"', '"v64"', '"bool"', '"int"', '"unsigned"', '"long"', '"::"', 'SYMBOL', context=_context)
        if _token == '"i8"':
            self._scan('"i8"', context=_context)
            return "rrr::i8"
        elif _token == '"i16"':
            self._scan('"i16"', context=_context)
            return "rrr::i16"
        elif _token == '"i32"':
            self._scan('"i32"', context=_context)
            return "rrr::i32"
        elif _token == '"i64"':
            self._scan('"i64"', context=_context)
            return "rrr::i64"
        elif _token == '"v32"':
            self._scan('"v32"', context=_context)
            return "rrr::v32"
        elif _token == '"v64"':
            self._scan('"v64"', context=_context)
            return "rrr::v64"
        elif _token in ['"::"', 'SYMBOL']:
            full_symbol = self.full_symbol(_context)
            t = std_rename(full_symbol)
            if self._peek('"<"', 'SYMBOL', '","', '">"', '"\\|"', '"\\)"', context=_context) == '"<"':
                self._scan('"<"', context=_context)
                type = self.type(_context)
                t += "<" + type
                while self._peek('">"', '","', context=_context) == '","':
                    self._scan('","', context=_context)
                    type = self.type(_context)
                    t += ", " + type
                self._scan('">"', context=_context)
                t += ">"
            return t
        else: # in ['"bool"', '"int"', '"unsigned"', '"long"']
            _token = self._peek('"bool"', '"int"', '"unsigned"', '"long"', context=_context)
            if _token == '"bool"':
                self._scan('"bool"', context=_context)
            elif _token == '"int"':
                self._scan('"int"', context=_context)
            elif _token == '"unsigned"':
                self._scan('"unsigned"', context=_context)
            else: # == '"long"'
                self._scan('"long"', context=_context)
            error("please use i8, i16, i32, i64, v32 or v64 instead", _context)

    def full_symbol(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'full_symbol', [])
        s = ""
        if self._peek('"::"', 'SYMBOL', context=_context) == '"::"':
            self._scan('"::"', context=_context)
            s += "::"
        SYMBOL = self._scan('SYMBOL', context=_context)
        s += SYMBOL
        while self._peek('"::"', '"<"', 'SYMBOL', '","', '">"', '"\\|"', '"\\)"', context=_context) == '"::"':
            self._scan('"::"', context=_context)
            SYMBOL = self._scan('SYMBOL', context=_context)
            s += "::" + SYMBOL
        return s

    def service_decl(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'service_decl', [])
        abstract = False
        if self._peek('"abstract"', '"service"', context=_context) == '"abstract"':
            self._scan('"abstract"', context=_context)
            abstract = True
        self._scan('"service"', context=_context)
        SYMBOL = self._scan('SYMBOL', context=_context)
        self._scan('"{"', context=_context)
        service_functions = self.service_functions(_context)
        self._scan('"}"', context=_context)
        return pack(name=SYMBOL, abstract=abstract, functions=service_functions)

    def service_functions(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'service_functions', [])
        functions = []
        while self._peek('"fast"', '"raw"', '"defer"', 'SYMBOL', '"}"', context=_context) != '"}"':
            service_function = self.service_function(_context)
            functions += service_function,
        return functions

    def service_function(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'service_function', [])
        attr = None; abstract = False; input = []; output = []
        if self._peek('"fast"', '"raw"', '"defer"', 'SYMBOL', context=_context) != 'SYMBOL':
            _token = self._peek('"fast"', '"raw"', '"defer"', context=_context)
            if _token == '"fast"':
                self._scan('"fast"', context=_context)
                attr = "fast"
            elif _token == '"raw"':
                self._scan('"raw"', context=_context)
                attr = "raw"
            else: # == '"defer"'
                self._scan('"defer"', context=_context)
                attr = "defer"
        SYMBOL = self._scan('SYMBOL', context=_context)
        forbid_reserved_names(SYMBOL)
        self._scan('"\\("', context=_context)
        func_arg_list = self.func_arg_list(_context)
        input = func_arg_list
        if self._peek('"\\|"', '"\\)"', context=_context) == '"\\|"':
            self._scan('"\\|"', context=_context)
            func_arg_list = self.func_arg_list(_context)
            output = func_arg_list
        self._scan('"\\)"', context=_context)
        if self._peek('"="', '"fast"', '"raw"', '"defer"', 'SYMBOL', '"}"', context=_context) == '"="':
            self._scan('"="', context=_context)
            self._scan('"0"', context=_context)
            abstract = True
        return pack(name=SYMBOL, attr=attr, abstract=abstract, input=input, output=output)

    def func_arg_list(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'func_arg_list', [])
        args = []
        _token = self._peek('"i8"', '"i16"', '"i32"', '"i64"', '"v32"', '"v64"', '"bool"', '"int"', '"unsigned"', '"long"', '","', '"::"', 'SYMBOL', '"\\|"', '"\\)"', context=_context)
        if _token in ['","', '"\\|"', '"\\)"']:
            pass
        else:
            func_arg = self.func_arg(_context)
            args = [func_arg]
            while self._peek('","', '"\\|"', '"\\)"', context=_context) == '","':
                self._scan('","', context=_context)
                func_arg = self.func_arg(_context)
                args += func_arg,
        return args

    def func_arg(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'func_arg', [])
        name = None
        type = self.type(_context)
        if self._peek('SYMBOL', '","', '"\\|"', '"\\)"', context=_context) == 'SYMBOL':
            SYMBOL = self._scan('SYMBOL', context=_context)
            name = SYMBOL; forbid_reserved_names(name)
        return pack(name=name, type=type)


def parse(rule, text):
    P = Rpc(RpcScanner(text))
    return runtime.wrap_error_reporter(P, rule)

# End -- grammar generated by Yapps



def generate_rpc_table(rpc_source):
    rpc_table = {}
    for service in rpc_source.services:
        for func in service.functions:
            rpc_code = random.randint(0x10000000, 0x70000000)
            rpc_table["%s.%s" % (service.name, func.name)] = rpc_code
    return rpc_table

def rpcgen(rpc_fpath, languages):
    with open(rpc_fpath) as f:
        rpc_src = f.read()

    rpc_src_lines = rpc_src.split("\n")

    cpp_header = cpp_footer = src = ''

    if rpc_src_lines.count('%%') == 2:
        # cpp_header + source + cpp_footer
        first = rpc_src_lines.index("%%")
        next = rpc_src_lines.index("%%", first + 1)
        cpp_header =  '\n'.join(rpc_src_lines[:first])
        src = '\n'.join(rpc_src_lines[first + 1:next])
        cpp_footer = '\n'.join(rpc_src_lines[next + 1:])
    elif rpc_src_lines.count('%%') == 1:
        # source + cpp_footer
        first = rpc_src_lines.index("%%")
        src = '\n'.join(rpc_src_lines[:first])
        cpp_footer = '\n'.join(rpc_src_lines[first + 1:])
    else:
        src = '\n'.join(rpc_src_lines)

    rpc_source = parse("rpc_source", src)
    rpc_table = generate_rpc_table(rpc_source) # service.func = rpc_code

    if "cpp" in languages:
        fpath = os.path.splitext(rpc_fpath)[0] + ".h"
        emit_rpc_source_cpp(rpc_source, rpc_table, fpath, cpp_header, cpp_footer)

    if "python" in languages:
        fpath = os.path.splitext(rpc_fpath)[0] + ".py"
        emit_rpc_source_python(rpc_source, rpc_table, fpath)

import sys
import os
import random
import re
sys.path += os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../pylib")),
from simplerpcgen.lang_cpp import emit_rpc_source_cpp
from simplerpcgen.lang_python import emit_rpc_source_python

def error(msg, ctx):
    from yapps import runtime
    err = runtime.SyntaxError(None, msg, ctx)
    runtime.print_error(err, ctx.scanner)
    sys.exit(1)


class pack:
    def __init__(self, **kv):
        self.__dict__.update(kv)
    def __str__(self):
        return str(self.__dict__)

def std_rename(t):
    if t in ["pair", "string", "map", "list", "set", "vector", "unordered_map", "unordered_set"]:
        t = "std::" + t
    return t

def forbid_reserved_names(name):
    if re.match("__([^_]+.*[^_]+|[^_])__$", name):
        raise Exception("bad name '%s', __NAME__ format names are reserved" % name)


# Begin -- grammar generated by Yapps
import sys, re
from yapps import runtime

class RpcScanner(runtime.Scanner):
    patterns = [
        ('"0"', re.compile('0')),
        ('"="', re.compile('=')),
        ('"\\)"', re.compile('\\)')),
        ('"\\|"', re.compile('\\|')),
        ('"\\("', re.compile('\\(')),
        ('"defer"', re.compile('defer')),
        ('"raw"', re.compile('raw')),
        ('"fast"', re.compile('fast')),
        ('"service"', re.compile('service')),
        ('"abstract"', re.compile('abstract')),
        ('"long"', re.compile('long')),
        ('"unsigned"', re.compile('unsigned')),
        ('"int"', re.compile('int')),
        ('"bool"', re.compile('bool')),
        ('">"', re.compile('>')),
        ('","', re.compile(',')),
        ('"<"', re.compile('<')),
        ('"v64"', re.compile('v64')),
        ('"v32"', re.compile('v32')),
        ('"i64"', re.compile('i64')),
        ('"i32"', re.compile('i32')),
        ('"i16"', re.compile('i16')),
        ('"i8"', re.compile('i8')),
        ('"}"', re.compile('}')),
        ('"{"', re.compile('{')),
        ('"struct"', re.compile('struct')),
        ('"::"', re.compile('::')),
        ('"namespace"', re.compile('namespace')),
        ('\\s+', re.compile('\\s+')),
        ('//[^\\n]+', re.compile('//[^\\n]+')),
        (';', re.compile(';')),
        ('EOF', re.compile('($|%%)')),
        ('SYMBOL', re.compile('[a-zA-Z_][a-zA-Z0-9_]*')),
    ]
    def __init__(self, str,*args,**kw):
        runtime.Scanner.__init__(self,None,{';':None,'\\s+':None,'//[^\\n]+':None,},str,*args,**kw)

class Rpc(runtime.Parser):
    Context = runtime.Context
    def rpc_source(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'rpc_source', [])
        namespace = None
        if self._peek('"namespace"', 'EOF', '"struct"', '"abstract"', '"service"', context=_context) == '"namespace"':
            namespace_decl = self.namespace_decl(_context)
            namespace = namespace_decl
        structs_and_services = self.structs_and_services(_context)
        EOF = self._scan('EOF', context=_context)
        return pack(namespace=namespace, structs=structs_and_services.structs, services=structs_and_services.services)

    def namespace_decl(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'namespace_decl', [])
        self._scan('"namespace"', context=_context)
        SYMBOL = self._scan('SYMBOL', context=_context)
        namespace = [SYMBOL]
        while self._peek('"::"', 'EOF', '"struct"', '"abstract"', '"service"', context=_context) == '"::"':
            self._scan('"::"', context=_context)
            SYMBOL = self._scan('SYMBOL', context=_context)
            namespace += SYMBOL,
        return namespace

    def structs_and_services(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'structs_and_services', [])
        structs = []; services = []
        while self._peek('"struct"', '"abstract"', '"service"', 'EOF', context=_context) != 'EOF':
            _token = self._peek('"struct"', '"abstract"', '"service"', context=_context)
            if _token == '"struct"':
                struct_decl = self.struct_decl(_context)
                structs += struct_decl,
            else: # in ['"abstract"', '"service"']
                service_decl = self.service_decl(_context)
                services += service_decl,
        return pack(structs=structs, services=services)

    def struct_decl(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'struct_decl', [])
        self._scan('"struct"', context=_context)
        SYMBOL = self._scan('SYMBOL', context=_context)
        self._scan('"{"', context=_context)
        struct_fields = self.struct_fields(_context)
        self._scan('"}"', context=_context)
        return pack(name=SYMBOL, fields=struct_fields)

    def struct_fields(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'struct_fields', [])
        fields = []
        while self._peek('"}"', '"i8"', '"i16"', '"i32"', '"i64"', '"v32"', '"v64"', '"bool"', '"int"', '"unsigned"', '"long"', '"::"', 'SYMBOL', context=_context) != '"}"':
            struct_field = self.struct_field(_context)
            fields += struct_field,
        return fields

    def struct_field(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'struct_field', [])
        type = self.type(_context)
        SYMBOL = self._scan('SYMBOL', context=_context)
        return pack(name=SYMBOL, type=type)

    def type(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'type', [])
        _token = self._peek('"i8"', '"i16"', '"i32"', '"i64"', '"v32"', '"v64"', '"bool"', '"int"', '"unsigned"', '"long"', '"::"', 'SYMBOL', context=_context)
        if _token == '"i8"':
            self._scan('"i8"', context=_context)
            return "rrr::i8"
        elif _token == '"i16"':
            self._scan('"i16"', context=_context)
            return "rrr::i16"
        elif _token == '"i32"':
            self._scan('"i32"', context=_context)
            return "rrr::i32"
        elif _token == '"i64"':
            self._scan('"i64"', context=_context)
            return "rrr::i64"
        elif _token == '"v32"':
            self._scan('"v32"', context=_context)
            return "rrr::v32"
        elif _token == '"v64"':
            self._scan('"v64"', context=_context)
            return "rrr::v64"
        elif _token in ['"::"', 'SYMBOL']:
            full_symbol = self.full_symbol(_context)
            t = std_rename(full_symbol)
            if self._peek('"<"', 'SYMBOL', '","', '">"', '"\\|"', '"\\)"', context=_context) == '"<"':
                self._scan('"<"', context=_context)
                type = self.type(_context)
                t += "<" + type
                while self._peek('">"', '","', context=_context) == '","':
                    self._scan('","', context=_context)
                    type = self.type(_context)
                    t += ", " + type
                self._scan('">"', context=_context)
                t += ">"
            return t
        else: # in ['"bool"', '"int"', '"unsigned"', '"long"']
            _token = self._peek('"bool"', '"int"', '"unsigned"', '"long"', context=_context)
            if _token == '"bool"':
                self._scan('"bool"', context=_context)
            elif _token == '"int"':
                self._scan('"int"', context=_context)
            elif _token == '"unsigned"':
                self._scan('"unsigned"', context=_context)
            else: # == '"long"'
                self._scan('"long"', context=_context)
            error("please use i8, i16, i32, i64, v32 or v64 instead", _context)

    def full_symbol(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'full_symbol', [])
        s = ""
        if self._peek('"::"', 'SYMBOL', context=_context) == '"::"':
            self._scan('"::"', context=_context)
            s += "::"
        SYMBOL = self._scan('SYMBOL', context=_context)
        s += SYMBOL
        while self._peek('"::"', '"<"', 'SYMBOL', '","', '">"', '"\\|"', '"\\)"', context=_context) == '"::"':
            self._scan('"::"', context=_context)
            SYMBOL = self._scan('SYMBOL', context=_context)
            s += "::" + SYMBOL
        return s

    def service_decl(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'service_decl', [])
        abstract = False
        if self._peek('"abstract"', '"service"', context=_context) == '"abstract"':
            self._scan('"abstract"', context=_context)
            abstract = True
        self._scan('"service"', context=_context)
        SYMBOL = self._scan('SYMBOL', context=_context)
        self._scan('"{"', context=_context)
        service_functions = self.service_functions(_context)
        self._scan('"}"', context=_context)
        return pack(name=SYMBOL, abstract=abstract, functions=service_functions)

    def service_functions(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'service_functions', [])
        functions = []
        while self._peek('"fast"', '"raw"', '"defer"', 'SYMBOL', '"}"', context=_context) != '"}"':
            service_function = self.service_function(_context)
            functions += service_function,
        return functions

    def service_function(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'service_function', [])
        attr = None; abstract = False; input = []; output = []
        if self._peek('"fast"', '"raw"', '"defer"', 'SYMBOL', context=_context) != 'SYMBOL':
            _token = self._peek('"fast"', '"raw"', '"defer"', context=_context)
            if _token == '"fast"':
                self._scan('"fast"', context=_context)
                attr = "fast"
            elif _token == '"raw"':
                self._scan('"raw"', context=_context)
                attr = "raw"
            else: # == '"defer"'
                self._scan('"defer"', context=_context)
                attr = "defer"
        SYMBOL = self._scan('SYMBOL', context=_context)
        forbid_reserved_names(SYMBOL)
        self._scan('"\\("', context=_context)
        func_arg_list = self.func_arg_list(_context)
        input = func_arg_list
        if self._peek('"\\|"', '"\\)"', context=_context) == '"\\|"':
            self._scan('"\\|"', context=_context)
            func_arg_list = self.func_arg_list(_context)
            output = func_arg_list
        self._scan('"\\)"', context=_context)
        if self._peek('"="', '"fast"', '"raw"', '"defer"', 'SYMBOL', '"}"', context=_context) == '"="':
            self._scan('"="', context=_context)
            self._scan('"0"', context=_context)
            abstract = True
        return pack(name=SYMBOL, attr=attr, abstract=abstract, input=input, output=output)

    def func_arg_list(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'func_arg_list', [])
        args = []
        _token = self._peek('"i8"', '"i16"', '"i32"', '"i64"', '"v32"', '"v64"', '"bool"', '"int"', '"unsigned"', '"long"', '","', '"::"', 'SYMBOL', '"\\|"', '"\\)"', context=_context)
        if _token in ['","', '"\\|"', '"\\)"']:
            pass
        else:
            func_arg = self.func_arg(_context)
            args = [func_arg]
            while self._peek('","', '"\\|"', '"\\)"', context=_context) == '","':
                self._scan('","', context=_context)
                func_arg = self.func_arg(_context)
                args += func_arg,
        return args

    def func_arg(self, _parent=None):
        _context = self.Context(_parent, self._scanner, 'func_arg', [])
        name = None
        type = self.type(_context)
        if self._peek('SYMBOL', '","', '"\\|"', '"\\)"', context=_context) == 'SYMBOL':
            SYMBOL = self._scan('SYMBOL', context=_context)
            name = SYMBOL; forbid_reserved_names(name)
        return pack(name=name, type=type)


def parse(rule, text):
    P = Rpc(RpcScanner(text))
    return runtime.wrap_error_reporter(P, rule)

# End -- grammar generated by Yapps



def generate_rpc_table(rpc_source):
    rpc_table = {}
    for service in rpc_source.services:
        for func in service.functions:
            rpc_code = random.randint(0x10000000, 0x70000000)
            rpc_table["%s.%s" % (service.name, func.name)] = rpc_code
    return rpc_table

def rpcgen(rpc_fpath, languages):
    with open(rpc_fpath) as f:
        rpc_src = f.read()

    rpc_src_lines = rpc_src.split("\n")

    cpp_header = cpp_footer = src = ''

    if rpc_src_lines.count('%%') == 2:
        # cpp_header + source + cpp_footer
        first = rpc_src_lines.index("%%")
        next = rpc_src_lines.index("%%", first + 1)
        cpp_header =  '\n'.join(rpc_src_lines[:first])
        src = '\n'.join(rpc_src_lines[first + 1:next])
        cpp_footer = '\n'.join(rpc_src_lines[next + 1:])
    elif rpc_src_lines.count('%%') == 1:
        # source + cpp_footer
        first = rpc_src_lines.index("%%")
        src = '\n'.join(rpc_src_lines[:first])
        cpp_footer = '\n'.join(rpc_src_lines[first + 1:])
    else:
        src = '\n'.join(rpc_src_lines)

    rpc_source = parse("rpc_source", src)
    rpc_table = generate_rpc_table(rpc_source) # service.func = rpc_code

    if "cpp" in languages:
        fpath = os.path.splitext(rpc_fpath)[0] + ".h"
        emit_rpc_source_cpp(rpc_source, rpc_table, fpath, cpp_header, cpp_footer)

    if "python" in languages:
        fpath = os.path.splitext(rpc_fpath)[0] + ".py"
        emit_rpc_source_python(rpc_source, rpc_table, fpath)

# Begin -- grammar generated by Yapps # in ['"abstract"', '"service"'] # in ['"bool"', '"int"', '"unsigned"', '"long"'] # == '"long"' # == '"defer"' # End -- grammar generated by Yapps # cpp_header + source + cpp_footer # source + cpp_footer # service.func = rpc_code