Skip to content

Instantly share code, notes, and snippets.

@LeslieZhu
Created December 27, 2013 03:40
Show Gist options
  • Save LeslieZhu/8142288 to your computer and use it in GitHub Desktop.
Save LeslieZhu/8142288 to your computer and use it in GitHub Desktop.
将C语言源程序文件中的C89的32个关键字转换为大写,但不包括在注释里面的。 可以批处理文件,也可以通过管道输入,或者进入交互模式。 这是《编译原理及实践》的2.21习题的一个实践。
#!/usr/bin/env python
#-*- coding:utf-8 -*-
"""
upper-keyword.py ------- Change C source keyword which not in comment to UPPER.
Author: Leslie Zhu
Email: [email protected]
Version: 1.0
upper_keyword: read source and output with upper keyword(not in comment)
file_stream: check and read a file line by line
parse_line: parse each line based on status
status: a list with each flag
"""
Usage="""
Usage: python upper_keyword.py infile.c
e.g:
$ python upper_keyword.py [?|-?|-h|--help]
$ python upper_keyword.py FILE1.c FILE2.c FILE3.c [..]
$ cat FILE1.c FILE2.c [..] | python upper_keyword.py
$ python upper_keyword.py
/* test: int a=3;*/
// test: float b=3.0;*/
int
main()
{
int c=1;
return c;
}
^D
/* test: int a=3;*/
// test: float b=3.0;*/
INT
main()
{
INT c=1;
RETURN c;
}
"""
import os,sys
# init status list
# '/' : status_0 = False
# '*' : status_1 = False
# '//': status_2 = False
# '/*': status_3 = False
# '*/': status_4 = False
# not in comment: status_5 = True
status=[False,False,False,False,False,True]
# C89 32 keywords
keywords=['auto','enum','unsigned','break','extern',
'return','void','case','float','short',
'volatile','char','for','signed','while',
'const','goto','sizeof','continue','if',
'static','default','struct','do','int',
'switch','double','long','typedef',
'else','register','union']
# a keyword endswith token
tokens = [" ",";",",","(",")","{","}","\t",'\n']
def parse_line(line=""):
"parse line and determine its status in C source comments,then upper the comments."
outline = ""
global status,keywords,tokens
if status[2]: status[5] = True
status[2] = False
word_flag = False # a flag for mark word in source file
prev_word = "" # init prev word split by blackspace
line = line
length = len(line) - 1
for i,c in enumerate(line):
# update status
if status[5]:
if c == '/':
status=[True,False,False,False,False,False]
elif status[0]:
if c == '*' and not status[2]: status=[False,False,False,True,False,False]
if c == '/' and not status[3]: status=[False,False,True,False,False,False]
elif status[3]:
if status[1] and c != '/': status[2] = False
if c == '*': status=[False,True,False,True,False,False]
if c == '/' and status[1]: status=[False,False,False,False,False,True]
# depends on status
if status[2] or status[3]:
outline += str(c)
elif c in ['/','*']:
outline += str(c)
else:
if c != " " and not word_flag:
word_flag = True
if (c not in tokens and i != length) and word_flag:
prev_word += str(c)
if (c in tokens or i == length) and word_flag:
word_flag = False
if prev_word in keywords:
prev_word = prev_word.upper()
outline += prev_word
prev_word = ""
if (c in tokens or i == length) and not word_flag:
outline += str(c)
return outline
def file_stream(filename=None):
if not os.path.exists(filename):
print "File %s not exists!" % filename
sys.exit(1)
else:
return open(filename).readlines()
def upper_keyword(data=sys.stdin):
"read infile line by line and parse it."
for line in data:
print parse_line(line),
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] in ["?","-?","-h","--help"]:
print Usage
sys.exit(0)
if len(sys.argv) >= 2:
for i in range(1,len(sys.argv)):
upper_keyword(file_stream(sys.argv[i]))
else:
try:
upper_keyword(sys.stdin.readlines())
except (KeyboardInterrupt,EOFError,IOError):
print Usage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment