10 class SyntaxError(Exception):
13 class DBParser(object):
17 def _syntax_error(self, txt=None):
18 txt = txt and ' (%s)' % txt or ''
19 raise SyntaxError("Syntax error in line %d%s" % (self._lineno, txt))
22 sys.stderr.write("Warning (line %d): %s\n" % (self._lineno, txt))
24 def _parse_band_def(self, bname, banddef):
27 freqs, line = line.split(',', 1)
32 flags = [f.upper() for f in line.split(',') if f]
35 freqs, bw = freqs.split('@')
41 start, end = freqs.split('-')
45 self._syntax_error("band must have frequency range")
49 if not f in power_flags:
50 self._syntax_error("Invalid band flag")
53 b = (start, end, bw, fl)
54 self._banddup[bname] = bname
55 if b in self._bandrev:
56 self._warn('Duplicate band definition ("%s" and "%s")' % (
57 bname, self._bandrev[b]))
58 self._banddup[bname] = self._bandrev[b]
59 self._bands[bname] = b
60 self._bandrev[b] = bname
62 def _parse_band(self, line):
64 bname, line = line.split(':', 1)
66 self._syntax_error("'band' keyword must be followed by name")
68 self._syntax_error("band name must be followed by colon")
70 self._parse_band_def(bname, line)
72 def _parse_power(self, line):
74 pname, line = line.split(':', 1)
76 self._syntax_error("'power' keyword must be followed by name")
78 self._syntax_error("power name must be followed by colon")
86 max_eirp_ptp) = line.split(',')
87 max_ant_gain = float(max_ant_gain)
88 max_ir_ptmp = float(max_ir_ptmp)
89 max_ir_ptp = float(max_ir_ptp)
90 max_eirp_ptmp = float(max_eirp_ptmp)
91 max_eirp_ptp = float(max_eirp_ptp)
93 self._syntax_error("invalid power data")
97 if not environ in ('I', 'O', ' '):
98 self._syntax_error("Invalid environment specifier")
100 p = (environ, max_ant_gain, max_ir_ptmp,
101 max_ir_ptp, max_eirp_ptmp, max_eirp_ptp)
102 self._powerdup[pname] = pname
103 if p in self._powerrev:
104 self._warn('Duplicate power definition ("%s" and "%s")' % (
105 pname, self._powerrev[p]))
106 self._powerdup[pname] = self._powerrev[p]
107 self._power[pname] = p
108 self._powerrev[p] = pname
110 def _parse_country(self, line):
112 cname, line = line.split(':', 1)
114 self._syntax_error("'country' keyword must be followed by name")
116 self._syntax_error("extra data at end of country line")
118 self._syntax_error("country name must be followed by colon")
120 if not cname in self._countries:
121 self._countries[cname] = []
122 self._current_country = self._countries[cname]
123 self._current_country_name = cname
125 def _parse_country_item(self, line):
127 bname, pname = line.split(',', 1)
129 self._syntax_error("country definition must have band name")
131 self._syntax_error("country definition must have power name")
133 self._syntax_error("country definition must have band and power names")
134 if not bname in self._bands:
135 self._syntax_error("band does not exist")
136 if not pname in self._power:
137 self._syntax_error("power does not exist")
138 bname = self._banddup[bname]
139 pname = self._powerdup[pname]
140 # de-duplicate so binary database is more compact
141 self._bands_used[bname] = True
142 self._power_used[pname] = True
144 if tup in self._current_country:
145 self._warn('Rule "%s, %s" added to "%s" twice' % (
146 bname, pname, self._current_country_name))
148 self._current_country.append((bname, pname))
151 self._current_country = None
155 self._bands_used = {}
156 self._power_used = {}
166 line = line.replace(' ', '').replace('\t', '')
167 line = line.split('#')[0]
170 if line[0:4] == 'band':
171 self._parse_band(line[4:])
172 self._current_country = None
173 elif line[0:5] == 'power':
174 self._parse_power(line[5:])
175 self._current_country = None
176 elif line[0:7] == 'country':
177 self._parse_country(line[7:])
178 elif self._current_country is not None:
179 self._parse_country_item(line)
181 self._syntax_error("Expected band, power or country definition")
184 for k, v in self._countries.iteritems():
186 for k in k.split(','):
187 countries[k] = tuple(v)
189 for k, v in self._bands.iteritems():
190 if k in self._bands_used:
193 # we de-duplicated, but don't warn again about the dupes
194 if self._banddup[k] == k:
195 self._warn('Unused band definition "%s"' % k)
197 for k, v in self._power.iteritems():
198 if k in self._power_used:
201 # we de-duplicated, but don't warn again about the dupes
202 if self._powerdup[k] == k:
203 self._warn('Unused power definition "%s"' % k)
204 return bands, power, countries
206 def create_rules(countries):
208 for c in countries.itervalues():
213 def create_collections(countries):
215 for c in countries.itervalues():
220 if __name__ == '__main__':
223 b, p, c = p.parse(sys.stdin)
227 print create_rules(c)
228 print create_collections(c)