Annotation of OpenXM/src/ox_math/parse.c, Revision 1.4
1.1 ohara 1: /* -*- mode: C; coding: euc-japan -*- */
1.4 ! ohara 2: /* $OpenXM: OpenXM/src/ox_math/parse.c,v 1.3 1999/11/02 18:58:25 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: {
1.4 ! ohara 76: return token == TOKEN(SM);
1.1 ohara 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 ox* parse_ox_command()
162: {
163: ox* m;
164:
165: parse_comma();
1.4 ! ohara 166: parse_left_parenthesis();
1.1 ohara 167: m = (ox *)new_ox_command(parse_sm());
168: parse_right_parenthesis();
169: return m;
170: }
171:
1.4 ! ohara 172: static int parse_sm()
! 173: {
! 174: int sm_code;
! 175: if (token != TOKEN(SM)) {
! 176: parse_error("no opecode.");
! 177: }
! 178: sm_code = yylval.d;
! 179: token = lex();
! 180: parse_right_parenthesis();
! 181: return sm_code;
! 182: }
! 183:
! 184:
1.1 ohara 185: /* 正しい入力ならば, parse_cmo を呼ぶ時点で, token には
1.2 ohara 186: TOKEN(CMO_xxx), TOKEN(OX_xxx) のいずれかがセットされている. */
1.1 ohara 187: static cmo *parse_cmo()
188: {
189: cmo *m = NULL;
190:
191: switch(token) {
1.2 ohara 192: case TOKEN(CMO_NULL):
1.1 ohara 193: token = lex();
194: m = parse_cmo_null();
195: break;
1.2 ohara 196: case TOKEN(CMO_INT32):
1.1 ohara 197: token = lex();
198: m = parse_cmo_int32();
199: break;
1.2 ohara 200: case TOKEN(CMO_STRING):
1.1 ohara 201: token = lex();
202: m = parse_cmo_string();
203: break;
1.2 ohara 204: case TOKEN(CMO_MATHCAP):
205: token = lex();
206: m = parse_cmo_mathcap();
207: break;
208: case TOKEN(CMO_LIST):
209: token = lex();
210: m = parse_cmo_list();
211: break;
212: case TOKEN(CMO_MONOMIAL32):
213: token = lex();
214: m = parse_cmo_monomial32();
215: break;
216: case TOKEN(CMO_ZZ):
1.1 ohara 217: token = lex();
218: m = parse_cmo_zz();
219: break;
1.2 ohara 220: case TOKEN(CMO_ZERO):
221: token = lex();
222: m = parse_cmo_zero();
223: break;
224: case TOKEN(CMO_DMS_GENERIC):
1.1 ohara 225: token = lex();
1.2 ohara 226: m = parse_cmo_dms_generic();
227: break;
228: case TOKEN(CMO_RING_BY_NAME):
229: token = lex();
230: m = parse_cmo_ring_by_name();
231: break;
1.3 ohara 232: case TOKEN(CMO_DISTRIBUTED_POLYNOMIAL):
233: token = lex();
234: m = parse_cmo_distributed_polynomial();
235: break;
1.2 ohara 236: case TOKEN(CMO_ERROR2):
237: token = lex();
238: m = parse_cmo_error2();
1.1 ohara 239: break;
240: default:
1.3 ohara 241: parse_error("invalid cmo.");
1.1 ohara 242: }
243: return m;
244: }
245:
1.2 ohara 246: static int parse_left_parenthesis()
1.1 ohara 247: {
1.2 ohara 248: if (token != '(') {
1.3 ohara 249: parse_error("no left parenthesis.");
1.1 ohara 250: }
251: token = lex();
252: }
253:
1.2 ohara 254: static int parse_right_parenthesis()
1.1 ohara 255: {
1.2 ohara 256: if (token != ')') {
1.3 ohara 257: parse_error("no right parenthesis.");
1.1 ohara 258: }
259: token = lex();
260: }
261:
262: static int parse_comma()
263: {
264: if (token != ',') {
1.3 ohara 265: parse_error("no comma.");
1.1 ohara 266: }
267: token = lex();
268: }
269:
270: static int parse_integer()
271: {
272: int val;
273: if (token != T_INTEGER) {
1.3 ohara 274: parse_error("no integer.");
1.1 ohara 275: }
276: val = yylval.d;
277: token = lex();
278: return val;
279: }
280:
281: static char *parse_string()
282: {
283: char *s;
284: if (token != T_STRING) {
1.3 ohara 285: parse_error("no string.");
1.1 ohara 286: }
287: s = yylval.sym;
288: token = lex();
289: return s;
290: }
291:
292: static cmo *parse_cmo_null()
293: {
294: parse_right_parenthesis();
1.2 ohara 295: return (cmo *)new_cmo_null();
1.1 ohara 296: }
297:
298: static cmo *parse_cmo_int32()
299: {
300: int i;
301:
302: parse_comma();
303: i = parse_integer();
304: parse_right_parenthesis();
1.2 ohara 305: return (cmo *)new_cmo_int32(i);
1.1 ohara 306: }
307:
308: static cmo *parse_cmo_string()
309: {
310: cmo_string *m;
311: char *s;
312:
313: parse_comma();
314: if (token == T_INTEGER) {
1.2 ohara 315: parse_integer();
1.1 ohara 316: parse_comma();
1.2 ohara 317: }else if (!pflag_cmo_addrev) {
1.3 ohara 318: parse_error("invalid cmo string.");
1.2 ohara 319: }
320: s = parse_string();
321: m = new_cmo_string(s);
322: parse_right_parenthesis();
323: return (cmo *)m;
324: }
325:
326: static cmo *parse_cmo_mathcap()
327: {
328: cmo *ob;
329:
330: parse_comma();
331: parse_left_parenthesis();
332: ob = parse_cmo();
333: parse_right_parenthesis();
334: return (cmo *)new_cmo_mathcap(ob);
335: }
336:
337: static cmo *parse_cmo_list()
338: {
339: int length=0;
340: int i=0;
341: cmo_list *m = new_cmo_list();
342: cmo *newcmo;
343:
344: if (token == ',') {
345: parse_comma();
346:
347: if (token == T_INTEGER) {
348: parse_integer();
349: parse_comma();
350: }else if (!pflag_cmo_addrev) {
1.3 ohara 351: parse_error("invalid cmo_list.");
1.2 ohara 352: }
353:
354: while(token == '(') {
355: parse_left_parenthesis();
356: newcmo = parse_cmo();
357: append_cmo_list(m, newcmo);
358: if (token != ',') {
359: break;
360: }
361: parse_comma();
362: }
363: }else if (!pflag_cmo_addrev) {
1.3 ohara 364: parse_error("invalid cmo_list.");
1.2 ohara 365: }
366: parse_right_parenthesis();
367: return (cmo *)m;
368: }
369:
370: static cmo *parse_cmo_monomial32()
371: {
372: int size;
373: int *exps;
374: int i;
375: cmo_monomial32 *m;
1.3 ohara 376: int tag;
1.2 ohara 377:
378: parse_comma();
379: size = parse_integer();
1.3 ohara 380: if (size < 0) {
381: parse_error("invalid value.");
1.2 ohara 382: }
383: m = new_cmo_monomial32_size(size);
384:
385: for(i=0; i<size; i++) {
386: parse_comma();
387: m->exps[i] = parse_integer();
388: }
389: parse_comma();
390: parse_left_parenthesis();
391: m->coef = parse_cmo();
1.3 ohara 392: tag = m->coef->tag;
393:
394: /* m->coef は CMO_ZZ 型か CMO_INT32 型でなければならない */
395: if (tag != CMO_ZZ && tag != CMO_INT32) {
396: parse_error("invalid cmo.");
397: }
1.2 ohara 398: parse_right_parenthesis();
399: return (cmo *)m;
400: }
401:
402: /* cmo_zz の内部を直接いじる. */
403: static cmo *parse_cmo_zz()
404: {
405: int length;
406: int i=0;
407: cmo_zz *m= NULL;
408:
409: parse_comma();
410: length = parse_integer();
411: if (token == ',') {
412: m = new_cmo_zz_size(length);
413:
414: length = abs(length);
415: for(i=0; i<length; i++) {
416: parse_comma();
417: m->mpz->_mp_d[i] = parse_integer();
1.1 ohara 418: }
1.2 ohara 419: }else if (pflag_cmo_addrev) {
420: m = new_cmo_zz_set_si(length);
1.1 ohara 421: }else {
1.3 ohara 422: parse_error("no comma.");
1.1 ohara 423: }
1.2 ohara 424:
1.1 ohara 425: parse_right_parenthesis();
426: return (cmo *)m;
427: }
428:
1.2 ohara 429: static cmo *parse_cmo_zero()
430: {
431: parse_right_parenthesis();
432: return (cmo *)new_cmo_zero();
433: }
434:
435: static cmo *parse_cmo_dms_generic()
436: {
437: parse_right_parenthesis();
438: return (cmo *)new_cmo_dms_generic();
439: }
440:
441: static cmo *parse_cmo_ring_by_name()
442: {
443: cmo *ob;
444:
445: parse_comma();
446: parse_left_parenthesis();
447: ob = parse_cmo();
1.3 ohara 448:
449: /* ob は CMO_STRING 型でなければならない */
450: if (ob->tag != CMO_STRING) {
451: parse_error("invalid cmo.");
452: }
1.2 ohara 453: parse_right_parenthesis();
454: return (cmo *)new_cmo_ring_by_name(ob);
455: }
456:
1.3 ohara 457: static cmo *parse_cmo_distributed_polynomial()
458: {
459: int length=0;
460: int i=0;
461: cmo_distributed_polynomial *m = new_cmo_distributed_polynomial();
462: cmo *ob;
463: int tag;
464:
465: if (token == ',') {
466: parse_comma();
467:
468: if (token == T_INTEGER) {
469: parse_integer();
470: parse_comma();
471: }else if (!pflag_cmo_addrev) {
472: parse_error("invalid d-polynomial.");
473: }
474:
475: parse_left_parenthesis();
476: m->ringdef = parse_cmo();
477: tag = m->ringdef->tag;
478: /* m->ringdef は DringDefinition でなければならない */
479: if (tag != CMO_RING_BY_NAME && tag != CMO_DMS_GENERIC
480: && tag != CMO_DMS_OF_N_VARIABLES) {
481: parse_error("invalid cmo.");
482: }
483:
484: parse_comma();
485:
486: while(token == '(') {
487: parse_left_parenthesis();
488: ob = parse_cmo();
489: if (ob->tag != CMO_MONOMIAL32 && ob->tag != CMO_ZERO) {
490: parse_error("invalid cmo.");
491: }
492: append_cmo_list(m, ob);
493: if (token != ',') {
494: break;
495: }
496: parse_comma();
497: }
498: }else if (!pflag_cmo_addrev) {
499: parse_error("invalid d-polynomial.");
500: }
501: parse_right_parenthesis();
502: return (cmo *)m;
503: }
504:
505:
1.2 ohara 506: static cmo *parse_cmo_error2()
507: {
508: cmo *ob;
509:
510: parse_comma();
511: parse_left_parenthesis();
512: ob = parse_cmo();
513: parse_right_parenthesis();
514: return (cmo *)new_cmo_error2(ob);
515: }
516:
1.1 ohara 517: /* --- 字句解析部 --- */
518:
519: /* lexical analyzer で読み飛ばされる文字なら何を初期値にしてもよい */
520: static int c = ' ';
521:
522: /* 一文字読み込む関数 */
523: static int (*GETC)() = getchar;
524:
525: int setgetc(int (*foo)())
526: {
527: GETC = foo;
528: }
529:
530: int resetgetc()
531: {
532: GETC = getchar;
533: }
534:
1.2 ohara 535: #define SIZE_BUFFER 8192
1.1 ohara 536: static char buffer[SIZE_BUFFER];
537:
538: /* 桁溢れの場合の対策はない */
539: static int lex_digit()
540: {
541: int d = 0;
542: do {
543: d = 10*d + (c - '0');
544: c = GETC();
545: } while(isdigit(c));
546: return d;
547: }
548:
549: /* バッファあふれした場合の対策をちゃんと考えるべき */
550: static char *lex_quoted_string()
551: {
552: int i;
553: char c0 = ' ';
554: char *s = NULL;
555: for (i=0; i<SIZE_BUFFER; i++) {
556: c = GETC();
557: if(c == '"') {
558: s = malloc(i+1);
559: buffer[i]='\0';
560: strcpy(s, buffer);
561:
562: c = GETC();
563: return s;
564: }else if (c == '\\') {
565: c0 = c;
566: c = GETC();
567: if (c != '"') {
568: buffer[i++] = c0;
569: }
570: }
571: buffer[i]=c;
572: }
573: fprintf(stderr, "buffer overflow!\n");
574: exit(1);
575: /* return NULL; */
576: }
577:
1.2 ohara 578: typedef struct {
579: char *key;
580: int token;
1.4 ! ohara 581: int op;
1.2 ohara 582: } symbol;
583:
1.4 ! ohara 584: #define MK_KEY_CMO(x) { #x , TOKEN(x) , 0}
! 585: #define MK_KEY_SM(x) { #x , TOKEN(SM) , x}
! 586: #define MK_KEY(x) { #x , TOKEN(x) , 0}
1.2 ohara 587:
588: static symbol symbol_list[] = {
1.3 ohara 589: MK_KEY_CMO(CMO_NULL),
590: MK_KEY_CMO(CMO_INT32),
591: MK_KEY_CMO(CMO_DATUM),
592: MK_KEY_CMO(CMO_STRING),
593: MK_KEY_CMO(CMO_MATHCAP),
594: MK_KEY_CMO(CMO_LIST),
595: MK_KEY_CMO(CMO_MONOMIAL32),
596: MK_KEY_CMO(CMO_ZZ),
597: MK_KEY_CMO(CMO_ZERO),
598: MK_KEY_CMO(CMO_DMS_GENERIC),
599: MK_KEY_CMO(CMO_RING_BY_NAME),
600: MK_KEY_CMO(CMO_INDETERMINATE),
601: MK_KEY_CMO(CMO_DISTRIBUTED_POLYNOMIAL),
602: MK_KEY_CMO(CMO_ERROR2),
1.4 ! ohara 603: MK_KEY_SM(SM_popCMO),
! 604: MK_KEY_SM(SM_popString),
! 605: MK_KEY_SM(SM_mathcap),
! 606: MK_KEY_SM(SM_pops),
! 607: MK_KEY_SM(SM_executeStringByLocalParser),
! 608: MK_KEY_SM(SM_executeFunction),
! 609: MK_KEY_SM(SM_setMathCap),
! 610: MK_KEY_SM(SM_control_kill),
! 611: MK_KEY_SM(SM_control_reset_connection),
! 612: MK_KEY(OX_COMMAND),
! 613: MK_KEY(OX_DATA),
1.2 ohara 614: {NULL, 0} /* a gate keeper */
615: };
616:
617: static int token_of_symbol(char *key)
618: {
619: symbol *kp;
620: for(kp = symbol_list; kp->key != NULL; kp++) {
621: if (strcmp(key, kp->key)==0) {
1.4 ! ohara 622: yylval.d = kp->op;
1.2 ohara 623: return kp->token;
624: }
625: }
626: #if DEBUG
1.1 ohara 627: fprintf(stderr, "lex error\n");
1.2 ohara 628: #endif
1.1 ohara 629: return 0;
630: }
631:
1.2 ohara 632: static int lex_symbol()
1.1 ohara 633: {
634: int i;
635: for (i=0; i<SIZE_BUFFER; i++) {
636: if (!isalnum(c) && c != '_') {
637: buffer[i]='\0';
1.2 ohara 638: return token_of_symbol(buffer);
1.1 ohara 639: }
640: buffer[i]=c;
641: c = GETC();
642: }
643: fprintf(stderr, "buffer overflow!\n");
1.2 ohara 644: return 0;
1.1 ohara 645: }
646:
647: /* return する前に一文字先読みしておく。 */
648: int lex()
649: {
650: int c_dash = 0;
651:
652: /* 空白をスキップする. */
653: while (isspace(c) && c != '\n') {
654: c = GETC();
655: }
656:
657: switch(c) {
658: case '(':
659: case ')':
660: case ',':
661: case '\n':
662: c_dash = c;
663: c = ' ';
664: return c_dash;
665: case EOF:
666: c = GETC();
667: return c_dash;
668: case '"': /* a quoted string! */
669: yylval.sym = lex_quoted_string();
670: return T_STRING;
671: default:
672: }
673:
674: if (isalpha(c)) { /* 識別子 */
1.2 ohara 675: return lex_symbol();
1.1 ohara 676: }
677:
678: /* 32bit 整数値 */
679: if (isdigit(c)){
680: yylval.d = lex_digit();
681: return T_INTEGER;
682: }
683: if (c == '-') {
684: c = GETC();
685: while (isspace(c) && c != '\n') {
686: c = GETC();
687: }
688: if (isdigit(c)){
689: yylval.d = - lex_digit();
690: return T_INTEGER;
691: }
692: return 0;
693: }
694:
695: c = GETC();
696: return 0;
697: }
698:
699: static char *mygetc_line;
700: static int mygetc_counter;
701: static int mygetc_counter_max;
702:
703: int mygetc()
704: {
705: if (mygetc_counter <= mygetc_counter_max) {
706: return mygetc_line[mygetc_counter++];
707: }
708: return 0;
709: }
710:
711: int setmode_mygetc(char *s, int len)
712: {
713: mygetc_counter=0;
714: mygetc_counter_max=len;
715: mygetc_line=s;
1.2 ohara 716: }
717:
718: int setflag_parse(int flag)
719: {
720: pflag_cmo_addrev = flag;
1.1 ohara 721: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>