=================================================================== RCS file: /home/cvs/OpenXM/src/ox_toolkit/parse.c,v retrieving revision 1.1 retrieving revision 1.16 diff -u -p -r1.1 -r1.16 --- OpenXM/src/ox_toolkit/parse.c 1999/12/09 22:44:56 1.1 +++ OpenXM/src/ox_toolkit/parse.c 2005/07/20 17:48:03 1.16 @@ -1,29 +1,33 @@ /* -*- mode: C; coding: euc-japan -*- */ -/* $OpenXM$ */ +/* $OpenXM: OpenXM/src/ox_toolkit/parse.c,v 1.15 2004/12/01 17:32:26 ohara Exp $ */ -/* OX expression, CMO expression パーサ */ +/* + This module is a parser for OX/CMO expressions. + Some commnets are written in Japanese by using the EUC-JP coded + character set. +*/ #include #include #include #include #include -#include "oxtag.h" -#include "ox.h" +#include + +#include "ox_toolkit.h" #include "parse.h" -/* --- 構文解析部 --- */ -/* (重要)セマンティックスについての注意. +/* --- Parser --- */ +/* Remarks for semantics. CMO_LIST, CMO_STRING は、あらかじめ与えられた要素の個数を無視する. CMO_MONOMIAL32 は無視しない. (つまりおかしいときは構文エラーになる) */ -/* parse.c, lex.c では, Lisp 表現された CMO 文字列を読み込み, +/* + parse.c では, Lisp 表現された CMO 文字列を読み込み, バイト列を出力する. 中間表現として、cmo 構造体を利用する. parse() はトークンの列から cmo 構造体を生成し、そのポインタを返す. -*/ - -/* 重要なことはパーサ(の各サブルーチン)は + 重要なことはパーサ(の各サブルーチン)は 常にトークンをひとつ先読みしていると言うことである. */ @@ -36,18 +40,22 @@ static union{ char *sym; } yylval; -/* pflag_cmo_addrev がセットされていれば、厳密には CMO expression では - ないもの, 例えば (CMO_STRING, "hello") も CMO に変換される. */ +/* + If `pflag_cmo_addrev' sets, then we admit extended CMO expressions. + For example, (CMO_STRING, "hello") is not a real CMO expression + but it is admitted. +*/ +static int pflag_cmo_addrev = 1; -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(); +/* definitions of local functions */ +static void init_parser(char *s); +static cmo *parse(); +static void parse_error(char *s); +static void parse_right_parenthesis(); +static void parse_left_parenthesis(); +static void parse_comma(); +static mpz_ptr parse_mpz_integer(); +static int parse_integer(); static char *parse_string(); static cmo *parse_cmo_null(); static cmo *parse_cmo_int32(); @@ -67,7 +75,15 @@ static int parse_sm(); static ox *parse_ox(); static ox *parse_ox_command(); static ox *parse_ox_data(); +static void init_lex(char *s); +static int lex(); +/* Parsing a Lisp-style expression of CMO. */ +cmo *ox_parse_lisp(char *s) +{ + return (s != NULL && strlen(s) > 0)? init_parser(s), parse(): NULL; +} + static int is_token_cmo(int token) { return (token >= MIN_T_CMO && token < MAX_T_CMO) || token == TOKEN(CMO_ERROR2); @@ -85,51 +101,43 @@ static int is_token_ox(int token) static jmp_buf env_parse; -/* 構文解析に失敗したことを意味する. */ -static int parse_error(char *s) +/* This is a parsing fault. */ +static void parse_error(char *s) { - fprintf(stderr, "syntax error: %s\n", s); + ox_printf("syntax error: %s\n", s); longjmp(env_parse, 1); } -/* この部分は書き換え予定. */ -cmo *parse() +static void setflag_parse(int flag) { - cmo *m; + pflag_cmo_addrev = flag; +} - if (setjmp(env_parse) != 0) { - return NULL; /* 構文解析に失敗したら NULL を返す. */ - } +static void init_parser(char *s) +{ + setflag_parse(PFLAG_ADDREV); + init_lex(s); +} - do{ +static cmo *parse() +{ + cmo *m = NULL; + if (setjmp(env_parse) == 0) { token = lex(); - }while (token == '\n'); - - if (token == '(') { - token = lex(); - if (is_token_cmo(token)) { - m = parse_cmo(); - }else if(is_token_ox(token)) { - m = parse_ox(); - }else { - parse_error("invalid symbol."); + if (token == '(') { + token = lex(); + if (is_token_cmo(token)) { + m = parse_cmo(); + }else if(is_token_ox(token)) { + m = parse_ox(); + }else { + parse_error("invalid symbol."); + } } - parse_lf(); - return m; } - return NULL; + return m; } -/* トークンを先読みしない(重要). */ -static int parse_lf() -{ - if (token != '\n') { - parse_error("no new line."); - } - return 0; -} - - static ox *parse_ox() { ox *m = NULL; @@ -183,9 +191,6 @@ static int parse_sm() return sm_code; } - -/* 正しい入力ならば, parse_cmo を呼ぶ時点で, token には - TOKEN(CMO_xxx), TOKEN(OX_xxx) のいずれかがセットされている. */ static cmo *parse_cmo() { cmo *m = NULL; @@ -249,7 +254,7 @@ static cmo *parse_cmo() return m; } -static int parse_left_parenthesis() +static void parse_left_parenthesis() { if (token != '(') { parse_error("no left parenthesis."); @@ -257,7 +262,7 @@ static int parse_left_parenthesis() token = lex(); } -static int parse_right_parenthesis() +static void parse_right_parenthesis() { if (token != ')') { parse_error("no right parenthesis."); @@ -265,7 +270,7 @@ static int parse_right_parenthesis() token = lex(); } -static int parse_comma() +static void parse_comma() { if (token != ',') { parse_error("no comma."); @@ -273,15 +278,66 @@ static int parse_comma() token = lex(); } +static mpz_ptr new_mpz_set_str(char *s) +{ + mpz_ptr z = MALLOC(sizeof(mpz_t)); + mpz_init_set_str(z, s, 10); + return z; +} + +static mpz_ptr my_mpz_neg(mpz_ptr src) +{ + mpz_ptr z = MALLOC(sizeof(mpz_t)); + mpz_init(z); + mpz_neg(z, src); + return z; +} + +static mpz_ptr parse_mpz_integer() +{ + int sign = 1; + mpz_ptr val; + + if (token == '+') { + token = lex(); + }else if (token == '-') { + sign = -1; + token = lex(); + } + + if (token != T_DIGIT) { + parse_error("no integer."); + } + val = new_mpz_set_str(yylval.sym); + if (sign == -1) { + val = my_mpz_neg(val); + } + token = lex(); + return val; +} + static int parse_integer() { +#if 0 + return mpz_get_si(parse_mpz_integer()); +#else + int sign = 1; int val; - if (token != T_INTEGER) { + + if (token == '+') { + token = lex(); + }else if (token == '-') { + sign = -1; + token = lex(); + } + + if (token != T_DIGIT) { parse_error("no integer."); } - val = yylval.d; + val = sign*atoi(yylval.sym); token = lex(); return val; +#endif } static char *parse_string() @@ -303,12 +359,12 @@ static cmo *parse_cmo_null() static cmo *parse_cmo_int32() { - int i; + int z; parse_comma(); - i = parse_integer(); + z = parse_integer(); parse_right_parenthesis(); - return (cmo *)new_cmo_int32(i); + return (cmo *)new_cmo_int32(z); } static cmo *parse_cmo_string() @@ -317,7 +373,7 @@ static cmo *parse_cmo_string() char *s; parse_comma(); - if (token == T_INTEGER) { + if (token == T_DIGIT) { parse_integer(); parse_comma(); }else if (!pflag_cmo_addrev) { @@ -342,15 +398,13 @@ static cmo *parse_cmo_mathcap() 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) { + if (token == T_DIGIT) { parse_integer(); parse_comma(); }else if (!pflag_cmo_addrev) { @@ -360,7 +414,7 @@ static cmo *parse_cmo_list() while(token == '(') { parse_left_parenthesis(); newcmo = parse_cmo(); - append_cmo_list(m, newcmo); + list_append(m, newcmo); if (token != ',') { break; } @@ -376,7 +430,6 @@ static cmo *parse_cmo_list() static cmo *parse_cmo_monomial32() { int size; - int *exps; int i; cmo_monomial32 *m; int tag; @@ -397,7 +450,8 @@ static cmo *parse_cmo_monomial32() m->coef = parse_cmo(); tag = m->coef->tag; - /* m->coef は CMO_ZZ 型か CMO_INT32 型でなければならない */ + /* semantics: + The tag of m->coef must be CMO_ZZ or CMO_INT32. */ if (tag != CMO_ZZ && tag != CMO_INT32) { parse_error("invalid cmo."); } @@ -405,16 +459,18 @@ static cmo *parse_cmo_monomial32() return (cmo *)m; } -/* cmo_zz の内部を直接いじる. */ +/* the following function rewrite internal data of mpz/cmo_zz. */ static cmo *parse_cmo_zz() { int length; int i=0; cmo_zz *m= NULL; + mpz_ptr z; parse_comma(); - length = parse_integer(); + z = parse_mpz_integer(); if (token == ',') { + length = mpz_get_si(z); m = new_cmo_zz_size(length); length = abs(length); @@ -423,7 +479,7 @@ static cmo *parse_cmo_zz() m->mpz->_mp_d[i] = parse_integer(); } }else if (pflag_cmo_addrev) { - m = new_cmo_zz_set_si(length); + m = new_cmo_zz_set_mpz(z); }else { parse_error("no comma."); } @@ -452,7 +508,7 @@ static cmo *parse_cmo_ring_by_name() parse_left_parenthesis(); ob = parse_cmo(); - /* ob は CMO_STRING 型でなければならない */ + /* The ob has a type of CMO_STRING. */ if (ob->tag != CMO_STRING) { parse_error("invalid cmo."); } @@ -462,8 +518,6 @@ static cmo *parse_cmo_ring_by_name() static cmo *parse_cmo_distributed_polynomial() { - int length=0; - int i=0; cmo_distributed_polynomial *m = new_cmo_distributed_polynomial(); cmo *ob; int tag; @@ -471,7 +525,7 @@ static cmo *parse_cmo_distributed_polynomial() if (token == ',') { parse_comma(); - if (token == T_INTEGER) { + if (token == T_DIGIT) { parse_integer(); parse_comma(); }else if (!pflag_cmo_addrev) { @@ -481,7 +535,7 @@ static cmo *parse_cmo_distributed_polynomial() parse_left_parenthesis(); m->ringdef = parse_cmo(); tag = m->ringdef->tag; - /* m->ringdef は DringDefinition でなければならない */ + /* m->ringdef needs to be a DringDefinition. */ if (tag != CMO_RING_BY_NAME && tag != CMO_DMS_GENERIC && tag != CMO_DMS_OF_N_VARIABLES) { parse_error("invalid cmo."); @@ -495,7 +549,7 @@ static cmo *parse_cmo_distributed_polynomial() if (ob->tag != CMO_MONOMIAL32 && ob->tag != CMO_ZERO) { parse_error("invalid cmo."); } - append_cmo_list((cmo_list *)m, ob); + list_append((cmo_list *)m, ob); if (token != ',') { break; } @@ -530,43 +584,58 @@ static cmo *parse_cmo_error2() return (cmo *)new_cmo_error2(ob); } -/* --- 字句解析部 --- */ +/* --- lexical analyzer --- */ -/* lexical analyzer で読み飛ばされる文字なら何を初期値にしてもよい */ +/* A white space is ignored by lexical analyzer. */ static int c = ' '; -/* 一文字読み込む関数 */ -static int (*GETC)() = getchar; - -int setgetc(int (*foo)()) +/* getting a character from string. */ +static char *mygetc_ptr; +static int mygetc() { - GETC = foo; + return *mygetc_ptr++; } -int resetgetc() +static void init_lex(char *s) { - GETC = getchar; + c=' '; + mygetc_ptr=s; } #define SIZE_BUFFER 8192 static char buffer[SIZE_BUFFER]; -/* 桁溢れの場合の対策はない */ -static int lex_digit() +static char *new_string(char *s) { - int d = 0; - do { - d = 10*d + (c - '0'); - c = GETC(); - } while(isdigit(c)); - return d; + char *t = MALLOC(strlen(s)+1); + strcpy(t, s); + return t; } +/* no measure for buffer overflow */ +static char *lex_digit() +{ + static char buff[SIZE_BUFFER]; + int i; + + for(i=0; ikey != NULL; symp++) { if (strcmp(key, symp->key)==0) { return symp; @@ -607,9 +676,9 @@ symbol* lookup_by_symbol(char *key) return NULL; } -symbol* lookup_by_token(int tok) +symbol_t lookup_by_token(int tok) { - symbol *symp; + symbol_t symp; for(symp = symbol_list; symp->key != NULL; symp++) { if (tok == symp->token) { return symp; @@ -618,9 +687,9 @@ symbol* lookup_by_token(int tok) return NULL; } -symbol* lookup_by_tag(int tag) +symbol_t lookup_by_tag(int tag) { - symbol *symp; + symbol_t symp; for(symp = symbol_list; symp->key != NULL; symp++) { if (tag == symp->tag) { return symp; @@ -629,50 +698,51 @@ symbol* lookup_by_tag(int tag) return NULL; } -symbol* lookup(int i) +symbol_t lookup(int i) { return &symbol_list[i]; } -/* バッファあふれした場合の対策をちゃんと考えるべき */ +char *get_symbol_by_tag(int tag) +{ + symbol_t symp = lookup_by_tag(tag); + return (symp != NULL)? symp->key: NULL; +} + +/* no measure for buffer overflow */ static char *lex_quoted_string() { int i; char c0 = ' '; - char *s = NULL; + for (i=0; itag; return symp->token; } -#if DEBUG - fprintf(stderr, "lex error:: \"%s\" is unknown symbol.\n", key); -#endif + ox_printf("lex error:: \"%s\" is unknown symbol.\n", key); return 0; } @@ -685,93 +755,51 @@ static int lex_symbol() return token_of_symbol(buffer); } buffer[i]=c; - c = GETC(); + c = mygetc(); } - fprintf(stderr, "buffer overflow!\n"); + ox_printf("buffer overflow!\n"); return 0; } -/* return する前に一文字先読みしておく. */ -int lex() +/* Remark: prefetching a character before return. */ +static int lex() { int c_dash = 0; - /* 空白をスキップする. */ - while (isspace(c) && c != '\n') { - c = GETC(); + /* white spaces are ignored. */ + while (isspace(c)) { + c = mygetc(); } switch(c) { case '(': case ')': case ',': - case '\n': + case '+': + case '-': c_dash = c; c = ' '; return c_dash; case EOF: - c = GETC(); + c = mygetc(); return c_dash; case '"': /* a quoted string! */ yylval.sym = lex_quoted_string(); return T_STRING; default: + ; } - if (isalpha(c)) { /* 識別子 */ + if (isalpha(c)) { + /* symbols */ return lex_symbol(); } - /* 32bit 整数値 */ + /* digit */ if (isdigit(c)){ - yylval.d = lex_digit(); - return T_INTEGER; + yylval.sym = lex_digit(); + return T_DIGIT; } - if (c == '-') { - c = GETC(); - while (isspace(c) && c != '\n') { - c = GETC(); - } - if (isdigit(c)){ - yylval.d = - lex_digit(); - return T_INTEGER; - } - return 0; - } - - c = GETC(); + c = mygetc(); return 0; -} - -/* 一文字読み込む関数 */ -static char *mygetc_line; -static int mygetc_counter; -static int mygetc_counter_max; -static int mygetc_nonlf_flag; - -int mygetc() -{ - int c = '\0'; - - if (mygetc_nonlf_flag && mygetc_counter <= mygetc_counter_max) { - c = mygetc_line[mygetc_counter++]; - if (c == '\0') { - c = '\n'; - mygetc_nonlf_flag = 0; - } - } - return c; -} - -int setmode_mygetc(char *s, int len) -{ - mygetc_nonlf_flag=1; - mygetc_counter=0; - mygetc_counter_max=len; - mygetc_line=s; -} - -int setflag_parse(int flag) -{ - pflag_cmo_addrev = flag; }