/* -*- mode: C; coding: euc-japan -*- */ /* $OpenXM: OpenXM/src/ox_math/parse.c,v 1.1 1999/10/29 08:06:41 ohara Exp $ */ /* $Id: parse.c,v 1.4 1999/10/14 10:19:04 ohara Exp ohara $ */ /* OX expression, CMO expression パーサ */ /* cmo_addrev がセットされていれば、 厳密には CMO expression でないもの, 例えば (CMO_STRING, "abcdef") も CMO に変換される. */ #include #include #include #include #include "oxtag.h" #include "ox.h" #include "parse.h" /* --- 構文解析部 --- */ /* parse.c, lex.c では, Lisp 表現された CMO 文字列を読み込み, バイト列を出力する. 中間表現として、cmo *を利用する. parse() はトークンの列から cmo *(の指す構造体)を生成する. */ /* 重要なことはパーサ(の各サブルーチン)は 常にトークンをひとつ先読みしていると言うことである. */ /* 現在読み込み中のトークンを表す. */ static int token = 0; /* yylval は lex() によってセットされる. */ extern lex_value_t yylval; int 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 char *parse_string(); static int parse_sm(); static ox* parse_ox(); static ox* parse_ox_command(); static ox* parse_ox_data(); static int parse_error(char *s) { if (s != NULL) { fprintf(stderr, "%s\n", s); }else { fprintf(stderr, "syntax error.\n"); } exit(1); /* 例外処理. 本当は longjmp すべきであろう. */ } #define MIN_T_CMO (T_MAGIC + 0) #define MAX_T_CMO (T_MAGIC + 256) static int is_t_cmo(int token) { return (token >= MIN_T_CMO && token < MAX_T_CMO) || token == T_CMO_ERROR2; } #define MIN_T_SM (T_MAGIC + 256) #define MAX_T_SM (T_MAGIC + 1100) static int is_t_sm(int token) { return token >= MIN_T_SM && token < MAX_T_SM; } #define MIN_T_OX (T_MAGIC + 512) #define MAX_T_OX (T_MAGIC + 600) static int is_t_ox(int token) { return token >= MIN_T_OX && token < MAX_T_OX; } /* この部分は書き換え予定. */ cmo *parse() { cmo *m; do{ token = lex(); }while (token == '\n'); if (token == '(') { token = lex(); if (is_t_cmo(token)) { m = parse_cmo(); }else if(is_t_ox(token)) { m = parse_ox(); }else { parse_error("syntax error: unknown keyword."); return NULL; } parse_lf(); return m; } return NULL; } /* トークンを先読みしない(重要). */ static int parse_lf() { if (token != '\n') { parse_error("syntax error: not new line."); } return 0; } static ox* parse_ox() { ox *m = NULL; switch(token) { case T_OX_COMMAND: token = lex(); m = parse_ox_command(); break; case T_OX_DATA: token = lex(); m = parse_ox_data(); break; default: parse_error("syntax error: invalid ox_tag."); } return m; } static ox* parse_ox_data() { ox* m; parse_comma(); parse_left_parenthesis(); m = (ox *)new_ox_data(parse_cmo()); parse_right_parenthesis(); return m; } static int parse_sm() { int sm_code; if (!is_t_sm(token)) { parse_error("syntax error: invalid sm code."); } sm_code = token - T_MAGIC; token = lex(); 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 のいずれかがセットされている. */ static cmo *parse_cmo() { cmo *m = NULL; switch(token) { case T_CMO_NULL: token = lex(); m = parse_cmo_null(); break; case T_CMO_INT32: token = lex(); m = parse_cmo_int32(); break; case T_CMO_STRING: token = lex(); m = parse_cmo_string(); break; case T_CMO_ZZ: token = lex(); m = parse_cmo_zz(); break; case T_CMO_LIST: token = lex(); m = parse_cmo_list(); break; default: parse_error("syntax error: invalid cmo_tag."); } return m; } static int parse_right_parenthesis() { if (token != ')') { parse_error("syntax error: no right parenthesis exists."); return 0; } token = lex(); } static int parse_left_parenthesis() { if (token != '(') { parse_error("syntax error: no left parenthesis exists."); return 0; } token = lex(); } static int parse_comma() { if (token != ',') { parse_error("syntax error: no comma exists."); return 0; } token = lex(); return 1; } /* cmo_zz の内部を直接いじる. */ static cmo *parse_cmo_zz() { int length; int i=0; cmo_zz *m= NULL; parse_comma(); length = parse_integer(); if (token == ',') { m = new_cmo_zz_size(length); length = abs(length); for(i=0; impz->_mp_d[i] = parse_integer(); } }else if (cmo_addrev) { m = new_cmo_zz_set_si(length); }else { parse_error("syntax error: invalid keyword."); } parse_right_parenthesis(); return (cmo *)m; } static cmo *parse_cmo_list() { 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; i