import re,sys,codecs

transl = {}

_chars = re.compile(r'<!ENTITY (.*) SDATA "(.+)"')
re1 = re.compile(r'&([^;]+);')
re2 = re.compile(r'&#(\d+)(\D)([^;]+);')
re3 = re.compile(r'&(\w+)/([^;]*);')



translation_file = '../../data/BNCchars.translation'

def load_chars(filename = translation_file):
	for line in open(filename):
		m = _chars.match(line)
		if m:
			t = m.group(1).strip()
			transl[ m.group(1).strip() ] = m.group(2).strip()

def _repl_func(match):
	if transl.has_key(match.group(1).strip()):
		return transl[match.group(1).strip()]
	else:
		return '&' + match.group(1) + ';'

def mdash_fun(match):
	return '&mdash;' + match.group(1)

def ndash_fun(match):
	return '&ndash;' + match.group(1)

def frac_fun(match):
	return '&frac' + match.group(1) + ';' + match.group(2)

def formula_fun(match):
	return '&formula;' + match.group(1)

def egr_fun(match):
	return '&Egr;' + match.group(1)

def yacute_fun(match):
	return '&yacute;' + match.group(1)

def agrave_fun(match):
	return '&agrave;' + match.group(1)

def thgr_fun(match):
	return '&thgr;' + match.group(1)

def pound_fun(match):
	return '&pound;' + match.group(1)

def gt_fun(match):
	return '&gt;' + match.group(1)

def lt_fun(match):
	return '&lt;' + match.group(1)

def zgr_fun(match):
	return '&zgr;' + match.group(1)

def bgr_fun(match):
	return '&bgr;' + match.group(1)

def dgr_fun(match):
	return '&dgr;' + match.group(1)

def amp_fun(match):
	return '&amp;' + match.group(1)

def eacute_fun(match):
	return '&eacute;' + match.group(1)

def deg_fun(match):
	return '&deg;' + match.group(1)

def egrave_fun(match):
	return '&egrave;' + match.group(1)

def agr_fun(match):
	return '&agr;' + match.group(1)

def phgr_fun(match):
	return '&phgr;' + match.group(1)

def ngr_fun(match):
	return '&ngr;' + match.group(1)

def rehy_fun(match):
	return '&ngr;' + match.group(1)

def bsol_fun(match):
	return '&bsol;' + match.group(1)

def dollar_fun(match):
	return '&dollar;' + match.group(1)

def lgr_fun(match):
	return '&lgr;' + match.group(1)

def Zgr_fun(match):
	return '&Zgr;' + match.group(1)

def cacute_fun(match):
	return '&cacute;' + match.group(1)

def lsqb_fun(match):
	return '&lsqb;' + match.group(1)

def ohgr_fun(match):
	return '&ohgr;' + match.group(1)

def verbar_fun(match):
	return '&verbar;' + match.group(1)

def pgr_fun(match):
	return '&pgr;' + match.group(1)

def ogr_fun(match):
	return '&ogr;' + match.group(1)

def commat_fun(match):
	return '&commat;' + match.group(1)

mdash_errors = (re.compile(r'&mdash([^;]+);'), mdash_fun)
ndash_errors = (re.compile(r'&ndash([^;]+);'), ndash_fun)
frac_errors = (re.compile(r'&frac(\d\d)([^;]+);'), frac_fun)
formula_errors = (re.compile(r'&formula([^;]+);'), formula_fun)
egr_errors = (re.compile(r'&Egr([^;]+);'), egr_fun)
yacute_errors = (re.compile(r'&yacute([^;]+);'), yacute_fun)
agrave_errors = (re.compile(r'&agrave([^;]+);'), agrave_fun)
thgr_errors = (re.compile(r'&thgr([^;]+);'), thgr_fun)
pound_errors = (re.compile(r'&pound([^;]+);'), pound_fun)
gt_errors = (re.compile(r'&gt([^;]+);'), gt_fun)
lt_errors = (re.compile(r'&lt([^;]+);'), lt_fun)
zgr_errors = (re.compile(r'&zgr([^;]+);'), zgr_fun)
bgr_errors = (re.compile(r'&bgr([^;]+);'), bgr_fun)
dgr_errors = (re.compile(r'&dgr([^;]+);'), dgr_fun)
amp_errors = (re.compile(r'&amp([^;]+);'), amp_fun)
eacute_errors = (re.compile(r'&eacute([^;]+);'), eacute_fun)
deg_errors = (re.compile(r'&deg([^;]+);'), deg_fun)
egrave_errors = (re.compile(r'&egrave([^;]+);'), egrave_fun)
agr_errors = (re.compile(r'&agr([^;]+);'), agr_fun)
phgr_errors = (re.compile(r'&phgr([^;]+);'), phgr_fun)
ngr_errors = (re.compile(r'&ngr([^;]+);'), ngr_fun)
rehy_errors = (re.compile(r'&rehy([^;]+);'), rehy_fun)
bsol_errors = (re.compile(r'&bsol([^;]+);'), bsol_fun)
dollar_errors = (re.compile(r'&dollar([^;]+);'), dollar_fun)
lgr_errors = (re.compile(r'&lgr([^;]+);'), lgr_fun)
Zgr_errors = (re.compile(r'&Zgr([^;]+);'), Zgr_fun)
cacute_errors = (re.compile(r'&cacute([^;]+);'), cacute_fun)
lsqb_errors = (re.compile(r'&lsqb([^;]+);'), lsqb_fun)
ohgr_errors = (re.compile(r'&ohgr([^;]+);'), ohgr_fun)
verbar_errors = (re.compile(r'&verbar([^;]+);'), verbar_fun)
pgr_errors = (re.compile(r'&pgr([^;]+);'), pgr_fun)
ogr_errors = (re.compile(r'&ogr([^;]+);'), ogr_fun)
commat_errors = (re.compile(r'&commat([^;]+);'), commat_fun)

errors = [ mdash_errors, ndash_errors, frac_errors,formula_errors, egr_errors, yacute_errors, agrave_errors, \
		thgr_errors, pound_errors, gt_errors, lt_errors, zgr_errors, bgr_errors, dgr_errors, amp_errors, eacute_errors, \
		deg_errors, egrave_errors, agr_errors, phgr_errors, ngr_errors, rehy_errors, bsol_errors, dollar_errors,\
		lgr_errors, Zgr_errors, cacute_errors, lsqb_errors, ohgr_errors, verbar_errors, pgr_errors, ogr_errors,\
		commat_errors] 

def correct_errors(string):
	for transformation in errors:
		string = transformation[0].sub(transformation[1], string)
	return string
	
def _repl_func_preliminary(match):
	return '&#' + match.group(1) +';' + match.group(2) + match.group(3)
 
def _repl_func_preliminary2(match):
	return '&' + match.group(1) +';/' +  match.group(2)

def handle_bnc_entities(string):
     return re1.sub(_repl_func, re2.sub(_repl_func_preliminary, re3.sub(_repl_func_preliminary2, correct_errors(string) ) ) )

if __name__ == '__main__':
	if len(sys.argv) != 3:
		print "Usage: python bnc_to_std file_in file_out"
	else:
		load_chars()
		out = codecs.open(sys.argv[1], 'w', 'utf8')	
		for line in open(sys.argv[2]):
			out.write(handle_bnc_entities(line))
