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: gtprocess 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 description in gt format and generate .g and *.c sourse files with the
16 according lexical tables.
17 *
18 ******************************************************************************/
19
20 //include : "lexgtdo.g"
21
22 define
23 {
24 gt_OUTPUT = 0 // Output items as it
25 gt_TEST = 1 // Try to detect macro
26 gt_SKIP = 2 // Skip the output after procfail
27 }
28
29 method str gtitem.process( str in ret, arrstr pars )
30 {
31 uint off start prev mode initoff end
32 arrout out
33 // lex ilex
34 // uint lex
35 uint curgti last quotes calltext
36 str value
37 arrstr params
38
39 subfunc procfail
40 {
41 mode = $gt_SKIP
42 while initoff < off
43 {
44 uint li
45
46 li as initoff->lexitem
47
48 ret.append( start + li.pos, li.len )
49 initoff += sizeof( lexitem )
50 }
51 off -= sizeof( lexitem )
52 }
53 if &pars && *pars
54 {
55 uint i
56 fornum i, *pars
57 {
58 str stemp
59 this.process( pars[i], stemp, 0->arrstr )
60 pars[i] = stemp
61 }
62 }
63
64 out.isize = sizeof( lexitem )
65 // lex = lex_init( 0, lexgtdo_.ptr())
66 // gentee_lex( in->buf, lex, out )
67 // gentee_lex( in->buf, this.maingt->gt.lexdo, out )
68 gentee_lex( &in, this.maingt->gt.lexdo, &out )
69
70 off = out.data.ptr()
71 start = in.ptr()
72 end = out.data.ptr() + *out * sizeof( lexitem )
73 while off < end
74 {
75 uint li
76
77 li as off->lexitem
78 // print("TYpe = \( hex2stru("", li.ltype )) Off=\(li.pos) len = \(li.len)\n")
79
80 switch li.ltype
81 {
82 case $GTDO_TEXT
83 {
84 if mode == $gt_TEST : procfail()
85 }
86 case $GTDO_HEX
87 {
88 if mode == $gt_TEST : procfail()
89 else
90 {
91 ret.appendch( uint( "0x".append( start + li.pos + 2,
92 li.len - 3 )))
93 goto ok
94 }
95 }
96 case $GTDO_PAR
97 {
98 if mode == $gt_TEST : procfail()
99 else
100 {
101 uint par = uint( "".copy( start + li.pos + 2,
102 li.len - 3 )) - 1
103 if &pars && par < *pars : ret += pars[ par ]
104 goto ok
105 }
106 }
107 case $GTDO_SIGN
108 {
109 if mode == $gt_TEST
110 {
111 if prev == $GTDO_SIGN : procfail()
112 else
113 {
114 mode = $gt_OUTPUT
115 if calltext
116 {
117 str stemp
118
119 stemp @ calltext->func( params )
120 params.clear()
121 curgti->gtitem.process( stemp, ret, params )
122 calltext = 0
123 }
124 else
125 {
126 curgti->gtitem.process( value, ret, params )
127 }
128 goto ok
129 }
130 }
131 else
132 {
133 params.clear()
134 value.clear()
135 initoff = off
136 calltext = 0
137 curgti as this
138 mode = $gt_TEST
139 goto ok
140 }
141 }
142 }
143 if mode == $gt_TEST
144 {
145 switch li.ltype
146 {
147 case $GTDO_NAME
148 {
149 str name
150
151 name.copy( start + li.pos, li.len )
152 if prev == $GTDO_DOT
153 {
154 if curgti->gtitem.find( name )
155 {
156 curgti->gtitem.get( name, value )
157 goto ok
158 }
159 }
160 elif prev == $GTDO_SIGN // ? было prev = $gtDO
161 {
162 uint it
163 it = &curgti->gtitem.findrel( name )
164
165 if it
166 {
167 curgti = it
168 value = curgti->gtitem.value
169 goto ok
170 }
171 else
172 {
173 if calltext = getid( name, 0, %{ arrstr } )
174 {
175 // value @ calltext->func( params )
176 // calltext = 0
177 goto ok
178 }
179 }
180 }
181 procfail()
182 }
183 case $GTDO_DOT
184 {
185 if prev != $GTDO_NAME && prev != $GTDO_SIGN : procfail()
186 }
187 case $GTDO_LP, $GTDO_LSP
188 {
189 if prev == $GTDO_NAME
190 {
191 last = 0
192 params += ""
193 goto ok
194 }
195 procfail()
196 }
197 case $GTDO_COLON, $GTDO_PARCALL
198 {
199 if prev == $GTDO_NAME
200 {
201 mode = $gt_OUTPUT
202 params.clear()
203 if li.ltype == $GTDO_COLON
204 {
205 last = 0
206 params += ""
207 params[ last ].append( start + li.pos + 1, li.len - 1 )
208 params[ last ].trimsys()
209 }
210 else
211 {
212 foreach cur, pars : params += cur
213 }
214 if calltext
215 {
216 str stemp
217 stemp @ calltext->func( params )
218 params.clear()
219 curgti->gtitem.process( stemp, ret, params )
220 calltext = 0
221 }
222 else
223 {
224 curgti->gtitem.process( value, ret, params )
225 }
226 goto ok
227 }
228 procfail()
229 }
230 case $GTDO_PARTEXT, $GTDO_PARSTEXT
231 {
232 params[ last ].append( start + li.pos, li.len )
233 if li.ltype == $GTDO_PARSTEXT
234 {
235 params[ last ].trimsys()
236 }
237 quotes = 0
238 }
239 case $GTDO_COMMA
240 {
241 if prev == $GTDO_SPACE && !quotes : params[ last ].trimrsys()
242 params += ""
243 last++
244 }
245 case $GTDO_SPACE
246 {
247 if *params[ last ] && !quotes
248 {
249 params[ last ].append( start + li.pos, li.len )
250 }
251 }
252 case $GTDO_RP,$GTDO_RSP
253 {
254 if prev == $GTDO_SPACE && !quotes : params[ last ].trimrsys()
255
256 mode = $gt_OUTPUT
257 // print("value =\(value) \( *params )\n")
258 if calltext
259 {
260 str stemp
261 stemp @ calltext->func( params )
262 params.clear()
263 curgti->gtitem.process( stemp, ret, params )
264 calltext = 0
265 }
266 else
267 {
268 curgti->gtitem.process( value, ret, params )
269 }
270 goto ok
271 }
272 case $GTDO_DQ, $GTDO_Q
273 {
274 if *params[ last ]
275 {
276 params[ last ].append( start + li.pos, li.len )
277 }
278 else : params[ last ].copy( start + li.pos + 1, li.len - 2 )
279 quotes = 1
280 }
281 }
282 }
283 if mode == $gt_OUTPUT
284 {
285 switch li.ltype
286 {
287 case $GTDO_Q, $GTDO_DQ, $GTDO_PARTEXT, $GTDO_PARSTEXT
288 {
289 str val
290 val.append( start + li.pos, li.len )
291 /* if calltext
292 {
293 ret @ calltext->func( pars )
294 curgti->gtitem.process( val, ret, pars )
295 calltext = 0
296 }
297 else
298 {*/
299 if li.ltype == $GTDO_PARSTEXT
300 {
301 val.trimsys()
302 }
303
304 curgti->gtitem.process( val, ret, pars )
305 // }
306 }
307 default
308 {
309 ret.append( start + li.pos, li.len )
310 }
311 }
312 }
313 elif mode == $gt_SKIP : mode = $gt_OUTPUT
314 label ok
315 prev = li.ltype
316 off += sizeof( lexitem )
317 }
318 return ret
319 }
320
321 method ustr gtitem.process( ustr in ret, arrstr pars )
322 {
323 str stemp sret
324
325 in.toutf8( stemp )
326 this.process( stemp, sret, pars )
327 return ret = sret
328 }
329
330 method str gt.process( str in )
331 {
332 str stemp
333 arrstr pars
334
335 this.root().process( in, stemp, pars )
336 return in = stemp
337 }
338
339