扫描器类的设计
【问题描述】
熟悉并实现一个简单的扫描器,设计扫描器的自动机;设计翻译、生成Token的算法;编写代码并上机调试运行通过。
-
-
扫描器可识别的单词包括:关键字、界符、标识符和常数(常数包括如:123 123.567 0.567 12.34e+23 ......);
-
要求常整数输出按十进制输出(测试数据中只有16进制与10进制整数),浮点数考虑到精度问题按输入格式输出(测试数据只有10进制浮点数)。同时使用科学计数法的数字都是浮点数。为降低难度,样例3给出一种边界情况供大家调试。
-
在面对诸如"a+++++b"以及"a+++b"这种丧心病狂的输入时,界符匹配按照从左向右贪心匹配最长界符的策略进行匹配。
-
-
判断字符常量及字符串常量单词,将字符和字符串常量分别保存进单独的常量表CT、ST。例如’a’、”OK”;同时字符串与字符常量均不考虑转义字符("\"和带"\"的都不考虑)。
-
可以识别简单的词法错误主要形式为’sdddd’、1.sdasf等,尚未定义的单词等。
-
其中关键字表、界符表、标识符表、常整数表、常实数表、字符表、字符串表如下:(表中除关键词与界符表的表都可以接着编号继续扩展)
【输入形式】一行带空格的输入。其中关于数字,对于整型保证仅需考虑10进制与16进制数据,对于浮点型保证仅需考虑10进制数据。
【输出形式】
-
相应单词的Token序列;
-
标识符表,整数表,实数表,字符表,字符串表
-
如果错误则输出"ERROR"。
【样例输入】
样例1输入: 120+10.3*12.3e-1; 样例2输入: a="xyz"; 样例3输入: int a=12.1; float b=15e2, c=0x15e2; 样例4输入: int a='label';
【样例输出】
样例1输出: Token :(C1 1)(P 8)(C2 1)(P 9)(C2 2)(P 13) I : C1 :120 C2 :10.3 12.3e-1 CT : ST : 样例2输出: Token :(I 1)(P 11)(ST 1)(P 13) I :a C1 : C2 : CT : ST :xyz 样例3输出: Token :(K 1)(I 1)(P 11)(C2 1)(P 13)(K 4)(I 2)(P 11)(C2 2)(P 12)(I 3)(P 11)(C1 1)(P 13) I :a b c C1 :5602 C2 :12.1 15e2 CT : ST : 样例4输出: ERROR
【样例说明】
样例3中,0x15e2看起来是一个使用科学计数法的浮点数,但实际上他是一个16进制整型。其中e并不代表指数而是代表十进制下的数字14。这也是为什么16进制下不能使用e来进行科学计数的原因。扩展阅读:Floating-point literal - cppreference.com c - Why does hexadecimal floating point need to have a specified exponent? - Stack Overflow
【评分标准】
import re
import sys
K = ['','int','void','break','float','while','do','struct','const','case','for','return','if','default','else']
P = ['','-','/','(',')','==','<=','<','+','*','>','=',',',';','++','{','}']
I = ['']
C1 = ['']
C2 = ['']
CT = ['']
ST = ['']
P_first = ['=','<','+']
sep = [' ','\n','\t',"'",'"']
def in_p_sep(ch):
return ch in P or ch in sep
def print_error():
print("ERROR")
def is_C1(str1):
if re.match(r'^[0-9]+$',str1):
return 1
elif re.match(r'^0x[0-9a-zA-Z]+$',str1):
return 2
else:
return 0
def is_C2(str1):
return bool(re.match(r'^[0-9]+(?:\.[0-9]+)?(?:e[+-]?[0-9]+)?$', str1))
def is_CT(str1):
return bool(re.match(r"^'[a-zA-Z0-9]$",str1))
def is_ST(str1):
return bool(re.match(r'^\".*$',str1))
def is_I(str1):
return bool(re.match(r'^[a-zA-Z_]\w*$',str1))
def judge(str1, Token):
if str1 in K:
num = K.index(str1)
Token += f'(K {num})'
elif str1 in C1:
num = C1.index(str1)
Token += f'(C1 {num})'
elif str1 in C2:
num = C2.index(str1)
Token += f'(C2 {num})'
elif str1 in CT:
num = CT.index(str1)
Token += f'(CT {num})'
elif str1 in ST:
num = ST.index(str1)
Token += f'(ST {num})'
elif str1 in P:
num = P.index(str1)
Token += f'(P {num})'
else:
if is_C1(str1) == 1:
C1.append(str1)
num = C1.index(str1)
Token += f'(C1 {num})'
elif is_C1(str1) == 2:
C1.append(str(int(str1, 16)))
num = C1.index(str(int(str1, 16)))
Token += f'(C1 {num})'
elif is_C2(str1):
C2.append(str1)
num = C2.index(str1)
Token += f'(C2 {num})'
elif is_CT(str1):
CT.append(str1[1:])
num = CT.index(str1[1:])
Token += f'(CT {num})'
elif is_ST(str1):
ST.append(str1[1:])
num = ST.index(str1[1:])
Token += f'(ST {num})'
elif is_I(str1):
I.append(str1)
num = I.index(str1)
Token += f'(I {num})'
else:
print_error()
sys.exit()
return Token
def main():
Token = "Token :"
a = str(input())
flag, flag2, flag3 = 0, 0, 0
str1, str2 = "", ""
for i in a:
if in_p_sep(i):
if i == '-' and flag2 == 2:
str1 += i
continue
elif i in sep:
if i in ["'", '"']:
flag = 1 if flag == 0 else 0
if bool(str1) and flag == 0:
Token = judge(str1, Token)
str1 = ""
flag2 = 0
if flag == 0:
if i in P and flag3 == 1:
if not judge(str2+i, Token):
Token = judge(str2, Token)
Token = judge(i, Token)
else:
Token = judge(str2+i, Token)
str2 = ""
flag3 = 0
elif i in P_first and flag3 == 0:
flag3 = 1
str2 += i
elif i in P and i not in P_first and flag3 == 0:
Token = judge(i, Token)
else:
str1 += i
else:
if i == 'e' and flag2 != 1:
flag2 = 2
elif str1 == '0x':
flag2 = 1
elif flag == 1:
flag = 4
elif flag == 2:
flag = 4
elif flag == 2 and i != 'e':
flag == 0
if flag3 == 1:
Token = judge(str2, Token)
str2 = ""
flag3 = 0
str1 += i
if bool(str1):
Token = judge(str1, Token)
str1 = ""
print(Token)
print("I :", end="")
for keyword in I[1:]:
print(keyword, end=" ")
print("\nC1 :", end="")
for keyword in C1[1:]:
print(keyword, end=" ")
print("\nC2 :", end="")
for keyword in C2[1:]:
print(keyword, end=" ")
print("\nCT :", end="")
for keyword in CT[1:]:
print(keyword, end=" ")
print("\nST :", end="")
for keyword in ST[1:]:
print(keyword, end=" ")
if __name__ == "__main__":
main()