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