-
Notifications
You must be signed in to change notification settings - Fork 114
Expand file tree
/
Copy pathtoken_parser.py
More file actions
157 lines (134 loc) · 4.47 KB
/
Copy pathtoken_parser.py
File metadata and controls
157 lines (134 loc) · 4.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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
# Copyright (c) 2022 Zhendong Peng (pzd17@tsinghua.org.cn)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import string
EOS = "<EOS>"
TN_ORDERS = {
"date": ["year", "month", "day"],
"fraction": ["denominator", "numerator"],
"measure": ["denominator", "numerator", "value"],
"money": ["value", "currency"],
"time": ["noon", "hour", "minute", "second"],
}
EN_TN_ORDERS = {
"date": ["preserve_order", "text", "day", "month", "year"],
"money": ["integer_part", "fractional_part", "quantity", "currency_maj"],
}
ITN_ORDERS = {
"date": ["year", "month", "day", "preserve_order"],
"fraction": ["sign", "numerator", "denominator"],
"measure": ["numerator", "denominator", "value", "units"],
"money": ["currency", "value", "decimal"],
"time": ["hour", "minute", "second", "noon"],
"telephone": ["value"],
"electronic": ["username", "domain", "protocol"],
}
class Token:
def __init__(self, name):
self.name = name
self.order = []
self.members = {}
def append(self, key, value):
self.order.append(key)
self.members[key] = value
def string(self, orders):
output = self.name + " {"
if self.name in orders.keys():
if "preserve_order" not in self.members.keys() or self.members["preserve_order"] != "true":
self.order = orders[self.name]
for key in self.order:
if key not in self.members.keys():
continue
output += ' {}: "{}"'.format(key, self.members[key])
return output + " }"
class TokenParser:
def __init__(self, ordertype="tn"):
if ordertype == "tn":
self.orders = TN_ORDERS
elif ordertype == "itn":
self.orders = ITN_ORDERS
elif ordertype == "en_tn":
self.orders = EN_TN_ORDERS
else:
raise NotImplementedError()
def load(self, input):
assert len(input) > 0
self.index = 0
self.text = input
self.char = input[0]
self.tokens = []
def read(self):
if self.index < len(self.text) - 1:
self.index += 1
self.char = self.text[self.index]
return True
self.char = EOS
return False
def parse_ws(self):
not_eos = self.char != EOS
while not_eos and self.char == " ":
not_eos = self.read()
return not_eos
def parse_char(self, exp):
if self.char == exp:
self.read()
return True
return False
def parse_chars(self, exp):
ok = False
for x in exp:
ok |= self.parse_char(x)
return ok
def parse_key(self):
assert self.char != EOS
assert self.char not in string.whitespace
key = ""
while self.char in string.ascii_letters + "_":
key += self.char
self.read()
return key
def parse_value(self):
assert self.char != EOS
escape = False
value = ""
while self.char != '"':
value += self.char
escape = self.char == "\\"
self.read()
if escape:
escape = False
value += self.char
self.read()
return value
def parse(self, input):
self.load(input)
while self.parse_ws():
name = self.parse_key()
self.parse_chars(" { ")
token = Token(name)
while self.parse_ws():
if self.char == "}":
self.parse_char("}")
break
key = self.parse_key()
self.parse_chars(': "')
value = self.parse_value()
self.parse_char('"')
token.append(key, value)
self.tokens.append(token)
def reorder(self, input):
self.parse(input)
output = ""
for token in self.tokens:
output += token.string(self.orders) + " "
return output.strip()