1cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi#!lua
2cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-----------------------------------------------------------------------------
3cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- lua script picoloadphones.lua --- creates pkb containing phones table.
4cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi--
5cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- Copyright (C) 2009 SVOX AG. All rights reserved.
6cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-----------------------------------------------------------------------------
7cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
8cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- load pico phones src file and create phones pkb file
9cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
10cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- accepted syntax:
11cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- - parses line of the following format:
12cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi--   :SYM "<sym>" :PROP mapval = <uint8> { , <propname> = <int> }
13cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- - initial '!' and trailing '!.*' are treated as comments, no '[]'
14cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
15cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
16cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi--- valid property names
17cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivipropnames = {mapval=0, vowel=0, diphth=0, glott=0, nonsyllvowel=0, syllcons=0}
18cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi--- valid property names (that may occur once only)
19cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviupropnames = {primstress=0, secstress=0, syllbound=0, wordbound=0, pause=0}
20cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
21cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
22cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- init
23cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviif #arg ~= 2 then
24cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  print("*** error: wrong number of arguments, must be 2"); return
25cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviend
26cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivilocal infile = io.open(arg[1], "r")
27cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviif not infile then
28cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  print("*** error: could not open input file: " .. arg[1]); return
29cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviend
30cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivilocal outfile = io.open(arg[2], "wb")
31cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviif not outfile then
32cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  print("*** error: could not open output file: " .. arg[2]); return
33cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviend
34cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
35cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
36cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- tables
37cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi--- table with symbol name keys (not really used currently)
38cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivilocal syms = {}
39cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi--- table with symbol name number keys (specified with property mapval)
40cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivilocal symnrs = {}
41cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi--- array of symbol name numer keys used (to check for unique mapvals)
42cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivilocal symnrsused = {}
43cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
44cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
45cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- parse input file, build up syms and symnrs tables
46cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivifor line in infile:lines() do
47cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  if string.match(line, "^%s*!.*$") or string.match(line, "^%s*$") then
48cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    -- discard comment-only lines
49cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  else
50cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    cline = string.gsub(line, "^%s*", "")
51cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    -- get :SYM
52cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    sym = string.match(cline, "^:SYM%s+\"([^\"]-)\"%s+")
53cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    if not sym then
54cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      sym = string.match(cline, "^:SYM%s+'([^']-)'%s+")
55cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    end
56cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    if sym then
57cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      cline = string.gsub(cline, "^:SYM%s+['\"].-['\"]%s+", "")
58cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      -- get :PROP and mapval prop/propval
59cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      propval = string.match(cline, "^:PROP%s+mapval%s*=%s*(%d+)%s*")
60cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      if propval then
61cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	cline = string.gsub(cline, "^:PROP%s+mapval%s*=%s*%d+%s*", "")
62cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	-- construct props table and add first mapval property
63cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	props = {mapval = tonumber(propval)}
64cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	symnr = tonumber(propval)
65cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	if not symnrsused[symnr] then
66cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	  symnrsused[symnr] = true
67cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	else
68cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	  io.write("*** error: mapval values must be unique, ", symnr, "\n")
69cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	  print("line: ", line); return
70cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	end
71cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	-- check if remaining part are comments only
72cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	cline = string.gsub(cline, "^!.*", "")
73cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	while (#cline > 0) do
74cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	  -- try to get next prop/propval and add to props
75cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	  prop, propval = string.match(cline, "^,%s*(%w+)%s*=%s*(%d+)%s*")
76cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	  if prop and propval then
77cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	    cline = string.gsub(cline, "^,%s*%w+%s*=%s*%d+%s*", "")
78cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	    props[prop] = tonumber(propval)
79cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	  else
80cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	    print("*** error: syntax error in property list")
81cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	    print("line: ", line); return
82cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	  end
83cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	  -- cleanup if only comments remaining
84cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	  cline = string.gsub(cline, "^!.*", "")
85cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	end
86cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      else
87cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	print("*** error: no mapval property found")
88cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	print("line: ", line); return
89cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      end
90cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      syms[sym] = props
91cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      symnrs[symnr] = props
92cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    else
93cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      print("*** error: no symbol found")
94cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      print("line: ", line)
95cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      return
96cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    end
97cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  end
98cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviend
99cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
100cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
101cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- check syms and symnrs
102cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
103cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivifunction checksymtable (st)
104cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  for s in pairs(propnames) do propnames[s] = 0 end
105cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  for s in pairs(upropnames) do upropnames[s] = 0 end
106cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  for s, p in pairs(st) do
107cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    for prop, propval in pairs(p) do
108cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      if not propnames[prop] and not upropnames[prop] then
109cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	io.write("*** error: invalid property name '", prop, "'\n")
110cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	return
111cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      end
112cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      if propnames[prop] then
113cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	propnames[prop] = propnames[prop] + 1
114cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      elseif upropnames[prop] then
115cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	upropnames[prop] = upropnames[prop] + 1
116cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      end
117cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    end
118cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    for prop, propval in pairs(upropnames) do
119cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      if propval > 1  then
120cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi	io.write("*** error: property '", prop, "' must be unique\n"); return
121cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi      end
122cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    end
123cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  end
124cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviend
125cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
126cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivichecksymtable(syms)
127cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivichecksymtable(symnrs)
128cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
129cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
130cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- get IDs of unique specids
131cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
132cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivispecid = {}
133cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivifor i = 1, 8 do specid[i] = 0 end
134cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivifor s, pl in pairs(symnrs) do
135cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  if pl["primstress"] then    specid[1] = pl["mapval"]
136cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  elseif pl["secstress"] then specid[2] = pl["mapval"]
137cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  elseif pl["syllbound"] then specid[3] = pl["mapval"]
138cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  elseif pl["pause"] then     specid[4] = pl["mapval"]
139cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  elseif pl["wordbound"] then specid[5] = pl["mapval"]
140cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  end
141cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviend
142cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
143cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
144cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- write out Phones pkb
145cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
146cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivifunction encodeprops (n)
147cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  rv = 0
148cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  pl = symnrs[n]
149cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  if pl then
150cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    if pl["vowel"] then rv = 1 end
151cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    if pl["diphth"]then rv = rv + 2 end
152cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    if pl["glott"] then rv = rv + 4 end
153cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    if pl["nonsyllvowel"] then rv = rv + 8 end
154cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi    if pl["syllcons"] then rv = rv + 16 end
155cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  end
156cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  return rv
157cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviend
158cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
159cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivifor i=1,8 do
160cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  if specid[i] == 0 then outfile:write("\0")
161cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  else outfile:write(string.format("%c", specid[i]))
162cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  end
163cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviend
164cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivifor i = 0, 255 do
165cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  nr = encodeprops(i)
166cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  if nr == 0 then outfile:write("\0")
167cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  else outfile:write(string.format("%c", nr))
168cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi  end
169cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviend
170cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
171cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
172cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- tini
173cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
174cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Triviinfile:close()
175cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivioutfile:close()
176cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi
177cb1b5f35225a63d1efdd595955e6455e718b1698Jean-Michel Trivi-- end
178