程序读取字符作为换行符
program reads character as newline
我有一个我一直在制作的编译器代码的简化版本,一个奇怪的事件让我感到困惑。这是简化的代码:
LETTER = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M'
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z']
WHITESPACE = [' ', '\n', '\r', '\v', '\t', '\f']
SYMBOL = [';', ':', ',', '[', ']', '{', '}', '(', ')', '+', '-', '*', '=', '<']
input_file = open('input.txt', 'r')
line_num = 1
def get_token():
global line_num
value = ''
input_char = ''
value = input_file.read(1)
if value in WHITESPACE:
start = line_num
if value == '\n':
line_num += 1
return "whitespace", value, start
elif value in LETTER:
input_char = input_file.read(1)
while input_char != '':
if input_char in LETTER:
value += input_char
elif input_char in SYMBOL or input_char in WHITESPACE:
input_file.seek(input_file.tell() - 1)
return 'id', value, line_num
else:
value += input_char
return 'invalid', value, line_num
input_char = input_file.read(1)
return 'id', value, line_num
elif value in SYMBOL:
return 'symbol', value, line_num
elif value == '':
return None
else:
return 'invalid', value, line_num
while True:
token = get_token()
if token:
print(f"({token[2]}, {token[0]}, {token[1]})")
else:
break
input_file.close()
这是输入文件的内容:
prod;
}
这是我要实现的输出:
(1, id, prod)
(1, symbol, ;)
(1, whitespace,
)
(2, whitespace,
)
(3, symbol, })
但是,这是我得到的输出:
(1, id, prod)
(1, whitespace,
)
(2, whitespace,
)
(3, whitespace,
)
(4, symbol, })
在检查了每个阶段的变量值和文件指针后,我得出的结论是程序确实在识别字符';'。作为换行符,我在其中放置的任何其他 SYMBOL 也是如此。更令人困惑的是,如果我将拳头写成 'prod ;' 或 'prod;;' 或 'prod; ',它会给出正确的输出。这是怎么回事?
您似乎在未提及的限制下工作(即评论中“不允许我使用任何导入的库”)。
你的寻求并不像你那样工作。不要使用 tell
,而是自己跟踪位置:
pos = 0
# handle your own positioning
def get_char_and_pos(f):
"""Reads one character from file, returns character and position"""
global pos
pos += 1
return f.read(1), pos-1
并通过调用您的位置跟踪函数替换 input_file.read(1)
的所有实例:
# sets are faster for 'in' checks
LETTER = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
WHITESPACE = set(" \n\r\v\t\f")
SYMBOL = set(";:,[]{}()+-*=<")
# write demo file
with open("input.txt", "w") as f:
f.write("prod;\n\n}")
input_file = open('input.txt', 'r+')
line_num = 1
def get_token():
global line_num
value = ''
input_char = ''
value, value_pos = get_char_and_pos(input_file) # use function
if value in WHITESPACE:
start = line_num
if value == '\n':
line_num += 1
return "whitespace", value, start
elif value in LETTER:
input_char, value_pos = get_char_and_pos(input_file) # use function
while input_char != '':
if input_char in LETTER:
value += input_char
elif input_char in SYMBOL or input_char in WHITESPACE:
input_file.seek(value_pos) # jump to correct position
return 'id', value, line_num
else:
value += input_char
return 'invalid', value, line_num
input_char, value_pos = get_char_and_pos(input_file) # use function
return 'id', value, line_num
elif value in SYMBOL:
return 'symbol', value, line_num
elif value == '':
return None
else:
return 'invalid', value, line_num
while True:
token = get_token()
if token:
print(f"({token[2]}, {token[0]}, {token[1]})")
else:
break
input_file.close()
输出:
(1, id, prod)
(1, symbol, ;)
(1, whitespace,
)
(2, whitespace,
)
(3, symbol, })
我有一个我一直在制作的编译器代码的简化版本,一个奇怪的事件让我感到困惑。这是简化的代码:
LETTER = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M'
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z']
WHITESPACE = [' ', '\n', '\r', '\v', '\t', '\f']
SYMBOL = [';', ':', ',', '[', ']', '{', '}', '(', ')', '+', '-', '*', '=', '<']
input_file = open('input.txt', 'r')
line_num = 1
def get_token():
global line_num
value = ''
input_char = ''
value = input_file.read(1)
if value in WHITESPACE:
start = line_num
if value == '\n':
line_num += 1
return "whitespace", value, start
elif value in LETTER:
input_char = input_file.read(1)
while input_char != '':
if input_char in LETTER:
value += input_char
elif input_char in SYMBOL or input_char in WHITESPACE:
input_file.seek(input_file.tell() - 1)
return 'id', value, line_num
else:
value += input_char
return 'invalid', value, line_num
input_char = input_file.read(1)
return 'id', value, line_num
elif value in SYMBOL:
return 'symbol', value, line_num
elif value == '':
return None
else:
return 'invalid', value, line_num
while True:
token = get_token()
if token:
print(f"({token[2]}, {token[0]}, {token[1]})")
else:
break
input_file.close()
这是输入文件的内容:
prod;
}
这是我要实现的输出:
(1, id, prod)
(1, symbol, ;)
(1, whitespace,
)
(2, whitespace,
)
(3, symbol, })
但是,这是我得到的输出:
(1, id, prod)
(1, whitespace,
)
(2, whitespace,
)
(3, whitespace,
)
(4, symbol, })
在检查了每个阶段的变量值和文件指针后,我得出的结论是程序确实在识别字符';'。作为换行符,我在其中放置的任何其他 SYMBOL 也是如此。更令人困惑的是,如果我将拳头写成 'prod ;' 或 'prod;;' 或 'prod; ',它会给出正确的输出。这是怎么回事?
您似乎在未提及的限制下工作(即评论中“不允许我使用任何导入的库”)。
你的寻求并不像你那样工作。不要使用 tell
,而是自己跟踪位置:
pos = 0
# handle your own positioning
def get_char_and_pos(f):
"""Reads one character from file, returns character and position"""
global pos
pos += 1
return f.read(1), pos-1
并通过调用您的位置跟踪函数替换 input_file.read(1)
的所有实例:
# sets are faster for 'in' checks
LETTER = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
WHITESPACE = set(" \n\r\v\t\f")
SYMBOL = set(";:,[]{}()+-*=<")
# write demo file
with open("input.txt", "w") as f:
f.write("prod;\n\n}")
input_file = open('input.txt', 'r+')
line_num = 1
def get_token():
global line_num
value = ''
input_char = ''
value, value_pos = get_char_and_pos(input_file) # use function
if value in WHITESPACE:
start = line_num
if value == '\n':
line_num += 1
return "whitespace", value, start
elif value in LETTER:
input_char, value_pos = get_char_and_pos(input_file) # use function
while input_char != '':
if input_char in LETTER:
value += input_char
elif input_char in SYMBOL or input_char in WHITESPACE:
input_file.seek(value_pos) # jump to correct position
return 'id', value, line_num
else:
value += input_char
return 'invalid', value, line_num
input_char, value_pos = get_char_and_pos(input_file) # use function
return 'id', value, line_num
elif value in SYMBOL:
return 'symbol', value, line_num
elif value == '':
return None
else:
return 'invalid', value, line_num
while True:
token = get_token()
if token:
print(f"({token[2]}, {token[0]}, {token[1]})")
else:
break
input_file.close()
输出:
(1, id, prod)
(1, symbol, ;)
(1, whitespace,
)
(2, whitespace,
)
(3, symbol, })