1 /******************************************************************************
2 *
3 * Copyright (C) 2006, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * ID: genlex 18.10.06 0.0.A.
11 *
12 * Author: Alexey Krivonogov ( gentee )
13 *
14 * Summary: This program creates tables for lexical analizer. It gets a
15 wwwww wwwww
16 *
17 ******************************************************************************/
18
19 include
20 {
21 $"..\..\lib\gt\gt.g"
22 }
23
24 method uint hash.gettype
25 {
26 return this.itype
27 }
28
29 operator hash =( hash left, collection right )
30 {
31 uint i
32
33 while i < *right - 1
34 {
35 if right.gettype( i ) != str : break
36 if left.itype == str
37 {
38 left->hash of str[ right[ i ]->str ] = right[ ++i ]->str
39 }
40 else : left[ right[ i ]->str ] = right[ ++i ]
41
42 i++
43 }
44 return left
45 }
46
47 method buf buf.generatelex( gtitem gti, hash defines )
48 {
49 uint count icmd // latest custom command
50 // gtitems gtis
51 hash lexcmd lexflag lexstate
52
53 lexflag.ignorecase()
54 lexcmd.ignorecase()
55
56 lexcmd = %{ "STOP" , 0xFF000000, "OK", 0xFE000000, "SKIP", 0xFD000000,
57 "GTNAME", 0xFC000000, "STRNAME", 0xFB000000, "EXPR", 0xFA000000 }
58 lexflag = %{ "itstate" , 0x0001, "itcmd", 0x0002, "pos" , 0x0004,
59 "stay" , 0x0008, "try" , 0x0010, "ret" , 0x0020,
60 "value" , 0x0040, "push" , 0x0080, "pop" , 0x0100,
61 "pushli" , 0x0200, "popli", 0x0400, "multi", 0x0800,
62 "hexmulti", 0x0800, "keyword", 0x1000, "new", 0x2000,
63 "pair", 0x4000 }
64
65 subfunc uint getcsf( gtitem gti ) // Get state cmd and flags
66 {
67 uint ret
68 str state
69
70 foreach curl, lexflag.keys
71 {
72 if gti.find( curl ) : ret |= lexflag[ curl ]
73 }
74 if *gti.get( "state", state )
75 {
76 if !lexstate.find( state )
77 {
78 congetch( "Cannot find \(state) state!" )
79 }
80 ret |= lexstate[ state ] << 16
81 if gti.find( "itstate" ) : defines[ state ] = ret & 0xFF0000
82 }
83 if *gti.get( "cmd", state )
84 {
85 if !lexcmd.find( state ) : lexcmd[ state ] = ( ++icmd ) << 24
86 ret |= lexcmd[ state ]
87 if gti.find( "itcmd" ) : defines[ state ] = ret & 0xFF000000
88 }
89 if *gti.get( "trycmd", state )
90 {
91 if !lexstate.find( state )
92 {
93 congetch( "Cannot find \(state) state!" )
94 }
95 ret |= lexstate[ state ] << 24
96 }
97 return ret
98 }
99 subfunc hexchars( str chars )
100 {
101 uint i
102 str stemp
103
104 while i < *chars
105 {
106 str s
107
108 stemp.appendch( uint("0x\( s.substr( chars, i, 2 ))"))
109 i += 2
110 }
111 chars = stemp
112 }
113 // Reading all states in lexstate and numerate them
114 foreach cur, gti
115 {
116 cur as gtitem
117 if cur.find( "skip" ) || cur.comment : continue
118 lexstate[ cur.name ] = ++count
119 }
120 this += count
121 // Main processing
122 foreach curi, gti
123 {
124 uint count offcount
125 // gtitems gtsub
126 curi as gtitem
127
128 if curi.find( "skip" ) || curi.comment : continue
129 offcount = *this
130 this += *curi
131 this += getcsf( curi )
132
133 foreach cursub, curi
134 {
135 uint chars i
136 str sch
137
138 cursub as gtitem
139 if cursub.comment : continue
140
141 count++
142 if cursub.find( "lespace" ) : chars = 0x0120
143 elif cursub.find( "name" ) : chars = 0x4100
144 elif cursub.find( "numname" ) : chars = 0x3000
145 elif cursub.find( "numhex" ) : chars = 0x5800
146 elif cursub.find( "multi" )
147 {
148 cursub.get( "multi", sch )
149 fornum i = 0, *sch : chars |= sch[i] << ( 8 * i )
150 }
151 elif cursub.find( "hexmulti" )
152 {
153 cursub.get( "hexmulti", sch )
154 hexchars( sch )
155 fornum i = 0, *sch : chars |= sch[i] << ( 8 * i )
156 }
157 elif cursub.find( "range" )
158 {
159 cursub.get( "range", sch )
160 chars |= ( sch[0] << 8 ) | sch[1]
161 }
162 elif cursub.find( "hexrange" )
163 {
164 cursub.get( "hexrange", sch )
165 hexchars( sch )
166 chars |= ( sch[0] << 8 ) | sch[1]
167 }
168 sch.clear()
169
170 if !*cursub.get( "ch", sch )
171 {
172 if *cursub.get( "hexch", sch ) : hexchars( sch )
173 }
174 if *sch
175 {
176 if chars
177 {
178 fornum i = 0, *sch : chars |= sch[i] << ( 8 * ( i + 2 ))
179 }
180 else
181 {
182 chars = sch[0] + ( sch[0] << 8 )
183 fornum i = 1, *sch : chars |= sch[i] << ( 8 * ( i + 1 ))
184 }
185 }
186 this += chars
187 this += getcsf( cursub )
188 // print("\(cursub.name) = \( *cursub ) \(hex2stru( "", getcsf( cursub )))\n")
189 }
190 ( this.ptr() + offcount )->uint = count
191 // print("\(curi.name) = \( *curi ) \(hex2stru( "", getcsf( curi )))\n")
192 }
193 return this
194 }
195
196 text header( str name )
197 /******************************************************************************
198 *
199 * Copyright (C) 2006, The Gentee Group. All rights reserved.
200 * This file is part of the Gentee open source project <http://www.gentee.com>.
201 *
202 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
203 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
204 * ACCEPTANCE OF THE AGREEMENT.
205 *
206 * lex\(name) \{
207 str sdate
208 datetime dt
209 getdatetime( dt.gettime(), sdate, 0->str )
210 @sdate
211 }
212 *
213 * Author: Generated with 'lextbl' program
214 *
215 * Description: This file contains a lexical table for the lexical analizer.
216 *
217 ******************************************************************************/
218 \!
219
220 text gout( buf out, str defout keyout name )
221 \@header( name )
222
223 define
224 {
225 // States
226 \(defout)
227 // Keywords
228 \(keyout)
229 }
230
231 global
232 {
233 buf lex\(name) = '\\h4 \{
234 uint i
235 fornum i, *out >> 2
236 {
237 @" "//0x"
238 this.hexu((out.ptr() + ( i << 2 ))->uint )
239 if ( i & 7 ) == 7 : @"\l"
240 }
241 }'
242 }
243 \!
244
245 text cout( buf out, str name )
246 \@header( name )
247 #include "lextbl.h"
248
249 const uint lex\(name)[] = { \{
250 uint i
251 fornum i, *out >> 2
252 {
253 @"0x"
254 this.hexu( (out.ptr() + ( i << 2 ))->uint )
255 @","//0x"
256 if ( i & 7 ) == 7 : @"\l"
257 }
258 }
259 };
260 \!
261
262 text hout( buf out, str defout keyout name )
263 \@header( name )
264 #ifndef _LEX\(name.upper())_
265 #define _LEX\( name )_
266
267 #ifdef __cplusplus
268 extern "C" {
269 #endif // __cplusplus
270
271 // States
272 \(defout)
273 // Keywords
274 \(keyout)
275
276 #ifdef __cplusplus
277 }
278 #endif // __cplusplus
279
280 #endif // _LEX\( name )_
281 \!
282
283 func generatelex( str name )
284 {
285 uint gti keyid gtk
286 gt igt
287 buf out kout
288 str prefix stemp sout gdefout gkeyout gfile cfile cdefout ckeyout
289 hash defines keywords
290
291 igt.read( "\(name).gt" )
292 gti as igt.find( name )
293 gti.get( "prefix", prefix )
294 gti.get( "gout", gfile )
295 gti.get( "cout", cfile )
296
297 gtk as gti.findrel( "/keywords" )
298 if >k
299 {
300 kout += byte( *gtk )
301 kout += byte( ?( gtk.find( "ignore" ), 0x01, 0 ))
302
303 foreach curk, gtk
304 {
305 uint i
306 arrstr names
307 curk as gtitem
308
309 keyid = curk.getuint( "id" )
310 curk.value.split( names, ' ', $SPLIT_NOSYS )
311 // kout += ushort( *names )
312 kout += keyid
313 fornum i, *names
314 {
315 keywords[ names[i]] = keyid
316 kout += names[ i ]
317 if *gfile
318 {
319 gkeyout += "KEY_\(names[i].upper()) = 0x\( hex2stru(
320 keyid++)) \l"
321 }
322 if *cfile
323 {
324 ckeyout += "#define KEY_\(names[i].upper()) 0x\( hex2stru(
325 keyid++)) // \( keyid - 1 )\l"
326 }
327 }
328 kout += byte( 0 )
329 }
330 }
331 else : kout += byte( 0 )
332 out.generatelex( gti, defines )
333 foreach curd, defines.keys
334 {
335 str comment
336
337 igt.get( ?( defines[ curd ] < 0x01000000, "\(name)/\(curd)",
338 "\(name)/commands/\(curd)" ), "comment", comment )
339 if *gfile
340 {
341 gdefout += "\(prefix)\(curd) = 0x\(hex2stru(
342 defines[ curd ])) // \(comment) \l"
343 }
344 if *cfile
345 {
346 cdefout += "#define \(prefix)\(curd) 0x\(hex2stru(
347 defines[ curd ])) // \(comment) \l"
348 }
349 }
350 out += kout
351 out += 0 // add zero
352 if *gti.get( "binout", stemp ) : out.write( stemp )
353 if *gfile
354 {
355 sout@gout( out, gdefout, gkeyout, name )
356 sout.write( gfile )
357 }
358 if *cfile
359 {
360 sout.clear()
361 sout@cout( out, name )
362 sout.write( cfile )
363 sout.clear()
364 sout@hout( out, cdefout, ckeyout, name )
365 sout.write( cfile.fsetext( cfile, "h" ) )
366 }
367 }
368