C专家编程:用python写cdecl程序,以分析C语言程序的声明语句

前两天阅读《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



你可能感兴趣的:(C专家编程:用python写cdecl程序,以分析C语言程序的声明语句)