SICP 的 sqlite_shell.py 非常神奇的无法处理 /* */ 中的 ;,会产生报错:
sqlite> /*;*/;
near "*": syntax error
阅读 sqlite_shell.py 会发现,sql_commands 不认为 /* 是一个 delimeter,因此出现问题:
sqlite_shell.py
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 | def sql_commands(read_line):
delims = ['"', "'", ';', '--']
counter = 0
in_string = None
j = i = 0
prev_line = None
line = None
concat = []
while True:
if line is None:
while True: # process preprocessor directives
counter += 1
not_in_the_middle_of_any_input = not in_string and i == j and all(map(lambda chunk_: len(chunk_) == 0, concat))
line = read_line(counter - 1, not_in_the_middle_of_any_input, prev_line)
empty_string = line[:0] if line is not None else line
prev_line = line
if not line:
break
if not_in_the_middle_of_any_input and line.startswith("."):
yield line
line = None
else:
break
if not line:
break
j = i = 0
if j < len(line):
(j, delim) = min(map(lambda pair: pair if pair[0] >= 0 else (len(line), pair[1]), map(lambda d: (line.find(d, j), d), in_string or delims if in_string != '--' else "\n")))
if i < j: concat.append(line[i:j]); i = j
if not in_string:
if j < len(line):
j += len(delim)
if delim == ';':
i = j
concat.append(line[j : j + len(delim)]) # ensure delimeter is the same type as the string (it may not be due to implicit conversion)
# Eat up any further spaces until a newline
while j < len(line):
delim = line[j:j+1]
if not delim.isspace(): break
j += 1
if delim == "\n": break
if i < j: concat.append(line[i:j]); i = j
yield empty_string.join(concat)
del concat[:]
else:
in_string = delim
else:
if j < len(line):
ch = line[j:j+1]
assert ch == in_string or in_string == '--'
j += 1
i = j
concat.append(ch)
in_string = None
else:
if i < j: concat.append(line[i:j]); i = j
line = None
|
稍微改一下就能修复,主要是把 /* 加到 delimeters 里,然后修改后续逻辑。
sqlite_shell.py
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 | def sql_commands(read_line):
delims = ['"', "'", ';', '--', '/*']
counter = 0
in_string = None
j = i = 0
prev_line = None
line = None
concat = []
while True:
if line is None:
while True: # process preprocessor directives
counter += 1
not_in_the_middle_of_any_input = not in_string and i == j and all(map(lambda chunk_: len(chunk_) == 0, concat))
line = read_line(counter - 1, not_in_the_middle_of_any_input, prev_line)
empty_string = line[:0] if line is not None else line
prev_line = line
if not line:
break
if not_in_the_middle_of_any_input and line.startswith("."):
yield line
line = None
else:
break
if not line:
break
j = i = 0
if j < len(line):
if in_string is None:
targets = delims
elif in_string == '--':
targets = ["\n"]
elif in_string == '/*':
targets = ["*/"]
else:
targets = [in_string]
(j, delim) = min(map(lambda pair: pair if pair[0] >= 0 else (len(line), pair[1]), map(lambda d: (line.find(d, j), d), targets)))
if i < j: concat.append(line[i:j]); i = j
if not in_string:
if j < len(line):
j += len(delim)
if delim == ';':
i = j
concat.append(line[j : j + len(delim)]) # ensure delimeter is the same type as the string (it may not be due to implicit conversion)
# Eat up any further spaces until a newline
while j < len(line):
delim = line[j:j+1]
if not delim.isspace(): break
j += 1
if delim == "\n": break
if i < j: concat.append(line[i:j]); i = j
yield empty_string.join(concat)
del concat[:]
else:
in_string = delim
else:
if j < len(line):
j += len(delim)
i = j
concat.append(line[j-len(delim):j])
in_string = None
else:
if i < j: concat.append(line[i:j]); i = j
line = None
|
当然,我也不知道我改对了没有。。仅供参考。