| version 1.2, 1999/12/22 11:26:37 | version 1.12, 2003/03/23 22:09:57 | 
|  |  | 
| /* -*- mode: C; coding: euc-japan -*- */ | /* -*- mode: C; coding: euc-japan -*- */ | 
| /* $OpenXM: OpenXM/src/ox_toolkit/parse.c,v 1.1 1999/12/09 22:44:56 ohara Exp $ */ | /* $OpenXM: OpenXM/src/ox_toolkit/parse.c,v 1.11 2003/03/23 20:17:35 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 <stdio.h> | #include <stdio.h> | 
| #include <stdlib.h> | #include <stdlib.h> | 
| #include <string.h> | #include <string.h> | 
| #include <sys/param.h> | #include <sys/param.h> | 
| #include <setjmp.h> | #include <setjmp.h> | 
| #include "oxtag.h" | #include <ctype.h> | 
| #include "ox.h" |  | 
|  | #include "ox_toolkit.h" | 
| #include "parse.h" | #include "parse.h" | 
|  |  | 
| /* --- 構文解析部 --- */ | /* --- Parser --- */ | 
| /* (重要)セマンティックスについての注意. | /* Remarks for semantics. | 
| CMO_LIST, CMO_STRING は、あらかじめ与えられた要素の個数を無視する. | CMO_LIST, CMO_STRING は、あらかじめ与えられた要素の個数を無視する. | 
| CMO_MONOMIAL32 は無視しない. (つまりおかしいときは構文エラーになる) | CMO_MONOMIAL32 は無視しない. (つまりおかしいときは構文エラーになる) | 
| */ | */ | 
|  |  | 
| /* parse.c, lex.c では, Lisp 表現された CMO 文字列を読み込み, | /* | 
|  | parse.c では, Lisp 表現された CMO 文字列を読み込み, | 
| バイト列を出力する.  中間表現として、cmo 構造体を利用する. | バイト列を出力する.  中間表現として、cmo 構造体を利用する. | 
| parse() はトークンの列から cmo 構造体を生成し、そのポインタを返す. | parse() はトークンの列から cmo 構造体を生成し、そのポインタを返す. | 
| */ | 重要なことはパーサ(の各サブルーチン)は | 
|  |  | 
| /* 重要なことはパーサ(の各サブルーチン)は |  | 
| 常にトークンをひとつ先読みしていると言うことである. | 常にトークンをひとつ先読みしていると言うことである. | 
| */ | */ | 
|  |  | 
|  |  | 
| char *sym; | char *sym; | 
| } yylval; | } 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 の省略記法を許すか否かのフラグ */ | /* definitions of local functions */ | 
|  | static void parse_error(char *s); | 
| /* 関数の宣言 */ | static void parse_right_parenthesis(); | 
| static int  parse_error(char *s); | static void parse_left_parenthesis(); | 
| static int  parse_lf(); | static void parse_comma(); | 
| static int  parse_right_parenthesis(); | #if defined(WITH_GMP) | 
| static int  parse_left_parenthesis(); | static mpz_ptr parse_mpz_integer(); | 
| static int  parse_comma(); | #endif /* WITH_GMP */ | 
| static int  parse_integer(); | static int   parse_integer(); | 
| static char *parse_string(); | static char *parse_string(); | 
| static cmo  *parse_cmo_null(); | static cmo  *parse_cmo_null(); | 
| static cmo  *parse_cmo_int32(); | static cmo  *parse_cmo_int32(); | 
| 
| Line 55  static cmo  *parse_cmo_string(); |  | 
| Line 63  static cmo  *parse_cmo_string(); |  | 
| static cmo  *parse_cmo_mathcap(); | static cmo  *parse_cmo_mathcap(); | 
| static cmo  *parse_cmo_list(); | static cmo  *parse_cmo_list(); | 
| static cmo  *parse_cmo_monomial32(); | static cmo  *parse_cmo_monomial32(); | 
|  | #if defined(WITH_GMP) | 
| static cmo  *parse_cmo_zz(); | static cmo  *parse_cmo_zz(); | 
|  | #endif /* WITH_GMP */ | 
| static cmo  *parse_cmo_zero(); | static cmo  *parse_cmo_zero(); | 
| static cmo  *parse_cmo_dms_generic(); | static cmo  *parse_cmo_dms_generic(); | 
| static cmo  *parse_cmo_ring_by_name(); | static cmo  *parse_cmo_ring_by_name(); | 
| 
| Line 67  static int  parse_sm(); |  | 
| Line 77  static int  parse_sm(); |  | 
| static ox   *parse_ox(); | static ox   *parse_ox(); | 
| static ox   *parse_ox_command(); | static ox   *parse_ox_command(); | 
| static ox   *parse_ox_data(); | static ox   *parse_ox_data(); | 
|  | static void init_lex(char *s); | 
|  | static int  lex(); | 
|  |  | 
|  |  | 
| static int is_token_cmo(int token) | static int is_token_cmo(int token) | 
| { | { | 
| return (token >= MIN_T_CMO && token < MAX_T_CMO) || token == TOKEN(CMO_ERROR2); | return (token >= MIN_T_CMO && token < MAX_T_CMO) || token == TOKEN(CMO_ERROR2); | 
| 
| Line 85  static int is_token_ox(int token) |  | 
| Line 98  static int is_token_ox(int token) |  | 
|  |  | 
| static jmp_buf env_parse; | static jmp_buf env_parse; | 
|  |  | 
| /* 構文解析に失敗したことを意味する. */ | /* This is a parsing fault. */ | 
| static int parse_error(char *s) | static void parse_error(char *s) | 
| { | { | 
| fprintf(stderr, "syntax error: %s\n", s); | ox_printf("syntax error: %s\n", s); | 
| longjmp(env_parse, 1); | longjmp(env_parse, 1); | 
| } | } | 
|  |  | 
| int setflag_parse(int flag) | void setflag_parse(int flag) | 
| { | { | 
| pflag_cmo_addrev = flag; | pflag_cmo_addrev = flag; | 
| } | } | 
|  |  | 
| int init_parser(char *s) | void init_parser(char *s) | 
| { | { | 
| setflag_parse(PFLAG_ADDREV); | setflag_parse(PFLAG_ADDREV); | 
| setmode_mygetc(s); | init_lex(s); | 
| } | } | 
|  |  | 
| /* この部分は書き換え予定. */ |  | 
| cmo *parse() | cmo *parse() | 
| { | { | 
| cmo *m; | cmo *m; | 
|  |  | 
| if (setjmp(env_parse) != 0) { | if (setjmp(env_parse) != 0) { | 
| return NULL; /* 構文解析に失敗したら NULL を返す. */ | return NULL; | 
|  | /* This is an error. */ | 
| } | } | 
|  |  | 
| do{ | token = lex(); | 
| token = lex(); |  | 
| }while (token == '\n'); |  | 
|  |  | 
| if (token == '(') { | if (token == '(') { | 
| token = lex(); | token = lex(); | 
| if (is_token_cmo(token)) { | if (is_token_cmo(token)) { | 
|  |  | 
| }else { | }else { | 
| parse_error("invalid symbol."); | parse_error("invalid symbol."); | 
| } | } | 
| /*      parse_lf(); */ |  | 
| return m; | return m; | 
| } | } | 
| return NULL; | return NULL; | 
| } | } | 
|  |  | 
| /* トークンを先読みしない(重要). */ |  | 
| static int parse_lf() |  | 
| { |  | 
| if (token != '\n') { |  | 
| parse_error("no new line."); |  | 
| } |  | 
| return 0; |  | 
| } |  | 
|  |  | 
|  |  | 
| static ox *parse_ox() | static ox *parse_ox() | 
| { | { | 
| ox *m = NULL; | ox *m = NULL; | 
| 
| Line 194  static int parse_sm() |  | 
| Line 193  static int parse_sm() |  | 
| return sm_code; | return sm_code; | 
| } | } | 
|  |  | 
|  |  | 
| /* 正しい入力ならば, parse_cmo を呼ぶ時点で, token には |  | 
| TOKEN(CMO_xxx), TOKEN(OX_xxx) のいずれかがセットされている. */ |  | 
| static cmo *parse_cmo() | static cmo *parse_cmo() | 
| { | { | 
| cmo *m = NULL; | cmo *m = NULL; | 
| 
| Line 226  static cmo *parse_cmo() |  | 
| Line 222  static cmo *parse_cmo() |  | 
| token = lex(); | token = lex(); | 
| m = parse_cmo_monomial32(); | m = parse_cmo_monomial32(); | 
| break; | break; | 
|  | #if defined(WITH_GMP) | 
| case TOKEN(CMO_ZZ): | case TOKEN(CMO_ZZ): | 
| token = lex(); | token = lex(); | 
| m = parse_cmo_zz(); | m = parse_cmo_zz(); | 
| break; | break; | 
|  | #endif /* WITH_GMP */ | 
| case TOKEN(CMO_ZERO): | case TOKEN(CMO_ZERO): | 
| token = lex(); | token = lex(); | 
| m = parse_cmo_zero(); | m = parse_cmo_zero(); | 
| 
| Line 260  static cmo *parse_cmo() |  | 
| Line 258  static cmo *parse_cmo() |  | 
| return m; | return m; | 
| } | } | 
|  |  | 
| static int parse_left_parenthesis() | static void parse_left_parenthesis() | 
| { | { | 
| if (token != '(') { | if (token != '(') { | 
| parse_error("no left parenthesis."); | parse_error("no left parenthesis."); | 
| 
| Line 268  static int parse_left_parenthesis() |  | 
| Line 266  static int parse_left_parenthesis() |  | 
| token = lex(); | token = lex(); | 
| } | } | 
|  |  | 
| static int parse_right_parenthesis() | static void parse_right_parenthesis() | 
| { | { | 
| if (token != ')') { | if (token != ')') { | 
| parse_error("no right parenthesis."); | parse_error("no right parenthesis."); | 
| 
| Line 276  static int parse_right_parenthesis() |  | 
| Line 274  static int parse_right_parenthesis() |  | 
| token = lex(); | token = lex(); | 
| } | } | 
|  |  | 
| static int parse_comma() | static void parse_comma() | 
| { | { | 
| if (token != ',') { | if (token != ',') { | 
| parse_error("no comma."); | parse_error("no comma."); | 
| 
| Line 284  static int parse_comma() |  | 
| Line 282  static int parse_comma() |  | 
| token = lex(); | token = lex(); | 
| } | } | 
|  |  | 
|  | #if defined(WITH_GMP) | 
|  | 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); | 
|  | #ifdef DEBUG | 
|  | free(src); | 
|  | #endif | 
|  | 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); | 
|  | } | 
|  | #ifdef DEBUG | 
|  | free(yylval.sym); | 
|  | #endif | 
|  | token = lex(); | 
|  | return val; | 
|  | } | 
|  | #endif /* WITH_GMP */ | 
|  |  | 
| static int parse_integer() | static int parse_integer() | 
| { | { | 
|  | #if defined(WITH_GMP) | 
|  | return mpz_get_si(parse_mpz_integer()); | 
|  | #else | 
|  | int sign = 1; | 
| int val; | 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."); | parse_error("no integer."); | 
| } | } | 
| val = yylval.d; | val = sign*atoi(yylval.sym); | 
|  | #ifdef DEBUG | 
|  | free(yylval.sym); | 
|  | #endif | 
| token = lex(); | token = lex(); | 
| return val; | return val; | 
|  | #endif | 
| } | } | 
|  |  | 
| static char *parse_string() | static char *parse_string() | 
| 
| Line 314  static cmo *parse_cmo_null() |  | 
| Line 374  static cmo *parse_cmo_null() |  | 
|  |  | 
| static cmo *parse_cmo_int32() | static cmo *parse_cmo_int32() | 
| { | { | 
| int i; | int z; | 
|  |  | 
| parse_comma(); | parse_comma(); | 
| i = parse_integer(); | z = parse_integer(); | 
| parse_right_parenthesis(); | parse_right_parenthesis(); | 
| return (cmo *)new_cmo_int32(i); | return (cmo *)new_cmo_int32(z); | 
| } | } | 
|  |  | 
| static cmo *parse_cmo_string() | static cmo *parse_cmo_string() | 
| 
| Line 328  static cmo *parse_cmo_string() |  | 
| Line 388  static cmo *parse_cmo_string() |  | 
| char *s; | char *s; | 
|  |  | 
| parse_comma(); | parse_comma(); | 
| if (token == T_INTEGER) { | if (token == T_DIGIT) { | 
| parse_integer(); | parse_integer(); | 
| parse_comma(); | parse_comma(); | 
| }else if (!pflag_cmo_addrev) { | }else if (!pflag_cmo_addrev) { | 
| 
| Line 353  static cmo *parse_cmo_mathcap() |  | 
| Line 413  static cmo *parse_cmo_mathcap() |  | 
|  |  | 
| static cmo *parse_cmo_list() | static cmo *parse_cmo_list() | 
| { | { | 
| int length=0; |  | 
| int i=0; |  | 
| cmo_list *m = new_cmo_list(); | cmo_list *m = new_cmo_list(); | 
| cmo *newcmo; | cmo *newcmo; | 
|  |  | 
| if (token == ',') { | if (token == ',') { | 
| parse_comma(); | parse_comma(); | 
|  |  | 
| if (token == T_INTEGER) { | if (token == T_DIGIT) { | 
| parse_integer(); | parse_integer(); | 
| parse_comma(); | parse_comma(); | 
| }else if (!pflag_cmo_addrev) { | }else if (!pflag_cmo_addrev) { | 
| 
| Line 371  static cmo *parse_cmo_list() |  | 
| Line 429  static cmo *parse_cmo_list() |  | 
| while(token == '(') { | while(token == '(') { | 
| parse_left_parenthesis(); | parse_left_parenthesis(); | 
| newcmo = parse_cmo(); | newcmo = parse_cmo(); | 
| append_cmo_list(m, newcmo); | list_append(m, newcmo); | 
| if (token != ',') { | if (token != ',') { | 
| break; | break; | 
| } | } | 
| 
| Line 387  static cmo *parse_cmo_list() |  | 
| Line 445  static cmo *parse_cmo_list() |  | 
| static cmo *parse_cmo_monomial32() | static cmo *parse_cmo_monomial32() | 
| { | { | 
| int size; | int size; | 
| int *exps; |  | 
| int i; | int i; | 
| cmo_monomial32 *m; | cmo_monomial32 *m; | 
| int tag; | int tag; | 
| 
| Line 408  static cmo *parse_cmo_monomial32() |  | 
| Line 465  static cmo *parse_cmo_monomial32() |  | 
| m->coef = parse_cmo(); | m->coef = parse_cmo(); | 
| tag = m->coef->tag; | 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) { | if (tag != CMO_ZZ && tag != CMO_INT32) { | 
| parse_error("invalid cmo."); | parse_error("invalid cmo."); | 
| } | } | 
| 
| Line 416  static cmo *parse_cmo_monomial32() |  | 
| Line 474  static cmo *parse_cmo_monomial32() |  | 
| return (cmo *)m; | return (cmo *)m; | 
| } | } | 
|  |  | 
| /* cmo_zz の内部を直接いじる. */ | #if defined(WITH_GMP) | 
|  | /* the following function rewrite internal data of mpz/cmo_zz. */ | 
| static cmo *parse_cmo_zz() | static cmo *parse_cmo_zz() | 
| { | { | 
| int length; | int length; | 
| int i=0; | int i=0; | 
| cmo_zz *m= NULL; | cmo_zz *m= NULL; | 
|  | mpz_ptr z; | 
|  |  | 
| parse_comma(); | parse_comma(); | 
| length = parse_integer(); | z = parse_mpz_integer(); | 
| if (token == ',') { | if (token == ',') { | 
|  | length = mpz_get_si(z); | 
| m = new_cmo_zz_size(length); | m = new_cmo_zz_size(length); | 
|  |  | 
| length = abs(length); | length = abs(length); | 
| 
| Line 434  static cmo *parse_cmo_zz() |  | 
| Line 495  static cmo *parse_cmo_zz() |  | 
| m->mpz->_mp_d[i] = parse_integer(); | m->mpz->_mp_d[i] = parse_integer(); | 
| } | } | 
| }else if (pflag_cmo_addrev) { | }else if (pflag_cmo_addrev) { | 
| m = new_cmo_zz_set_si(length); | m = new_cmo_zz_set_mpz(z); | 
| }else { | }else { | 
| parse_error("no comma."); | parse_error("no comma."); | 
| } | } | 
| 
| Line 442  static cmo *parse_cmo_zz() |  | 
| Line 503  static cmo *parse_cmo_zz() |  | 
| parse_right_parenthesis(); | parse_right_parenthesis(); | 
| return (cmo *)m; | return (cmo *)m; | 
| } | } | 
|  | #endif /* WITH_GMP */ | 
|  |  | 
| static cmo *parse_cmo_zero() | static cmo *parse_cmo_zero() | 
| { | { | 
| 
| Line 463  static cmo *parse_cmo_ring_by_name() |  | 
| Line 525  static cmo *parse_cmo_ring_by_name() |  | 
| parse_left_parenthesis(); | parse_left_parenthesis(); | 
| ob = parse_cmo(); | ob = parse_cmo(); | 
|  |  | 
| /* ob は CMO_STRING 型でなければならない */ | /* The ob has a type of CMO_STRING. */ | 
| if (ob->tag != CMO_STRING) { | if (ob->tag != CMO_STRING) { | 
| parse_error("invalid cmo."); | parse_error("invalid cmo."); | 
| } | } | 
| 
| Line 473  static cmo *parse_cmo_ring_by_name() |  | 
| Line 535  static cmo *parse_cmo_ring_by_name() |  | 
|  |  | 
| static cmo *parse_cmo_distributed_polynomial() | static cmo *parse_cmo_distributed_polynomial() | 
| { | { | 
| int length=0; |  | 
| int i=0; |  | 
| cmo_distributed_polynomial *m = new_cmo_distributed_polynomial(); | cmo_distributed_polynomial *m = new_cmo_distributed_polynomial(); | 
| cmo *ob; | cmo *ob; | 
| int tag; | int tag; | 
| 
| Line 482  static cmo *parse_cmo_distributed_polynomial() |  | 
| Line 542  static cmo *parse_cmo_distributed_polynomial() |  | 
| if (token == ',') { | if (token == ',') { | 
| parse_comma(); | parse_comma(); | 
|  |  | 
| if (token == T_INTEGER) { | if (token == T_DIGIT) { | 
| parse_integer(); | parse_integer(); | 
| parse_comma(); | parse_comma(); | 
| }else if (!pflag_cmo_addrev) { | }else if (!pflag_cmo_addrev) { | 
| 
| Line 492  static cmo *parse_cmo_distributed_polynomial() |  | 
| Line 552  static cmo *parse_cmo_distributed_polynomial() |  | 
| parse_left_parenthesis(); | parse_left_parenthesis(); | 
| m->ringdef = parse_cmo(); | m->ringdef = parse_cmo(); | 
| tag = m->ringdef->tag; | tag = m->ringdef->tag; | 
| /* m->ringdef は DringDefinition でなければならない */ | /* m->ringdef needs to be a DringDefinition. */ | 
| if (tag != CMO_RING_BY_NAME && tag != CMO_DMS_GENERIC | if (tag != CMO_RING_BY_NAME && tag != CMO_DMS_GENERIC | 
| && tag != CMO_DMS_OF_N_VARIABLES) { | && tag != CMO_DMS_OF_N_VARIABLES) { | 
| parse_error("invalid cmo."); | parse_error("invalid cmo."); | 
| 
| Line 506  static cmo *parse_cmo_distributed_polynomial() |  | 
| Line 566  static cmo *parse_cmo_distributed_polynomial() |  | 
| if (ob->tag != CMO_MONOMIAL32 && ob->tag != CMO_ZERO) { | if (ob->tag != CMO_MONOMIAL32 && ob->tag != CMO_ZERO) { | 
| parse_error("invalid cmo."); | parse_error("invalid cmo."); | 
| } | } | 
| append_cmo_list((cmo_list *)m, ob); | list_append((cmo_list *)m, ob); | 
| if (token != ',') { | if (token != ',') { | 
| break; | break; | 
| } | } | 
| 
| Line 541  static cmo *parse_cmo_error2() |  | 
| Line 601  static cmo *parse_cmo_error2() |  | 
| return (cmo *)new_cmo_error2(ob); | return (cmo *)new_cmo_error2(ob); | 
| } | } | 
|  |  | 
| /* --- 字句解析部 --- */ | /* --- lexical analyzer --- */ | 
|  |  | 
| /* lexical analyzer で読み飛ばされる文字なら何を初期値にしてもよい */ | /* A white space is ignored by lexical analyzer. */ | 
| static int c = ' '; | static int c = ' '; | 
|  |  | 
| /* 一文字読み込む関数 */ | /* getting a character from string. */ | 
| static char *mygetc_ptr; | static char *mygetc_ptr; | 
| static int mygetc() | static int mygetc() | 
| { | { | 
| return *mygetc_ptr++; | return *mygetc_ptr++; | 
| } | } | 
|  |  | 
| int setmode_mygetc(char *s) | static void init_lex(char *s) | 
| { | { | 
|  | c=' '; | 
| mygetc_ptr=s; | mygetc_ptr=s; | 
| } | } | 
|  |  | 
| static int (*GETC)() = mygetc; | #define SIZE_BUFFER  8192 | 
|  | static char buffer[SIZE_BUFFER]; | 
|  |  | 
| /* 一文字読み込む関数の選択 (ex. setgetc(getchar); ) */ | static char *mkstr(char *src) | 
| int setgetc(int (*foo)()) |  | 
| { | { | 
| if (foo == NULL) { | int len; | 
| GETC = mygetc; | char *s; | 
| }else { | len = strlen(src); | 
| GETC = foo; | s = malloc(len+1); | 
| } | strcpy(s, src); | 
|  | return s; | 
| } | } | 
|  |  | 
| #define SIZE_BUFFER  8192 | /* no measure for buffer overflow */ | 
| static char buffer[SIZE_BUFFER]; | static char *lex_digit() | 
|  |  | 
| /* 桁溢れの場合の対策はない */ |  | 
| static int lex_digit() |  | 
| { | { | 
| int d = 0; | static char buff[SIZE_BUFFER]; | 
| do { | int i; | 
| d = 10*d + (c - '0'); |  | 
| c = GETC(); | for(i=0; i<SIZE_BUFFER-1; i++) { | 
| } while(isdigit(c)); | if(isdigit(c)) { | 
| return d; | buff[i] = c; | 
|  | }else { | 
|  | buff[i] = '\0'; | 
|  | return mkstr(buff); | 
|  | } | 
|  | c = mygetc(); | 
|  | } | 
|  | buff[SIZE_BUFFER-1] = '\0'; | 
|  | return mkstr(buff); | 
| } | } | 
|  |  | 
| #define MK_KEY_CMO(x)  { #x , x  , TOKEN(x)  , IS_CMO } | #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_SM(x)   { #x , x  , TOKEN(SM) , IS_SM  } | 
| #define MK_KEY_OX(x)   { #x , x  , TOKEN(x)  , IS_OX  } | #define MK_KEY_OX(x)   { #x , x  , TOKEN(x)  , IS_OX  } | 
|  |  | 
| static symbol symbol_list[] = { | static struct symbol symbol_list[] = { | 
| MK_KEY_CMO(CMO_NULL), | MK_KEY_CMO(CMO_NULL), | 
| MK_KEY_CMO(CMO_INT32), | MK_KEY_CMO(CMO_INT32), | 
| MK_KEY_CMO(CMO_DATUM), | MK_KEY_CMO(CMO_DATUM), | 
| 
| Line 618  static symbol symbol_list[] = { |  | 
| Line 685  static symbol symbol_list[] = { |  | 
| {NULL, 0, 0, 0}        /* a gate keeper */ | {NULL, 0, 0, 0}        /* a gate keeper */ | 
| }; | }; | 
|  |  | 
| symbol* lookup_by_symbol(char *key) | symbol_t lookup_by_symbol(char *key) | 
| { | { | 
| symbol *symp; | symbol_t symp; | 
| for(symp = symbol_list; symp->key != NULL; symp++) { | for(symp = symbol_list; symp->key != NULL; symp++) { | 
| if (strcmp(key, symp->key)==0) { | if (strcmp(key, symp->key)==0) { | 
| return symp; | return symp; | 
| 
| Line 629  symbol* lookup_by_symbol(char *key) |  | 
| Line 696  symbol* lookup_by_symbol(char *key) |  | 
| return NULL; | 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++) { | for(symp = symbol_list; symp->key != NULL; symp++) { | 
| if (tok == symp->token) { | if (tok == symp->token) { | 
| return symp; | return symp; | 
| 
| Line 640  symbol* lookup_by_token(int tok) |  | 
| Line 707  symbol* lookup_by_token(int tok) |  | 
| return NULL; | 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++) { | for(symp = symbol_list; symp->key != NULL; symp++) { | 
| if (tag == symp->tag) { | if (tag == symp->tag) { | 
| return symp; | return symp; | 
| 
| Line 651  symbol* lookup_by_tag(int tag) |  | 
| Line 718  symbol* lookup_by_tag(int tag) |  | 
| return NULL; | return NULL; | 
| } | } | 
|  |  | 
| symbol* lookup(int i) | symbol_t lookup(int i) | 
| { | { | 
| return &symbol_list[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() | static char *lex_quoted_string() | 
| { | { | 
| int i; | int i; | 
| char c0 = ' '; | char c0 = ' '; | 
| char *s = NULL; |  | 
| for (i=0; i<SIZE_BUFFER; i++) { | for (i=0; i<SIZE_BUFFER; i++) { | 
| c = GETC(); | c = mygetc(); | 
| if(c == '"') { | if(c == '"') { | 
| s = malloc(i+1); | c = mygetc(); | 
| buffer[i]='\0'; | buffer[i]='\0'; | 
| strcpy(s, buffer); | return mkstr(buffer); | 
|  |  | 
| c = GETC(); |  | 
| return s; |  | 
| }else if (c == '\\') { | }else if (c == '\\') { | 
| c0 = c; | c0 = c; | 
| c = GETC(); | c = mygetc(); | 
| if (c != '"') { | if (c != '"') { | 
| buffer[i++] = c0; | buffer[i++] = c0; | 
| } | } | 
| } | } | 
| buffer[i]=c; | buffer[i]=c; | 
| } | } | 
| fprintf(stderr, "buffer overflow!\n"); | ox_printf("buffer overflow!\n"); | 
| exit(1); | exit(1); | 
| /* return NULL; */ | /* return NULL; */ | 
| } | } | 
|  |  | 
| static int token_of_symbol(char *key) | static int token_of_symbol(char *key) | 
| { | { | 
| symbol *symp = lookup_by_symbol(key); | symbol_t symp = lookup_by_symbol(key); | 
| if (symp != NULL) { | if (symp != NULL) { | 
| yylval.d = symp->tag; | yylval.d = symp->tag; | 
| return symp->token; | return symp->token; | 
| } | } | 
| #if DEBUG | ox_printf("lex error:: \"%s\" is unknown symbol.\n", key); | 
| fprintf(stderr, "lex error:: \"%s\" is unknown symbol.\n", key); |  | 
| #endif |  | 
| return 0; | return 0; | 
| } | } | 
|  |  | 
| 
| Line 707  static int lex_symbol() |  | 
| Line 775  static int lex_symbol() |  | 
| return token_of_symbol(buffer); | return token_of_symbol(buffer); | 
| } | } | 
| buffer[i]=c; | buffer[i]=c; | 
| c = GETC(); | c = mygetc(); | 
| } | } | 
| fprintf(stderr, "buffer overflow!\n"); | ox_printf("buffer overflow!\n"); | 
| return 0; | return 0; | 
| } | } | 
|  |  | 
| /* return する前に一文字先読みしておく. */ | /* Remark: prefetching a character before return. */ | 
| int lex() | static int lex() | 
| { | { | 
| int c_dash = 0; | int c_dash = 0; | 
|  |  | 
| /* 空白をスキップする. */ | /* white spaces are ignored. */ | 
| while (isspace(c) && c != '\n') { | while (isspace(c)) { | 
| c = GETC(); | c = mygetc(); | 
| } | } | 
|  |  | 
| switch(c) { | switch(c) { | 
| case '(': | case '(': | 
| case ')': | case ')': | 
| case ',': | case ',': | 
| case '\n': | case '+': | 
|  | case '-': | 
| c_dash = c; | c_dash = c; | 
| c = ' '; | c = ' '; | 
| return c_dash; | return c_dash; | 
| case EOF: | case EOF: | 
| c = GETC(); | c = mygetc(); | 
| return c_dash; | return c_dash; | 
| case '"':      /* a quoted string! */ | case '"':      /* a quoted string! */ | 
| yylval.sym = lex_quoted_string(); | yylval.sym = lex_quoted_string(); | 
|  |  | 
| default: | default: | 
| } | } | 
|  |  | 
| if (isalpha(c)) {    /* 識別子 */ | if (isalpha(c)) { | 
|  | /* symbols */ | 
| return lex_symbol(); | return lex_symbol(); | 
| } | } | 
|  |  | 
| /* 32bit 整数値 */ | /* digit */ | 
| if (isdigit(c)){ | if (isdigit(c)){ | 
| yylval.d = lex_digit(); | yylval.sym = lex_digit(); | 
| return T_INTEGER; | return T_DIGIT; | 
| } | } | 
| if (c == '-') { | c = mygetc(); | 
| c = GETC(); |  | 
| while (isspace(c) && c != '\n') { |  | 
| c = GETC(); |  | 
| } |  | 
| if (isdigit(c)){ |  | 
| yylval.d = - lex_digit(); |  | 
| return T_INTEGER; |  | 
| } |  | 
| return 0; |  | 
| } |  | 
|  |  | 
| c = GETC(); |  | 
| return 0; | return 0; | 
| } | } |