C++中訊息自動派發之二 About IDL解析器

來源:互聯網
上載者:User
文章目錄
  •  1. 詞法分析
  • 2. 文法分析
  • 3. 訊息體結構管理
  • 4. 中間代碼產生
  • 5. TODO

  前一篇blog中講了如何在C++中實現訊息的自動派發,而關鍵點在於如何?通過IDL檔案自動產生msg_dispatcher模板類。有幾個網友提醒我idl解析器會比較難寫,事實卻是如此。我第一個版本的idl解析器本來只是想做demo只用。花了一個晚上時間拼湊了幾個python函數,msg_dispatcher類倒是能產生,但解析器的代碼太混亂了,簡直毫無結構可言。說實話,這個訊息自動派發架構我還要深入的開發、擴充、最佳化,所以還是像模像樣的搞一個解析器吧。於是果斷扔掉第一版本的解析器代碼,重新實現之。仍然採用Python實現,目前只完成了cpp代碼產生器,並且只能支援訊息體的decode,不支援encode,文法報錯機制也沒有加入。隨未完美,但是畢竟開了個好頭,這裡講一下解析器的實現。

完整範例程式碼 svn co http://ffown.googlecode.com/svn/trunk/fflib/lib/generator/

樣本idl 檔案:svn co http://ffown.googlecode.com/svn/trunk/fflib/lib/generator/example.idl

struct student_t
{
struct book_t
{
int16 pages;
};
string age;
};
 1. 詞法分析

    用Python的好處是解析字串非常方便,首先要把idl源檔案解析成單個的單詞。我定義了一個src_parser_t類實現此功能。解析分如下幾步:

  1> 讀入idl 源檔案內容

  2> 把源檔案內容分隔成單個行,只需將file_content_str.split('\n')即可。

  3> 在把每行按空格分隔成單個單詞 split(' ')即可

  4> 如果有單詞最後一個字元有分號去掉。

解析代碼如下(只有80行):

from pylib.inc import *

class src_parser_t:
def __init__(self, file):
self.file = file
self.struct_def_mgr = struct_def_mgr_t()
self.file_content = ''
self.all_words = []
f = open(file)
self.file_content = f.read()
f.close()
def get_struct_def_mgr(self):
return self.struct_def_mgr
def parse_to_words(self):
all_line = self.file_content.split('\n')
for line in all_line:
words = line.split(' ')
for w in words:
w = w.strip()
if w != '':
self.all_words.append(w)

def build_struct_relation(self):
struct_stack = []
index = 0
while index < len(self.all_words):
if len(struct_stack) < 1:
struct_stack.append(self.struct_def_mgr)

parent_struct = struct_stack[len(struct_stack) - 1]
cur_word = self.all_words[index]
if cur_word == 'struct':
struct_def = struct_def_t(self.all_words[index + 1])
parent_struct.add_struct(struct_def)
struct_stack.append(struct_def)
index = index + 1
elif cur_word == '}' or cur_word == '};':
struct_stack.pop()
elif cur_word == 'int8' or cur_word == 'int16' or cur_word == 'int32' or \
cur_word == 'float' or cur_word == 'string':
field_name = self.all_words[index + 1].split(';')[0]
field = field_def_t(field_name, cur_word, '', '')
parent_struct.add_field(field)
index = index + 1
else:
if -1 == cur_word.find('dictionary') and -1 == cur_word.find('{') and -1 == cur_word.find('array') :
field_name = self.all_words[index + 1].split(';')[0]
field = field_def_t(field_name, cur_word, '', '')
parent_struct.add_field(field)
index = index + 1
else:
field_type = ''
field_name = ''
key_type = ''
val_type = ''
if -1 != cur_word.find('array'):
field_name = self.all_words[index + 1].split(';')[0]
word_split = cur_word.split('<')
field_type = word_split[0]
key_type = word_split[1].split('>')[0]
field = field_def_t(field_name, field_type, key_type, '')
parent_struct.add_field(field)
index = index + 1
elif -1 != cur_word.find('dictionary'):
field_name = self.all_words[index + 1].split(';')[0]
word_split = cur_word.split('<')
field_type = word_split[0]
key_val_type = word_split[1].split('>')
key_type = key_val_type[0].split(',')[0]
val_type = key_val_type[0].split(',')[1]
field = field_def_t(field_name, field_type, key_type, val_type)
parent_struct.add_field(field)
index = index + 1
index = index + 1

def exe(self):
self.parse_to_words()
self.build_struct_relation()
2. 文法分析

  idl 檔案文法規則非常簡單,遍曆所有單詞,依次做如下判斷:

  1> 如果當前單詞為struct, 那麼下一個單詞即為新的訊息體名稱,當然也有可能是子訊息體,無需擔心,只需將新建立的訊息體對象添加到特定棧的的棧頂struct對象中,預設struct_def_mgr存在於棧中。並把新的訊息體壓入棧中。

  2> 如果為int/string/float/array/dictionary,那麼下一個單詞即為訊息體的欄位名稱。把新欄位對象add到棧頂的struct_def對象中

  3> 遇到‘}’ 代表當前struct的解析完成。pop 彈出棧頂struct_def 對象。

  4> 其他欄位忽略

3. 訊息體結構管理

  1> field_def_t 描述訊息體欄位資訊,包括欄位的名稱、類型、key_type、val_type、父訊息體對象。如array<int>那麼key_type為int,如果dictionary<int,string> 那麼key_type為int, val_type為string

  2> struct_def_t 描述單個訊息體的資訊,包括訊息體名稱、子訊息集合、欄位對象集合。

  3> struct_def_mgr_t 維護所有的訊息體集合。

代碼即注釋:

class field_def_t:
def __init__(self, name, type, key_type, val_type_):
self.name = name
self.parent = None
self.type = type
self.key_type = key_type
self.val_type = val_type_
def get_name(self):
return self.name
def get_parent(self):
return self.parent
def set_parent(self, p):
self.parent = p
def get_type(self):
return self.type
def get_key_type(self):
return self.key_type
def get_val_type(self):
return self.val_type
def dump(self, prefix = ''):
print(prefix, self.name, self.type, self.key_type, self.val_type)

class struct_def_t:
def __init__(self, name, parent = None):
self.name = name
self.parent = parent
self.all_fields = {}
self.sub_struct = []

def get_name(self):
return self.name
def get_parent(self):
return self.parent
def set_parent(self, parent):
self.parent = parent
def add_field(self, field_def_):
self.all_fields[field_def_.get_name()] = field_def_
field_def_.set_parent(self)
def add_struct(self, struct_def_):
self.sub_struct.append(struct_def_)
struct_def_.set_parent(self)
def get_all_struct(self):
return self.sub_struct
def get_all_field(self):
return self.all_fields
def get_parent(self):
return self.parent
def has_field(self, name):
if None == self.all_fields.get(name):
return False
return True
def dump(self, prefix = ''):
print(prefix, self.name, 'include struct:')
for struct in self.sub_struct:
struct.dump(prefix + "")
print(prefix, self.name, "include fields:")
for field in self.all_fields:
self.all_fields[field].dump(prefix + "")


class struct_def_mgr_t:
def __init__(self):
self.all_struct = {}
def get_name(self):
return ''
def add_struct(self, struct_def_):
self.all_struct[struct_def_.get_name()] = struct_def_
struct_def_.set_parent(None)
def get_all_struct(self):
return self.all_struct
def get_struct(self, name):
return self.all_struct[name]
def get_parent(self):
return ''
def dump(self):
for name in self.all_struct:
self.all_struct[name].dump()
4. 中間代碼產生

  代碼是由code_generator_t 類實現的。考慮到未來需要支援多語言,中間代碼產生採用策略模式。當前只實現了cpp的code_generator。如果要增強其他語言,只需再編寫一個特定的code_generator_t類即可。

5. TODO

  1> struct 訊息體只支援decode from json,還不能支援encode to json,也不能支援decode from Bin or encode to Bin。

  2> 文法報錯不夠友好。

  3> 多語言支援。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.