前两天阅读《C专家编程》第3章“分析C语言的声明”,书中提供了一个名叫 cdecl 的算法流程分析C语言程序的声明语句。
输入C语言声明语句形式,用英语输出对应的描述。
我参照《C专家编程》“编程挑战”的设计,用python实现了一个 cdecl :
# -*- coding: cp936 -*- Type_list = ['void', 'char', 'int', 'float', 'struct'] # type of '*', '[', '(' is themselves Qualifier_list = ['const', 'static'] # otherwise, identifier This_token = {'type':'NOTYPE', 'string':""} String_left = "" Token_stack = [] Output_string = "" """ utility """ def classify_string(): # 查看当前标记 # 通过this.type返回一个值,内容为"type","qualifier"或"identifier" global This_token if This_token['string'] == "": This_token['type'] = 'NOTYPE' if This_token['string'] in Type_list: This_token['type'] = 'TYPE' elif This_token['string'] in Qualifier_list: This_token['type'] = 'QUALIFIER' else: This_token['type'] = 'IDENTIFIER' def get_token(): global This_token, String_left # 把下一个标记读入this.string if String_left == "": This_token['string'] = "" This_token['type'] = This_token['string'] return while String_left[0] == ' ': String_left = String_left[1:] if String_left == "": This_token['string'] = "" This_token['type'] = This_token['string'] return while not String_left == "": if String_left[0].isalnum(): This_token['string'] += String_left[0] String_left = String_left[1:] else: break # 如果是字母数字组合,调用classify_string if This_token['string'].isalnum(): classify_string() # 否则是一个单字符标记,this.type="该标记";用一个nul结束this.string else: if String_left == "": This_token['string'] = "" This_token['type'] = This_token['string'] return This_token['string'] = String_left[0] This_token['type'] = This_token['string'] String_left = String_left[1:] def read_to_first_identifier(): global Token_stack, This_token, String_left, Output_string # 调用get_token,并把标记压入到堆栈中,直到遇见第一个标识符 get_token() while not This_token['type'] == 'IDENTIFIER': Token_stack.append(This_token.copy()) This_token['string'] = "" This_token['type'] = 'NOTYPE' get_token() # print "identifier is __", this.string Output_string += "Identifier \"" + This_token['string'] + "\" is " # 继续调用get_token This_token['string'] = "" This_token['type'] = 'NOTYPE' get_token() """ parser """ def deal_with_function_args(): global String_left, Output_string # 当读取越过')'后,printf "函数返回...." pos = String_left.find(')') args = '(' + String_left[:pos] + ')' String_left = String_left[pos+1:] Output_string += "a function which take args " + args + " and returns " get_token() def deal_with_arrays(): global String_left, Output_string # 当读取"[size]"后,打印之并继续向右读取 pos = String_left.find(']') Output_string += "an array of size " + String_left[:pos] + \ ", in which each element is " String_left = String_left[pos+1:] get_token() def deal_with_any_pointers(): global This_token, String_left, Output_string # 当从堆栈中读取'*'时,print"指向....的指针"并将其弹出堆栈 if This_token['type'] == '*': Output_string += "a pointer to " def deal_with_declarator(): global Token_stack, This_token, String_left, Output_string # if this.type is '[': deal_with_arrays if This_token['type'] == '[': deal_with_arrays() # if this.type is '(': deal_with_function_args if This_token['type'] == '(': deal_with_function_args() # deal_with_any_pointers if This_token['type'] == '*': deal_with_any_pointers() # while(堆栈非空): while Token_stack: This_token = Token_stack.pop() # if 它是一个'(': if This_token['type'] == '(': # 将其弹出堆栈,并调用get_token;应该获得')' #This_token = Token_stack.pop() get_token() # deal_with_declarator deal_with_declarator() # [!] elif '*' elif This_token['type'] == '*': deal_with_declarator() # else: else: # 将其弹出堆栈并打印 Output_string += This_token['string'] + " " """ main """ if __name__ == "__main__": global Token_stack, This_token, String_left, Output_string # func_declaration = "char * const *(*next)();" test_strings = ["char * const *(*next)();", "char *(* c[10])(int **p);", "const int * grape", "int const * grape", "int * const grape", "int sum(int a, int b);", "char (*(*x())[])()", "char (*(*x[3])())[5]"] for string in test_strings: print "\n**********\n== %s ==" % string This_token = {'type':'NOTYPE', 'string':""} String_left = "" Token_stack = [] String_left = string Output_string = "" read_to_first_identifier() deal_with_declarator() print Output_string
********** == char * const *(*next)(); == Identifier "next" is a pointer to a function which take args () and returns a pointer to const a pointer to char ********** == char *(* c[10])(int **p); == Identifier "c" is an array of size 10, in which each element is a pointer to a function which take args (int **p) and returns a pointer to char ********** == const int * grape == Identifier "grape" is a pointer to int const ********** == int const * grape == Identifier "grape" is a pointer to const int ********** == int * const grape == Identifier "grape" is const a pointer to int ********** == int sum(int a, int b); == Identifier "sum" is a function which take args (int a, int b) and returns int ********** == char (*(*x())[])() == Identifier "x" is a function which take args () and returns a pointer to an array of size , in which each element is a pointer to a function which take args () and returns char ********** == char (*(*x[3])())[5] == Identifier "x" is an array of size 3, in which each element is a pointer to a function which take args () and returns a pointer to an array of size 5, in which each element is char
可惜的是,用了不少全局变量,今后有时间得优化它。
另外,书中章末附带实现 cdecl 的C程序网上有人抄写了,见 “程序比程序员更理解c语言! cdecl程序(分析c语言的声明”:
http://blog.csdn.net/mazheng1989/article/details/7307183