Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/mty-makai/expr_parse.y

Parent Directory Parent Directory | Revision Log Revision Log


Revision 192 - (show annotations) (download)
Mon May 26 06:29:35 2008 UTC (15 years, 10 months ago) by notanpe
File size: 8608 byte(s)
シーズン 2 に向けて
1 /***********************************************************************
2 *
3 * file: expr_parse.y
4 *
5 * お気楽なパーサ
6 *
7 */
8
9 %{
10
11 #include <assert.h>
12 #include <stdarg.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include "config.h"
17 #include "expr_parse.h"
18 #include "mtytypes.h"
19 #include "synth.h"
20 #include "wdict.h"
21
22 #if !defined(YYDEBUG) && DEBUG>=1
23 #define YYDEBUG 1
24 #endif
25
26 char *g_filename;
27 int g_lineno;
28
29 /* この版では、単純一致のみ */
30 struct ELEMS_ARY
31 {
32 union
33 {
34 uint64_t rng;
35 struct DICT_CHAR dict;
36 } ch[10];
37 unsigned rng :10; /* RNG だったら立てる */
38 unsigned len : 4;
39 };
40
41 %}
42
43 %union {
44 int a;
45 struct ITREE *tree;
46 struct ELEMS_ARY *elems;
47 char *str;
48 uint64_t bmp;
49 struct DICT_CHAR dict;
50 }
51
52 %{
53
54 #define YY_DECL static int yylex(void)
55
56 YY_DECL;
57 static void yyerror(char const *msg);
58 static void expr_error(char const *fmt, ...);
59 static unsigned cv64(int c);
60 static uint64_t mkrng(unsigned a, unsigned z);
61 static int mkdict(unsigned attr, unsigned e);
62 static int mkchx(int c, unsigned e);
63
64 static struct ITREE *g_node;
65
66 %}
67
68 %token JUNK
69 %token '^' '$' '?'
70 %token <dict> DICT
71 %token <dict> CHX CHXE
72 %token OR
73 %token CLS CLS_CMPL
74 %token <bmp> RNGS
75
76 %type <a> acc_op dol_op
77 %type <tree> expr
78 %type <elems> elems elem
79 %type <dict> dict d_el
80 %type <bmp> rngs
81
82 %%
83
84 file : delims_op exprs delims_op
85 | delims_op
86 ;
87
88 exprs : exprs orz expr
89 {
90 synth_add(g_node, $3, NULL);
91 }
92 | expr
93 {
94 synth_add(g_node, $1, NULL);
95 }
96 ;
97
98 delims_op
99 : /*nil*/
100 | orz
101 ;
102
103 orz : orz OR
104 | OR
105 ;
106
107 expr : acc_op elems dol_op
108 {
109 int i, j;
110 int ne = 0; /* 作った項数 */
111
112 $$ = NULL;
113 for (i = 1; $2 && i <= 11 - $2->len; i++)
114 {
115 struct ITREE *pc;
116
117 /* 先頭制約 */
118 if ($1 && i > 1)
119 continue;
120 /* 末尾制約 */
121 if (i == 11 - $2->len)
122 {
123 /* 末尾がありえない */
124 if (($2->rng & (1 << ($2->len - 1))))
125 {
126 if (!($2->ch[$2->len - 1].rng & 0x1111111111111111ULL))
127 continue;
128 }
129 else
130 {
131 if (!$2->ch[$2->len - 1].dict.e)
132 continue;
133 }
134 }
135 else if ($3) /* 末尾制約 $ */
136 continue;
137
138 /* 展開 */
139 if (!($2->rng & 1)
140 && $2->ch[0].dict.len == $2->len
141 && $2->len >=4)
142 {
143 /* 単独辞書 */
144 pc = synth_make_dict(i, /* 位置 */
145 &$2->ch[0].dict);
146 ne++;
147
148 /* NULL が返ってきた場合は、
149 すでに存在している辞書なので
150 もう追加しない(いいのか?) */
151 if (pc == NULL)
152 continue;
153 }
154 else for (j = 0, pc = synth_make_and();
155 j < $2->len;
156 j += (($2->rng & (1 << j))
157 ? 1
158 : $2->ch[j].dict.len))
159 if ($2->rng & (1 << j))
160 {
161 /* 汎用の範囲 */
162 synth_add(pc,
163 synth_make_lr($2->ch[j].rng, i + j),
164 NULL);
165 ne++;
166 }
167 else
168 {
169 /* 論理演算で展開 */
170 int k;
171 uint64_t m = $2->ch[j].dict.bmp;
172 for (k = 0; k < $2->ch[j].dict.len; k++, m >>= 6)
173 {
174 unsigned c = m & 0x3F;
175 synth_add(pc,
176 synth_make_lr((mkrng(c, c)
177 | (($2->ch[j].dict.xp & (1 << k))
178 ? (c >= 014
179 ? mkrng(c + 26, c + 26)
180 : c == 0
181 ? mkrng(c, c + 1)
182 : 0)
183 : 0)),
184 i + j + k),
185 NULL);
186 ne++;
187 }
188 }
189
190 if (!$$)
191 $$ = synth_make_or();
192
193 synth_add($$, pc, NULL);
194 }
195
196 if ($2 != NULL)
197 {
198 free($2); /* elems は不要 */
199
200 if (!ne)
201 {
202 $$ = NULL;
203 expr_error("一致しないんじゃないかな?(意見求ム)");
204 }
205 }
206 }
207 ;
208
209 acc_op : /*nil*/ { $$ = 0; }
210 | '^' { $$ = 1; }
211 ;
212
213 dol_op : /*nil*/ { $$ = 0; }
214 | '$' { $$ = 1; }
215 ;
216
217 elems : elems elem
218 {
219 if ($1 == NULL || $2 == NULL)
220 {
221 /* fallthru */
222 if ($1 != NULL)
223 free($1);
224 if ($2 != NULL)
225 free($1);
226 $$ = NULL;
227 }
228 else if ($1->len + $2->len <= 10)
229 {
230 assert(0 < $1->len + $2->len);
231 $$->rng = $1->rng | ($2->rng << $1->len);
232 memcpy(&$$->ch[$$->len], &$2->ch[0], $2->len * sizeof($2->ch[0]));
233 $$->len += $2->len;
234 free($2);
235 }
236 else
237 {
238 expr_error("なんだかタゲが10文字超えてる感じ?");
239 assert($1 != NULL);
240 assert($2 != NULL);
241 free($1);
242 free($2);
243 $$ = NULL;
244 }
245 }
246 | elem
247 ;
248
249 elem : dict
250 {
251 int i;
252 if ($1.len > 0)
253 {
254 $$ = calloc(1, sizeof(struct ELEMS_ARY));
255 $$->len = i = $1.len;
256 $$->rng = 0;
257 while (--i >= 0)
258 $$->ch[i].dict = $1;
259 }
260 else
261 $$ = NULL;
262 }
263 | CLS rngs
264 {
265 $$ = calloc(1, sizeof(struct ELEMS_ARY));
266 $$->len = 1;
267 $$->rng = 1;
268 $$->ch[0].rng = $2;
269 }
270 | CLS_CMPL rngs
271 {
272 $$ = calloc(1, sizeof(struct ELEMS_ARY));
273 $$->len = 1;
274 $$->rng = 1;
275 $$->ch[0].rng = ~$2;
276 }
277 | '?'
278 {
279 $$ = calloc(1, sizeof(struct ELEMS_ARY));
280 $$->len = 1;
281 $$->rng = 1;
282 /* すべてに一致する Placeholder(あとで取り除く) */
283 $$->ch[0].rng = (uint64_t)-1;
284 }
285 | JUNK
286 { $$ = NULL; } /* エラーは報告済み */
287 ;
288
289 rngs : rngs RNGS { $$ = $1 | $2; }
290 | RNGS { $$ = $1; }
291 ;
292
293 dict : dict d_el
294 {
295 unsigned len1 = $1.len;
296 if (len1 == 0 || $2.len == 0)
297 {
298 /* fallthru */
299 }
300 else if (len1 + $2.len <= 9 + $2.e)
301 {
302 /* $2 に $1 を差し込む形でマージ
303 $2.e は引き継がれる */
304 $$ = $2;
305 $$.len += len1;
306 $$.xp = ($$.xp << len1) | $1.xp;
307 $$.bmp = ($$.bmp << (6 * len1)) | $1.bmp;
308 $$.attr |= $1.attr;
309 }
310 else
311 {
312 expr_error("長すぎる単語があるよ?");
313 $$.len = 0;
314 }
315 }
316 | d_el
317 ;
318
319 d_el : DICT
320 | CHX
321 | CHXE
322 ;
323
324 %%
325
326 /***************************************************************
327 *
328 * 文字を内部コード(0〜63)に変換。
329 *
330 * スキャナ部から呼ばれるため、
331 * エラー処理は省いても構わない…ハズ。
332 *
333 */
334
335 static
336 unsigned
337 cv64(int c)
338 {
339 if ('.' <= c && c <= '/')
340 return c - '.';
341 else if ('0' <= c && c <= '9')
342 return c - '0' + 2;
343 else if ('A' <= c && c <= 'Z')
344 return c - 'A' + 2 + 10;
345 else if ('a' <= c && c <= 'z')
346 return c - 'a' + 2 + 10 + 26;
347
348 expr_error("<%02X>これはバグです。", c & 0xFF);
349 assert(!"char range is impossible");
350 return -1;
351 }
352
353 /***************************************************************
354 *
355 * [a-z] に対応するビットマップを生成
356 *
357 */
358
359 static
360 uint64_t
361 mkrng(unsigned a, unsigned z)
362 {
363 assert(a < 64);
364 if (z >= 64)
365 return mkrng(a, a);
366 if (a > z)
367 return mkrng(z, a);
368 /* シフトカウントを +1 すると、
369 1 << 64 を 1 << 0 と計算してしまうケースがあるため
370 外側で別途シフトするのが吉 */
371 return (2 * ((uint64_t)1 << (z - a)) - 1) << a;
372 }
373
374 /***************************************************************
375 *
376 * スキャナ
377 *
378 */
379
380 #include "expr_scan.c"
381
382 int yywrap(void)
383 {
384 return (yyin == NULL
385 || feof(yyin));
386 }
387
388 static
389 void yyerror(char const *msg)
390 {
391 expr_error("内部エラー<%s>困った困った。", msg);
392 }
393
394 /***************************************************************
395 *
396 * エラーっぽいものを報告
397 *
398 */
399
400 static
401 void
402 expr_error(char const *fmt, ...)
403 {
404 va_list ap;
405 fprintf(stderr, "%s:%d:", g_filename, g_lineno);
406 va_start(ap, fmt);
407 vfprintf(stderr, fmt, ap);
408 va_end(ap);
409 fputc('\n', stderr);
410 }
411
412 /***************************************************************
413 *
414 * DICT_CHAR を生成(yytext, yyleng, yylval)
415 *
416 */
417
418 static
419 int
420 mkdict(unsigned attr, unsigned e)
421 {
422 int i;
423 yylval.dict.xp = 0;
424 yylval.dict.len = yyleng;
425 yylval.dict.e = e;
426 yylval.dict.attr = attr;
427 yylval.dict.bmp = 0;
428 for (i = yyleng - 1; i >= 0; i--)
429 yylval.dict.bmp = (yylval.dict.bmp << 6) | cv64(yytext[i]);
430 return DICT;
431 }
432
433 static
434 int
435 mkchx(int c, unsigned e)
436 {
437 yylval.dict.len = 1;
438 yylval.dict.e = e;
439 yylval.dict.attr = CA_C;
440 if (c == '.' || c == '/')
441 yylval.dict.bmp = 000; /* dot で代表 */
442 else
443 yylval.dict.bmp = cv64(c & ~0x20);
444 yylval.dict.xp = 0x01U;
445 return DICT;
446 }
447
448 /***************************************************************
449 *
450 * ファイルを木に展開する
451 *
452 */
453
454 struct ITREE *
455 expr_parse(char const *filename)
456 {
457 int r;
458
459 #if defined(YYDEBUG) && DEBUG>=2
460 yydebug = 1;
461 #endif
462
463 #if DEBUG>=1
464 fprintf(stderr, "target:<%s>\n", filename);
465 #endif
466
467 yyin = fopen(filename, "rt");
468 if (!yyin)
469 {
470 perror(filename);
471 return NULL;
472 }
473 if (g_filename)
474 free(g_filename);
475 g_filename = strdup(filename);
476 g_lineno = 1;
477
478 fprintf(stderr, "ファイル<%s>を読み込み中…\n", filename);
479
480 YY_NEW_FILE;
481 g_node = synth_make_or();
482 g_node->ref++;
483 r = yyparse();
484 assert(r == 0);
485
486 if (g_node->n_ops == 0)
487 {
488 synth_unlink(g_node);
489 g_node = NULL;
490 }
491
492 fclose(yyin);
493 yyin = NULL;
494
495 return g_node;
496 }
497
498 /*
499 * Local Variables:
500 * tab-width: 4
501 * End:
502 *
503 * EOF */

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Rev URL

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26