您的位置:首页 > 编程语言 > C语言/C++

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

2013-07-29 09:56 351 查看
前两天阅读《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语言的声明”:

/article/8904506.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: