[BACK]Return to parse.c CVS log [TXT][DIR] Up to [local] / OpenXM / src / ox_math

Annotation of OpenXM/src/ox_math/parse.c, Revision 1.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>