Annotation of OpenXM/src/ox_math/parse.c, Revision 1.3
1.1 ohara 1: /* -*- mode: C; coding: euc-japan -*- */
1.3 ! ohara 2: /* $OpenXM: OpenXM/src/ox_math/parse.c,v 1.2 1999/11/02 06:11:58 ohara Exp $ */
1.2 ohara 3: /* $Id: parse.c,v 1.6 1999/11/01 17:58:38 ohara Exp $ */
1.1 ohara 4: /* OX expression, CMO expression パーサ */
5:
6: #include <stdio.h>
7: #include <stdlib.h>
8: #include <string.h>
9: #include <sys/param.h>
1.2 ohara 10: #include <setjmp.h>
1.1 ohara 11: #include "oxtag.h"
12: #include "ox.h"
13: #include "parse.h"
14:
15: /* --- 構文解析部 --- */
1.2 ohara 16: /* (重要)セマンティックスについての注意.
17: CMO_LIST, CMO_STRING は、あらかじめ与えられた要素の個数を無視する.
18: CMO_MONOMIAL32 は無視しない. (つまりおかしいときは構文エラーになる)
19: */
20:
21:
1.1 ohara 22: /* parse.c, lex.c では, Lisp 表現された CMO 文字列を読み込み,
23: バイト列を出力する. 中間表現として、cmo *を利用する.
24: parse() はトークンの列から cmo *(の指す構造体)を生成する.
25: */
26:
27: /* 重要なことはパーサ(の各サブルーチン)は
28: 常にトークンをひとつ先読みしていると言うことである.
29: */
30:
31: /* 現在読み込み中のトークンを表す. */
32: static int token = 0;
33:
1.2 ohara 34: /* トークンの属性値. yylval は lex() によってセットされる. */
35: static union{
36: int d;
37: char* sym;
38: } yylval;
39:
40: /* pflag_cmo_addrev がセットされていれば、厳密には CMO expression では
41: ないもの, 例えば (CMO_STRING, "hello") も CMO に変換される. */
1.1 ohara 42:
1.2 ohara 43: static int pflag_cmo_addrev = 1; /* CMO の省略記法を許すか否かのフラグ */
1.1 ohara 44:
45: /* 関数の宣言 */
46: static int parse_error(char *s);
47: static int parse_lf();
48: static int parse_right_parenthesis();
49: static int parse_left_parenthesis();
50: static int parse_comma();
51: static int parse_integer();
52: static cmo *parse_cmo_null();
1.2 ohara 53: static cmo *parse_cmo_int32();
54: static cmo *parse_cmo_string();
55: static cmo *parse_cmo_mathcap();
56: static cmo *parse_cmo_dms_generic();
57: static cmo *parse_cmo_ring_by_name();
58: static cmo *parse_cmo_error2();
59: static cmo *parse_cmo_zero();
1.1 ohara 60: static cmo *parse_cmo_zz();
61: static cmo *parse_cmo_list();
62: static cmo *parse_cmo();
63: static char *parse_string();
64: static int parse_sm();
65: static ox* parse_ox();
66: static ox* parse_ox_command();
67: static ox* parse_ox_data();
68:
1.3 ! ohara 69: static int is_token_cmo(int token)
1.1 ohara 70: {
1.2 ohara 71: return (token >= MIN_T_CMO && token < MAX_T_CMO) || token == TOKEN(CMO_ERROR2);
1.1 ohara 72: }
73:
1.3 ! ohara 74: static int is_token_sm(int token)
1.1 ohara 75: {
76: return token >= MIN_T_SM && token < MAX_T_SM;
77: }
78:
1.3 ! ohara 79: static int is_token_ox(int token)
1.1 ohara 80: {
81: return token >= MIN_T_OX && token < MAX_T_OX;
82: }
83:
1.2 ohara 84: static jmp_buf env_parse;
85:
86: /* 構文解析に失敗したことを意味する. */
87: static int parse_error(char *s)
88: {
1.3 ! ohara 89: fprintf(stderr, "syntax error: %s\n", s);
1.2 ohara 90: longjmp(env_parse, 1);
91: }
92:
1.1 ohara 93: /* この部分は書き換え予定. */
94: cmo *parse()
95: {
96: cmo *m;
97:
1.2 ohara 98: if (setjmp(env_parse) != 0) {
99: return NULL; /* 構文解析に失敗したら NULL を返す. */
100: }
101:
1.1 ohara 102: do{
103: token = lex();
104: }while (token == '\n');
105:
106: if (token == '(') {
107: token = lex();
1.3 ! ohara 108: if (is_token_cmo(token)) {
1.1 ohara 109: m = parse_cmo();
1.3 ! ohara 110: }else if(is_token_ox(token)) {
1.1 ohara 111: m = parse_ox();
112: }else {
1.3 ! ohara 113: parse_error("invalid symbol.");
1.1 ohara 114: }
115: parse_lf();
116: return m;
117: }
118: return NULL;
119: }
120:
121: /* トークンを先読みしない(重要). */
122: static int parse_lf()
123: {
124: if (token != '\n') {
1.3 ! ohara 125: parse_error("no new line.");
1.1 ohara 126: }
127: return 0;
128: }
129:
130:
131: static ox* parse_ox()
132: {
133: ox *m = NULL;
134:
135: switch(token) {
1.2 ohara 136: case TOKEN(OX_COMMAND):
1.1 ohara 137: token = lex();
138: m = parse_ox_command();
139: break;
1.2 ohara 140: case TOKEN(OX_DATA):
1.1 ohara 141: token = lex();
142: m = parse_ox_data();
143: break;
144: default:
1.3 ! ohara 145: parse_error("invalid ox.");
1.1 ohara 146: }
147: return m;
148: }
149:
150: static ox* parse_ox_data()
151: {
152: ox* m;
153:
154: parse_comma();
155: parse_left_parenthesis();
156: m = (ox *)new_ox_data(parse_cmo());
157: parse_right_parenthesis();
158: return m;
159: }
160:
161: static int parse_sm()
162: {
163: int sm_code;
1.3 ! ohara 164: if (!is_token_sm(token)) {
! 165: parse_error("invalid SM opecode.");
1.1 ohara 166: }
167: sm_code = token - T_MAGIC;
168: token = lex();
169: return sm_code;
170: }
171:
172:
173: static ox* parse_ox_command()
174: {
175: ox* m;
176:
177: parse_comma();
178: m = (ox *)new_ox_command(parse_sm());
179: parse_right_parenthesis();
180: return m;
181: }
182:
183: /* 正しい入力ならば, parse_cmo を呼ぶ時点で, token には
1.2 ohara 184: TOKEN(CMO_xxx), TOKEN(OX_xxx) のいずれかがセットされている. */
1.1 ohara 185: static cmo *parse_cmo()
186: {
187: cmo *m = NULL;
188:
189: switch(token) {
1.2 ohara 190: case TOKEN(CMO_NULL):
1.1 ohara 191: token = lex();
192: m = parse_cmo_null();
193: break;
1.2 ohara 194: case TOKEN(CMO_INT32):
1.1 ohara 195: token = lex();
196: m = parse_cmo_int32();
197: break;
1.2 ohara 198: case TOKEN(CMO_STRING):
1.1 ohara 199: token = lex();
200: m = parse_cmo_string();
201: break;
1.2 ohara 202: case TOKEN(CMO_MATHCAP):
203: token = lex();
204: m = parse_cmo_mathcap();
205: break;
206: case TOKEN(CMO_LIST):
207: token = lex();
208: m = parse_cmo_list();
209: break;
210: case TOKEN(CMO_MONOMIAL32):
211: token = lex();
212: m = parse_cmo_monomial32();
213: break;
214: case TOKEN(CMO_ZZ):
1.1 ohara 215: token = lex();
216: m = parse_cmo_zz();
217: break;
1.2 ohara 218: case TOKEN(CMO_ZERO):
219: token = lex();
220: m = parse_cmo_zero();
221: break;
222: case TOKEN(CMO_DMS_GENERIC):
1.1 ohara 223: token = lex();
1.2 ohara 224: m = parse_cmo_dms_generic();
225: break;
226: case TOKEN(CMO_RING_BY_NAME):
227: token = lex();
228: m = parse_cmo_ring_by_name();
229: break;
1.3 ! ohara 230: case TOKEN(CMO_DISTRIBUTED_POLYNOMIAL):
! 231: token = lex();
! 232: m = parse_cmo_distributed_polynomial();
! 233: break;
1.2 ohara 234: case TOKEN(CMO_ERROR2):
235: token = lex();
236: m = parse_cmo_error2();
1.1 ohara 237: break;
238: default:
1.3 ! ohara 239: parse_error("invalid cmo.");
1.1 ohara 240: }
241: return m;
242: }
243:
1.2 ohara 244: static int parse_left_parenthesis()
1.1 ohara 245: {
1.2 ohara 246: if (token != '(') {
1.3 ! ohara 247: parse_error("no left parenthesis.");
1.1 ohara 248: }
249: token = lex();
250: }
251:
1.2 ohara 252: static int parse_right_parenthesis()
1.1 ohara 253: {
1.2 ohara 254: if (token != ')') {
1.3 ! ohara 255: parse_error("no right parenthesis.");
1.1 ohara 256: }
257: token = lex();
258: }
259:
260: static int parse_comma()
261: {
262: if (token != ',') {
1.3 ! ohara 263: parse_error("no comma.");
1.1 ohara 264: }
265: token = lex();
266: }
267:
268: static int parse_integer()
269: {
270: int val;
271: if (token != T_INTEGER) {
1.3 ! ohara 272: parse_error("no integer.");
1.1 ohara 273: }
274: val = yylval.d;
275: token = lex();
276: return val;
277: }
278:
279: static char *parse_string()
280: {
281: char *s;
282: if (token != T_STRING) {
1.3 ! ohara 283: parse_error("no string.");
1.1 ohara 284: }
285: s = yylval.sym;
286: token = lex();
287: return s;
288: }
289:
290: static cmo *parse_cmo_null()
291: {
292: parse_right_parenthesis();
1.2 ohara 293: return (cmo *)new_cmo_null();
1.1 ohara 294: }
295:
296: static cmo *parse_cmo_int32()
297: {
298: int i;
299:
300: parse_comma();
301: i = parse_integer();
302: parse_right_parenthesis();
1.2 ohara 303: return (cmo *)new_cmo_int32(i);
1.1 ohara 304: }
305:
306: static cmo *parse_cmo_string()
307: {
308: cmo_string *m;
309: char *s;
310:
311: parse_comma();
312: if (token == T_INTEGER) {
1.2 ohara 313: parse_integer();
1.1 ohara 314: parse_comma();
1.2 ohara 315: }else if (!pflag_cmo_addrev) {
1.3 ! ohara 316: parse_error("invalid cmo string.");
1.2 ohara 317: }
318: s = parse_string();
319: m = new_cmo_string(s);
320: parse_right_parenthesis();
321: return (cmo *)m;
322: }
323:
324: static cmo *parse_cmo_mathcap()
325: {
326: cmo *ob;
327:
328: parse_comma();
329: parse_left_parenthesis();
330: ob = parse_cmo();
331: parse_right_parenthesis();
332: return (cmo *)new_cmo_mathcap(ob);
333: }
334:
335: static cmo *parse_cmo_list()
336: {
337: int length=0;
338: int i=0;
339: cmo_list *m = new_cmo_list();
340: cmo *newcmo;
341:
342: if (token == ',') {
343: parse_comma();
344:
345: if (token == T_INTEGER) {
346: parse_integer();
347: parse_comma();
348: }else if (!pflag_cmo_addrev) {
1.3 ! ohara 349: parse_error("invalid cmo_list.");
1.2 ohara 350: }
351:
352: while(token == '(') {
353: parse_left_parenthesis();
354: newcmo = parse_cmo();
355: append_cmo_list(m, newcmo);
356: if (token != ',') {
357: break;
358: }
359: parse_comma();
360: }
361: }else if (!pflag_cmo_addrev) {
1.3 ! ohara 362: parse_error("invalid cmo_list.");
1.2 ohara 363: }
364: parse_right_parenthesis();
365: return (cmo *)m;
366: }
367:
368: static cmo *parse_cmo_monomial32()
369: {
370: int size;
371: int *exps;
372: int i;
373: cmo_monomial32 *m;
1.3 ! ohara 374: int tag;
1.2 ohara 375:
376: parse_comma();
377: size = parse_integer();
1.3 ! ohara 378: if (size < 0) {
! 379: parse_error("invalid value.");
1.2 ohara 380: }
381: m = new_cmo_monomial32_size(size);
382:
383: for(i=0; i<size; i++) {
384: parse_comma();
385: m->exps[i] = parse_integer();
386: }
387: parse_comma();
388: parse_left_parenthesis();
389: m->coef = parse_cmo();
1.3 ! ohara 390: tag = m->coef->tag;
! 391:
! 392: /* m->coef は CMO_ZZ 型か CMO_INT32 型でなければならない */
! 393: if (tag != CMO_ZZ && tag != CMO_INT32) {
! 394: parse_error("invalid cmo.");
! 395: }
1.2 ohara 396: parse_right_parenthesis();
397: return (cmo *)m;
398: }
399:
400: /* cmo_zz の内部を直接いじる. */
401: static cmo *parse_cmo_zz()
402: {
403: int length;
404: int i=0;
405: cmo_zz *m= NULL;
406:
407: parse_comma();
408: length = parse_integer();
409: if (token == ',') {
410: m = new_cmo_zz_size(length);
411:
412: length = abs(length);
413: for(i=0; i<length; i++) {
414: parse_comma();
415: m->mpz->_mp_d[i] = parse_integer();
1.1 ohara 416: }
1.2 ohara 417: }else if (pflag_cmo_addrev) {
418: m = new_cmo_zz_set_si(length);
1.1 ohara 419: }else {
1.3 ! ohara 420: parse_error("no comma.");
1.1 ohara 421: }
1.2 ohara 422:
1.1 ohara 423: parse_right_parenthesis();
424: return (cmo *)m;
425: }
426:
1.2 ohara 427: static cmo *parse_cmo_zero()
428: {
429: parse_right_parenthesis();
430: return (cmo *)new_cmo_zero();
431: }
432:
433: static cmo *parse_cmo_dms_generic()
434: {
435: parse_right_parenthesis();
436: return (cmo *)new_cmo_dms_generic();
437: }
438:
439: static cmo *parse_cmo_ring_by_name()
440: {
441: cmo *ob;
442:
443: parse_comma();
444: parse_left_parenthesis();
445: ob = parse_cmo();
1.3 ! ohara 446:
! 447: /* ob は CMO_STRING 型でなければならない */
! 448: if (ob->tag != CMO_STRING) {
! 449: parse_error("invalid cmo.");
! 450: }
1.2 ohara 451: parse_right_parenthesis();
452: return (cmo *)new_cmo_ring_by_name(ob);
453: }
454:
1.3 ! ohara 455: static cmo *parse_cmo_distributed_polynomial()
! 456: {
! 457: int length=0;
! 458: int i=0;
! 459: cmo_distributed_polynomial *m = new_cmo_distributed_polynomial();
! 460: cmo *ob;
! 461: int tag;
! 462:
! 463: if (token == ',') {
! 464: parse_comma();
! 465:
! 466: if (token == T_INTEGER) {
! 467: parse_integer();
! 468: parse_comma();
! 469: }else if (!pflag_cmo_addrev) {
! 470: parse_error("invalid d-polynomial.");
! 471: }
! 472:
! 473: parse_left_parenthesis();
! 474: m->ringdef = parse_cmo();
! 475: tag = m->ringdef->tag;
! 476: /* m->ringdef は DringDefinition でなければならない */
! 477: if (tag != CMO_RING_BY_NAME && tag != CMO_DMS_GENERIC
! 478: && tag != CMO_DMS_OF_N_VARIABLES) {
! 479: parse_error("invalid cmo.");
! 480: }
! 481:
! 482: parse_comma();
! 483:
! 484: while(token == '(') {
! 485: parse_left_parenthesis();
! 486: ob = parse_cmo();
! 487: if (ob->tag != CMO_MONOMIAL32 && ob->tag != CMO_ZERO) {
! 488: parse_error("invalid cmo.");
! 489: }
! 490: append_cmo_list(m, ob);
! 491: if (token != ',') {
! 492: break;
! 493: }
! 494: parse_comma();
! 495: }
! 496: }else if (!pflag_cmo_addrev) {
! 497: parse_error("invalid d-polynomial.");
! 498: }
! 499: parse_right_parenthesis();
! 500: return (cmo *)m;
! 501: }
! 502:
! 503:
1.2 ohara 504: static cmo *parse_cmo_error2()
505: {
506: cmo *ob;
507:
508: parse_comma();
509: parse_left_parenthesis();
510: ob = parse_cmo();
511: parse_right_parenthesis();
512: return (cmo *)new_cmo_error2(ob);
513: }
514:
1.1 ohara 515: /* --- 字句解析部 --- */
516:
517: /* lexical analyzer で読み飛ばされる文字なら何を初期値にしてもよい */
518: static int c = ' ';
519:
520: /* 一文字読み込む関数 */
521: static int (*GETC)() = getchar;
522:
523: int setgetc(int (*foo)())
524: {
525: GETC = foo;
526: }
527:
528: int resetgetc()
529: {
530: GETC = getchar;
531: }
532:
1.2 ohara 533: #define SIZE_BUFFER 8192
1.1 ohara 534: static char buffer[SIZE_BUFFER];
535:
536: /* 桁溢れの場合の対策はない */
537: static int lex_digit()
538: {
539: int d = 0;
540: do {
541: d = 10*d + (c - '0');
542: c = GETC();
543: } while(isdigit(c));
544: return d;
545: }
546:
547: /* バッファあふれした場合の対策をちゃんと考えるべき */
548: static char *lex_quoted_string()
549: {
550: int i;
551: char c0 = ' ';
552: char *s = NULL;
553: for (i=0; i<SIZE_BUFFER; i++) {
554: c = GETC();
555: if(c == '"') {
556: s = malloc(i+1);
557: buffer[i]='\0';
558: strcpy(s, buffer);
559:
560: c = GETC();
561: return s;
562: }else if (c == '\\') {
563: c0 = c;
564: c = GETC();
565: if (c != '"') {
566: buffer[i++] = c0;
567: }
568: }
569: buffer[i]=c;
570: }
571: fprintf(stderr, "buffer overflow!\n");
572: exit(1);
573: /* return NULL; */
574: }
575:
1.2 ohara 576: typedef struct {
577: char *key;
578: int token;
579: } symbol;
580:
1.3 ! ohara 581: #define MK_KEY_CMO(x) { #x , TOKEN(x) }
1.2 ohara 582: #define MK_KEY(x) { #x , TOKEN(x) }
583:
584: static symbol symbol_list[] = {
1.3 ! ohara 585: MK_KEY_CMO(CMO_NULL),
! 586: MK_KEY_CMO(CMO_INT32),
! 587: MK_KEY_CMO(CMO_DATUM),
! 588: MK_KEY_CMO(CMO_STRING),
! 589: MK_KEY_CMO(CMO_MATHCAP),
! 590: MK_KEY_CMO(CMO_LIST),
! 591: MK_KEY_CMO(CMO_MONOMIAL32),
! 592: MK_KEY_CMO(CMO_ZZ),
! 593: MK_KEY_CMO(CMO_ZERO),
! 594: MK_KEY_CMO(CMO_DMS_GENERIC),
! 595: MK_KEY_CMO(CMO_RING_BY_NAME),
! 596: MK_KEY_CMO(CMO_INDETERMINATE),
! 597: MK_KEY_CMO(CMO_DISTRIBUTED_POLYNOMIAL),
! 598: MK_KEY_CMO(CMO_ERROR2),
1.2 ohara 599: MK_KEY(SM_popCMO),
600: MK_KEY(SM_popString),
601: MK_KEY(SM_mathcap),
602: MK_KEY(SM_pops),
603: MK_KEY(SM_executeStringByLocalParser),
604: MK_KEY(SM_executeFunction),
605: MK_KEY(SM_setMathCap),
606: MK_KEY(SM_control_kill),
607: MK_KEY(SM_control_reset_connection),
608: MK_KEY(OX_COMMAND), MK_KEY(OX_DATA),
609: {NULL, 0} /* a gate keeper */
610: };
611:
612: static int token_of_symbol(char *key)
613: {
614: symbol *kp;
615: for(kp = symbol_list; kp->key != NULL; kp++) {
616: if (strcmp(key, kp->key)==0) {
617: return kp->token;
618: }
619: }
620: #if DEBUG
1.1 ohara 621: fprintf(stderr, "lex error\n");
1.2 ohara 622: #endif
1.1 ohara 623: return 0;
624: }
625:
1.2 ohara 626: static int lex_symbol()
1.1 ohara 627: {
628: int i;
629: for (i=0; i<SIZE_BUFFER; i++) {
630: if (!isalnum(c) && c != '_') {
631: buffer[i]='\0';
1.2 ohara 632: return token_of_symbol(buffer);
1.1 ohara 633: }
634: buffer[i]=c;
635: c = GETC();
636: }
637: fprintf(stderr, "buffer overflow!\n");
1.2 ohara 638: return 0;
1.1 ohara 639: }
640:
641: /* return する前に一文字先読みしておく。 */
642: int lex()
643: {
644: int c_dash = 0;
645:
646: /* 空白をスキップする. */
647: while (isspace(c) && c != '\n') {
648: c = GETC();
649: }
650:
651: switch(c) {
652: case '(':
653: case ')':
654: case ',':
655: case '\n':
656: c_dash = c;
657: c = ' ';
658: return c_dash;
659: case EOF:
660: c = GETC();
661: return c_dash;
662: case '"': /* a quoted string! */
663: yylval.sym = lex_quoted_string();
664: return T_STRING;
665: default:
666: }
667:
668: if (isalpha(c)) { /* 識別子 */
1.2 ohara 669: return lex_symbol();
1.1 ohara 670: }
671:
672: /* 32bit 整数値 */
673: if (isdigit(c)){
674: yylval.d = lex_digit();
675: return T_INTEGER;
676: }
677: if (c == '-') {
678: c = GETC();
679: while (isspace(c) && c != '\n') {
680: c = GETC();
681: }
682: if (isdigit(c)){
683: yylval.d = - lex_digit();
684: return T_INTEGER;
685: }
686: return 0;
687: }
688:
689: c = GETC();
690: return 0;
691: }
692:
693: static char *mygetc_line;
694: static int mygetc_counter;
695: static int mygetc_counter_max;
696:
697: int mygetc()
698: {
699: if (mygetc_counter <= mygetc_counter_max) {
700: return mygetc_line[mygetc_counter++];
701: }
702: return 0;
703: }
704:
705: int setmode_mygetc(char *s, int len)
706: {
707: mygetc_counter=0;
708: mygetc_counter_max=len;
709: mygetc_line=s;
1.2 ohara 710: }
711:
712: int setflag_parse(int flag)
713: {
714: pflag_cmo_addrev = flag;
1.1 ohara 715: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>