=================================================================== RCS file: /home/cvs/OpenXM/src/ox_math/Attic/parse.c,v retrieving revision 1.1 retrieving revision 1.7 diff -u -p -r1.1 -r1.7 --- OpenXM/src/ox_math/Attic/parse.c 1999/10/29 08:06:41 1.1 +++ OpenXM/src/ox_math/Attic/parse.c 1999/11/06 21:39:37 1.7 @@ -1,24 +1,26 @@ /* -*- mode: C; coding: euc-japan -*- */ -/* $OpenXM$ */ -/* $Id: parse.c,v 1.1 1999/10/29 08:06:41 ohara Exp $ */ +/* $OpenXM: OpenXM/src/ox_math/parse.c,v 1.6 1999/11/04 18:15:20 ohara Exp $ */ + /* OX expression, CMO expression パーサ */ -/* cmo_addrev がセットされていれば、 - 厳密には CMO expression でないもの, 例えば - (CMO_STRING, "abcdef") も CMO に変換される. */ - #include #include #include #include +#include #include "oxtag.h" #include "ox.h" #include "parse.h" /* --- 構文解析部 --- */ +/* (重要)セマンティックスについての注意. + CMO_LIST, CMO_STRING は、あらかじめ与えられた要素の個数を無視する. + CMO_MONOMIAL32 は無視しない. (つまりおかしいときは構文エラーになる) +*/ + /* parse.c, lex.c では, Lisp 表現された CMO 文字列を読み込み, - バイト列を出力する. 中間表現として、cmo *を利用する. - parse() はトークンの列から cmo *(の指す構造体)を生成する. + バイト列を出力する. 中間表現として、cmo 構造体を利用する. + parse() はトークンの列から cmo 構造体を生成し、そのポインタを返す. */ /* 重要なことはパーサ(の各サブルーチン)は @@ -28,62 +30,66 @@ /* 現在読み込み中のトークンを表す. */ static int token = 0; -/* yylval は lex() によってセットされる. */ -extern lex_value_t yylval; +/* トークンの属性値. yylval は lex() によってセットされる. */ +static union{ + int d; + char *sym; +} yylval; -int cmo_addrev = 1; /* CMO の省略記法を許すか否かのフラグ */ +/* pflag_cmo_addrev がセットされていれば、厳密には CMO expression では + ないもの, 例えば (CMO_STRING, "hello") も CMO に変換される. */ +static int pflag_cmo_addrev = 1; /* CMO の省略記法を許すか否かのフラグ */ + /* 関数の宣言 */ -static int parse_error(char *s); -static int parse_lf(); -static int parse_right_parenthesis(); -static int parse_left_parenthesis(); -static int parse_comma(); -static int parse_integer(); -static cmo *parse_cmo_null(); -static cmo *parse_cmo_zz(); -static cmo *parse_cmo_list(); -static cmo *parse_cmo_int32(); -static cmo *parse_cmo_string(); -static cmo *parse_cmo(); +static int parse_error(char *s); +static int parse_lf(); +static int parse_right_parenthesis(); +static int parse_left_parenthesis(); +static int parse_comma(); +static int parse_integer(); static char *parse_string(); -static int parse_sm(); -static ox* parse_ox(); -static ox* parse_ox_command(); -static ox* parse_ox_data(); +static cmo *parse_cmo_null(); +static cmo *parse_cmo_int32(); +static cmo *parse_cmo_string(); +static cmo *parse_cmo_mathcap(); +static cmo *parse_cmo_list(); +static cmo *parse_cmo_monomial32(); +static cmo *parse_cmo_zz(); +static cmo *parse_cmo_zero(); +static cmo *parse_cmo_dms_generic(); +static cmo *parse_cmo_ring_by_name(); +static cmo *parse_cmo_distributed_polynomial(); +static cmo *parse_cmo_indeterminate(); +static cmo *parse_cmo_error2(); +static cmo *parse_cmo(); +static int parse_sm(); +static ox *parse_ox(); +static ox *parse_ox_command(); +static ox *parse_ox_data(); -static int parse_error(char *s) +static int is_token_cmo(int token) { - if (s != NULL) { - fprintf(stderr, "%s\n", s); - }else { - fprintf(stderr, "syntax error.\n"); - } - exit(1); /* 例外処理. 本当は longjmp すべきであろう. */ + return (token >= MIN_T_CMO && token < MAX_T_CMO) || token == TOKEN(CMO_ERROR2); } -#define MIN_T_CMO (T_MAGIC + 0) -#define MAX_T_CMO (T_MAGIC + 256) - -static int is_t_cmo(int token) +static int is_token_sm(int token) { - return (token >= MIN_T_CMO && token < MAX_T_CMO) || token == T_CMO_ERROR2; + return token == TOKEN(SM); } -#define MIN_T_SM (T_MAGIC + 256) -#define MAX_T_SM (T_MAGIC + 1100) - -static int is_t_sm(int token) +static int is_token_ox(int token) { - return token >= MIN_T_SM && token < MAX_T_SM; + return token >= MIN_T_OX && token < MAX_T_OX; } -#define MIN_T_OX (T_MAGIC + 512) -#define MAX_T_OX (T_MAGIC + 600) +static jmp_buf env_parse; -static int is_t_ox(int token) +/* 構文解析に失敗したことを意味する. */ +static int parse_error(char *s) { - return token >= MIN_T_OX && token < MAX_T_OX; + fprintf(stderr, "syntax error: %s\n", s); + longjmp(env_parse, 1); } /* この部分は書き換え予定. */ @@ -91,19 +97,22 @@ cmo *parse() { cmo *m; + if (setjmp(env_parse) != 0) { + return NULL; /* 構文解析に失敗したら NULL を返す. */ + } + do{ token = lex(); }while (token == '\n'); if (token == '(') { token = lex(); - if (is_t_cmo(token)) { + if (is_token_cmo(token)) { m = parse_cmo(); - }else if(is_t_ox(token)) { + }else if(is_token_ox(token)) { m = parse_ox(); }else { - parse_error("syntax error: unknown keyword."); - return NULL; + parse_error("invalid symbol."); } parse_lf(); return m; @@ -115,34 +124,34 @@ cmo *parse() static int parse_lf() { if (token != '\n') { - parse_error("syntax error: not new line."); + parse_error("no new line."); } return 0; } -static ox* parse_ox() +static ox *parse_ox() { ox *m = NULL; switch(token) { - case T_OX_COMMAND: + case TOKEN(OX_COMMAND): token = lex(); m = parse_ox_command(); break; - case T_OX_DATA: + case TOKEN(OX_DATA): token = lex(); m = parse_ox_data(); break; default: - parse_error("syntax error: invalid ox_tag."); + parse_error("invalid ox."); } return m; } -static ox* parse_ox_data() +static ox *parse_ox_data() { - ox* m; + ox *m; parse_comma(); parse_left_parenthesis(); @@ -151,75 +160,107 @@ static ox* parse_ox_data() return m; } +static ox *parse_ox_command() +{ + ox *m; + + parse_comma(); + parse_left_parenthesis(); + m = (ox *)new_ox_command(parse_sm()); + parse_right_parenthesis(); + return m; +} + static int parse_sm() { int sm_code; - if (!is_t_sm(token)) { - parse_error("syntax error: invalid sm code."); + if (token != TOKEN(SM)) { + parse_error("no opecode."); } - sm_code = token - T_MAGIC; + sm_code = yylval.d; token = lex(); + parse_right_parenthesis(); return sm_code; } -static ox* parse_ox_command() -{ - ox* m; - - parse_comma(); - m = (ox *)new_ox_command(parse_sm()); - parse_right_parenthesis(); - return m; -} - /* 正しい入力ならば, parse_cmo を呼ぶ時点で, token には - T_CMO_xxx, T_OX_xxx のいずれかがセットされている. */ + TOKEN(CMO_xxx), TOKEN(OX_xxx) のいずれかがセットされている. */ static cmo *parse_cmo() { cmo *m = NULL; switch(token) { - case T_CMO_NULL: + case TOKEN(CMO_NULL): token = lex(); m = parse_cmo_null(); break; - case T_CMO_INT32: + case TOKEN(CMO_INT32): token = lex(); m = parse_cmo_int32(); break; - case T_CMO_STRING: + case TOKEN(CMO_STRING): token = lex(); m = parse_cmo_string(); break; - case T_CMO_ZZ: + case TOKEN(CMO_MATHCAP): token = lex(); - m = parse_cmo_zz(); + m = parse_cmo_mathcap(); break; - case T_CMO_LIST: + case TOKEN(CMO_LIST): token = lex(); m = parse_cmo_list(); break; + case TOKEN(CMO_MONOMIAL32): + token = lex(); + m = parse_cmo_monomial32(); + break; + case TOKEN(CMO_ZZ): + token = lex(); + m = parse_cmo_zz(); + break; + case TOKEN(CMO_ZERO): + token = lex(); + m = parse_cmo_zero(); + break; + case TOKEN(CMO_DMS_GENERIC): + token = lex(); + m = parse_cmo_dms_generic(); + break; + case TOKEN(CMO_RING_BY_NAME): + token = lex(); + m = parse_cmo_ring_by_name(); + break; + case TOKEN(CMO_DISTRIBUTED_POLYNOMIAL): + token = lex(); + m = parse_cmo_distributed_polynomial(); + break; + case TOKEN(CMO_INDETERMINATE): + token = lex(); + m = parse_cmo_indeterminate(); + break; + case TOKEN(CMO_ERROR2): + token = lex(); + m = parse_cmo_error2(); + break; default: - parse_error("syntax error: invalid cmo_tag."); + parse_error("invalid cmo."); } return m; } -static int parse_right_parenthesis() +static int parse_left_parenthesis() { - if (token != ')') { - parse_error("syntax error: no right parenthesis exists."); - return 0; + if (token != '(') { + parse_error("no left parenthesis."); } token = lex(); } -static int parse_left_parenthesis() +static int parse_right_parenthesis() { - if (token != '(') { - parse_error("syntax error: no left parenthesis exists."); - return 0; + if (token != ')') { + parse_error("no right parenthesis."); } token = lex(); } @@ -227,13 +268,143 @@ static int parse_left_parenthesis() static int parse_comma() { if (token != ',') { - parse_error("syntax error: no comma exists."); - return 0; + parse_error("no comma."); } token = lex(); - return 1; } +static int parse_integer() +{ + int val; + if (token != T_INTEGER) { + parse_error("no integer."); + } + val = yylval.d; + token = lex(); + return val; +} + +static char *parse_string() +{ + char *s; + if (token != T_STRING) { + parse_error("no string."); + } + s = yylval.sym; + token = lex(); + return s; +} + +static cmo *parse_cmo_null() +{ + parse_right_parenthesis(); + return (cmo *)new_cmo_null(); +} + +static cmo *parse_cmo_int32() +{ + int i; + + parse_comma(); + i = parse_integer(); + parse_right_parenthesis(); + return (cmo *)new_cmo_int32(i); +} + +static cmo *parse_cmo_string() +{ + cmo_string *m; + char *s; + + parse_comma(); + if (token == T_INTEGER) { + parse_integer(); + parse_comma(); + }else if (!pflag_cmo_addrev) { + parse_error("invalid cmo string."); + } + s = parse_string(); + m = new_cmo_string(s); + parse_right_parenthesis(); + return (cmo *)m; +} + +static cmo *parse_cmo_mathcap() +{ + cmo *ob; + + parse_comma(); + parse_left_parenthesis(); + ob = parse_cmo(); + parse_right_parenthesis(); + return (cmo *)new_cmo_mathcap(ob); +} + +static cmo *parse_cmo_list() +{ + int length=0; + int i=0; + cmo_list *m = new_cmo_list(); + cmo *newcmo; + + if (token == ',') { + parse_comma(); + + if (token == T_INTEGER) { + parse_integer(); + parse_comma(); + }else if (!pflag_cmo_addrev) { + parse_error("invalid cmo_list."); + } + + while(token == '(') { + parse_left_parenthesis(); + newcmo = parse_cmo(); + append_cmo_list(m, newcmo); + if (token != ',') { + break; + } + parse_comma(); + } + }else if (!pflag_cmo_addrev) { + parse_error("invalid cmo_list."); + } + parse_right_parenthesis(); + return (cmo *)m; +} + +static cmo *parse_cmo_monomial32() +{ + int size; + int *exps; + int i; + cmo_monomial32 *m; + int tag; + + parse_comma(); + size = parse_integer(); + if (size < 0) { + parse_error("invalid value."); + } + m = new_cmo_monomial32_size(size); + + for(i=0; iexps[i] = parse_integer(); + } + parse_comma(); + parse_left_parenthesis(); + m->coef = parse_cmo(); + tag = m->coef->tag; + + /* m->coef は CMO_ZZ 型か CMO_INT32 型でなければならない */ + if (tag != CMO_ZZ && tag != CMO_INT32) { + parse_error("invalid cmo."); + } + parse_right_parenthesis(); + return (cmo *)m; +} + /* cmo_zz の内部を直接いじる. */ static cmo *parse_cmo_zz() { @@ -251,110 +422,116 @@ static cmo *parse_cmo_zz() parse_comma(); m->mpz->_mp_d[i] = parse_integer(); } - }else if (cmo_addrev) { + }else if (pflag_cmo_addrev) { m = new_cmo_zz_set_si(length); }else { - parse_error("syntax error: invalid keyword."); + parse_error("no comma."); } parse_right_parenthesis(); return (cmo *)m; } -static cmo *parse_cmo_list() +static cmo *parse_cmo_zero() { - int length=0; - int i=0; - cmo_list *m; - cmo *newcmo; - - parse_comma(); - - length = parse_integer(); - m = new_cmo_list(); - if (length<0) { - parse_error("semantics error: a list has negative length."); - } - - for(i=0; itag != CMO_STRING) { + parse_error("invalid cmo."); + } + parse_right_parenthesis(); + return (cmo *)new_cmo_ring_by_name(ob); } -static cmo *parse_cmo_null() +static cmo *parse_cmo_distributed_polynomial() { - cmo_null *m = new_cmo_null(); + int length=0; + int i=0; + cmo_distributed_polynomial *m = new_cmo_distributed_polynomial(); + cmo *ob; + int tag; + + if (token == ',') { + parse_comma(); + + if (token == T_INTEGER) { + parse_integer(); + parse_comma(); + }else if (!pflag_cmo_addrev) { + parse_error("invalid d-polynomial."); + } + + parse_left_parenthesis(); + m->ringdef = parse_cmo(); + tag = m->ringdef->tag; + /* m->ringdef は DringDefinition でなければならない */ + if (tag != CMO_RING_BY_NAME && tag != CMO_DMS_GENERIC + && tag != CMO_DMS_OF_N_VARIABLES) { + parse_error("invalid cmo."); + } + + parse_comma(); + + while(token == '(') { + parse_left_parenthesis(); + ob = parse_cmo(); + if (ob->tag != CMO_MONOMIAL32 && ob->tag != CMO_ZERO) { + parse_error("invalid cmo."); + } + append_cmo_list((cmo_list *)m, ob); + if (token != ',') { + break; + } + parse_comma(); + } + }else if (!pflag_cmo_addrev) { + parse_error("invalid d-polynomial."); + } parse_right_parenthesis(); return (cmo *)m; } -static cmo *parse_cmo_int32() +static cmo *parse_cmo_indeterminate() { - cmo_int32 *m; - int i; + cmo *ob; parse_comma(); - i = parse_integer(); - m = new_cmo_int32(i); + parse_left_parenthesis(); + ob = parse_cmo(); parse_right_parenthesis(); - return (cmo *)m; + return (cmo *)new_cmo_indeterminate(ob); } -static cmo *parse_cmo_string() +static cmo *parse_cmo_error2() { - cmo_string *m; - int length; - char *s; + cmo *ob; parse_comma(); - if (token == T_INTEGER) { - length = parse_integer(); - parse_comma(); - s = parse_string(); - if (length != strlen(s)) { - fprintf(stderr, "warning: strlen unmatched.\n"); - } - }else if (cmo_addrev) { - s = parse_string(); - }else { - parse_error("syntax error: invalid keyword."); - } - m = new_cmo_string(s); + parse_left_parenthesis(); + ob = parse_cmo(); parse_right_parenthesis(); - return (cmo *)m; + return (cmo *)new_cmo_error2(ob); } /* --- 字句解析部 --- */ -lex_value_t yylval; - /* lexical analyzer で読み飛ばされる文字なら何を初期値にしてもよい */ static int c = ' '; @@ -371,9 +548,8 @@ int resetgetc() GETC = getchar; } -#define SIZE_BUFFER 1024 +#define SIZE_BUFFER 8192 static char buffer[SIZE_BUFFER]; -static char* PARS = "(),\n"; /* 桁溢れの場合の対策はない */ static int lex_digit() @@ -386,6 +562,77 @@ static int lex_digit() return d; } +#define MK_KEY_CMO(x) { #x , x , TOKEN(x) , IS_CMO } +#define MK_KEY_SM(x) { #x , x , TOKEN(SM) , IS_SM } +#define MK_KEY_OX(x) { #x , x , TOKEN(x) , IS_OX } + +static symbol symbol_list[] = { + MK_KEY_CMO(CMO_NULL), + MK_KEY_CMO(CMO_INT32), + MK_KEY_CMO(CMO_DATUM), + MK_KEY_CMO(CMO_STRING), + MK_KEY_CMO(CMO_MATHCAP), + MK_KEY_CMO(CMO_LIST), + MK_KEY_CMO(CMO_MONOMIAL32), + MK_KEY_CMO(CMO_ZZ), + MK_KEY_CMO(CMO_ZERO), + MK_KEY_CMO(CMO_DMS_GENERIC), + MK_KEY_CMO(CMO_RING_BY_NAME), + MK_KEY_CMO(CMO_INDETERMINATE), + MK_KEY_CMO(CMO_DISTRIBUTED_POLYNOMIAL), + MK_KEY_CMO(CMO_ERROR2), + MK_KEY_SM(SM_popCMO), + MK_KEY_SM(SM_popString), + MK_KEY_SM(SM_mathcap), + MK_KEY_SM(SM_pops), + MK_KEY_SM(SM_executeStringByLocalParser), + MK_KEY_SM(SM_executeFunction), + MK_KEY_SM(SM_setMathCap), + MK_KEY_SM(SM_control_kill), + MK_KEY_SM(SM_control_reset_connection), + MK_KEY_OX(OX_COMMAND), + MK_KEY_OX(OX_DATA), + {NULL, 0, 0, 0} /* a gate keeper */ +}; + +symbol* lookup_by_symbol(char *key) +{ + symbol *symp; + for(symp = symbol_list; symp->key != NULL; symp++) { + if (strcmp(key, symp->key)==0) { + return symp; + } + } + return NULL; +} + +symbol* lookup_by_token(int tok) +{ + symbol *symp; + for(symp = symbol_list; symp->key != NULL; symp++) { + if (tok == symp->token) { + return symp; + } + } + return NULL; +} + +symbol* lookup_by_tag(int tag) +{ + symbol *symp; + for(symp = symbol_list; symp->key != NULL; symp++) { + if (tag == symp->tag) { + return symp; + } + } + return NULL; +} + +symbol* lookup(int i) +{ + return &symbol_list[i]; +} + /* バッファあふれした場合の対策をちゃんと考えるべき */ static char *lex_quoted_string() { @@ -415,60 +662,35 @@ static char *lex_quoted_string() /* return NULL; */ } -/* キーワードを増やしたあと修正するのを忘れてはいけない */ -#undef NUM_OF_KEYWORDS 18 - -static char *keywords[] = { - "CMO_INT32", "CMO_STRING", "CMO_LIST", "CMO_ZZ", "CMO_NULL", - "CMO_ZERO", "CMO_DATUM", - "SM_popCMO", "SM_popString", "SM_mathcap", "SM_pops", - "SM_executeStringByLocalParser", "SM_executeFunction", - "SM_setMathcap", - "SM_control_kill", "SM_control_reset_connection", - "OX_COMMAND", "OX_DATA", - NULL /* a gate keeper */ -}; - -static int token_of_keyword[] = { - T_CMO_INT32, T_CMO_STRING, T_CMO_LIST, T_CMO_ZZ, T_CMO_NULL, - T_CMO_ZERO, T_CMO_DATUM, - T_SM_popCMO, T_SM_popString, T_SM_mathcap, T_SM_pops, - T_SM_executeStringByLocalParser, T_SM_executeFunction, - T_SM_setMathcap, - T_SM_control_kill, T_SM_control_reset_connection, - T_OX_COMMAND, T_OX_DATA, - 0 /* dummy */ -}; - -static int token_of_matched_keyword(char *key) +static int token_of_symbol(char *key) { - int i; - - for(i=0; keywords[i] != NULL; i++) { - if(strcmp(key, keywords[i])==0) { - return token_of_keyword[i]; - } - } - fprintf(stderr, "lex error\n"); + symbol *symp = lookup_by_symbol(key); + if (symp != NULL) { + yylval.d = symp->tag; + return symp->token; + } +#if DEBUG + fprintf(stderr, "lex error:: \"%s\" is unknown symbol.\n", key); +#endif return 0; } -static int lex_keyword() +static int lex_symbol() { int i; for (i=0; i