⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ccx.c

📁 編譯器的辭法分析器工具
💻 C
字号:
/*   parser suite - and / or / nothing / something  parsers   parser = [token] -> ([token],status)       implemented as sideeffecting on [token], returns status.*/# include "ccx.h"static PARAM a0[MAXARGS], *a=a0;        /* holds parameters */STATUS p_errparse0 ()/* I'm just here to help detect errors */{    fprintf(stderr,"An unspecified parser has been called. Aborting.\n");    p_exit(100);        /* this is never called */    return FAILURE;}VOID callerror(m)/* aux: for diagnosing errors in the CALL macro */int m;{    printf("error: too many (%d) args in CALL\n",m-1);    p_exit(100);}STATUS p_andparse0n (PARSER *p, ...)/*Serial composition of parsers. Doesfirst p then q. Put p's instructions on thetop of the program stack, then layer q's aboveit.This version has full rewind of the input stream onfailure, but this can be altered to single tokenlookahead by deleting the line of code marked.*/{    static PARSER *q=p_errparse0;    va_list ap;    static int m;    static status  tok;    MARK;    va_start(ap,p);    m=va_arg(ap,int);    a=(PARAM*)ap; /* very NON-PORTABLE, but it's fast */    ap=(va_list)&a[m];    m++;    switch(m-1) {    case 0: tok=(*p)();break;    case 1: tok=(*p)(a[0]);break;    case 2: tok=(*p)(a[0],a[1]);break;    case 3: tok=(*p)(a[0],a[1],a[2]);break;    case 4: tok=(*p)(a[0],a[1],a[2],a[3]);break;    case 5: tok=(*p)(a[0],a[1],a[2],a[3],a[4]);break;    case 6: tok=(*p)(a[0],a[1],a[2],a[3],a[4],a[5]);break;    case 7: tok=(*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6]);break;    case 8: tok=(*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]);break;    case 9: tok=(*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);break;    case 10: tok=(*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);break;    case 11: tok=(*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10]);break;    case 12: tok=(*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11]);             break;    case 13: tok=(*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11],             a[12]);break;    case 14: tok=(*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11],             a[12],a[13]);break;    case 15: tok=(*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11],             a[12],a[13],a[14]);break;    case 16: tok=(*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11],             a[12],a[13],a[14],a[15]);break;    default: callerror(m);    }    if (BADSTATUS (tok)) {        va_end(ap);        RELEASE;        return tok;    }    q = va_arg(ap,PARSER*);     CALL(tok=(*q),m,a);    va_end(ap);    if (BADSTATUS (tok))    /* error */    {        REWIND;        /* remove this line for 1-token LA parsing */        return tok;    /* fail */    }    pushDECR;    RELEASE;    return tok;        /* succeed */}STATUS p_starparse0n (VALUE *x,PARSER *p, ...)/*Monadic composition of parsers. Doesfirst p then q, where q can use x, which is the address of p's result.Assume that q knows that x is an address!Put p's instructions on thetop of the program stack, then layer q's above it.This version has full rewind of the input stream onfailure, but this can be altered to single tokenlookahead by deleting the line of code marked.*/{    static PARSER *q=p_errparse0;    va_list ap;    static int m;    static PARAM *a;    static status  tok;    MARK;    va_start(ap,p);    CALL(tok=(*p),m,a);        if (BADSTATUS(tok)) {        va_end(ap);        RELEASE;        return tok;    }    /* I intend that x be local so that if we later fail, this     * value will disappear */    *x = (VALUE)INSTATUS(tok);    q = va_arg(ap,PARSER*);        CALL(tok=(*q),m,a);        va_end(ap);        if (BADSTATUS (tok))    /* error */        {            REWIND;        /* remove this line for 1-token LA parsing */            return tok;    /* fail */        }            pushDECR;        RELEASE;        return tok;        /* succeed */}STATUS   p_until0n(PARSER *p, ...)/* skip until p succeeds. This should be the same as    foo = p | ? foo . */{    va_list ap;    static STATUS tok;     static int m;    while (*pstr) {        va_start(ap,p);        CALL(tok=(*p),m,a);        va_end(ap);        if GOODSTATUS (tok)            return tok;        MOVEON;    }    return FAILURE;}STATUS p_orparse0n (PARSER *p, ...)/*alternate composition of parsers. Tries p first,and if it doesnt work, tries q. Code correspondingto the successful parse is placed on the program stack.If both fail, the routine relies on p and q's auto-rewindmechanisms to do the rewind for it.*/{    va_list ap;    static PARSER *q=p_errparse0;    static int m;    static status  tok;    va_start(ap,p);        CALL(tok=(*p),m,a);    if (BADSTATUS (tok))    /* error */    {        q = va_arg(ap,PARSER*);            CALL(tok=(*q),m,a);    }    va_end(ap);    return tok;        /* succeed */}STATUS  p_hidden0n (PARSER *p, ...)/*parser which tries p, but doesnt moveon, just reports the resultof p.*/{    static va_list ap;    static int m;    static status tok;    MARK;    va_start(ap,p);    CALL(tok=(*p),m,a);    va_end(ap);            REWIND;    if (GOODSTATUS(tok)) {       pushVALUE(p_hidden0n);    }    return tok;}STATUS  p_option0n (PARSER *p, ...)/*parser which tries p, but doesnt worry if p fails,just rewinds and considers itself happy with nothing at all.*/{    static va_list ap;    static int m;    static status tok;    va_start(ap,p);    CALL(tok=(*p),m,a);    va_end(ap);    if (GOODSTATUS(tok))        return tok;    pushINCR;    return(SUCCESS);}STATUS  p_many0n (PARSER *p, ...){    static    va_list(ap);    static status tok;    int repeat=0;    static int m;/* to use this from a function which has parameters foo,m,a1,...,am   use va_start(ap,foo) and call us */loop:    va_start(ap,p);    CALL(tok=(*p),m,a);    va_end(ap);    if (GOODSTATUS(tok)) {        repeat++;        goto loop;    }# ifdef STACKMANIPS    switch(repeat)    {        case 0: pushINCR; break;        case 1: break;        default:pushMANIP(repeat-1);    }# endif    return SUCCESS;}STATUS p_uerror0n (PARSER *p, ...){    static va_list(ap);    static int m;        va_start(ap,p);        m=va_arg(ap,int);        a=(PARAM*)ap;        ap=(va_list)&a[m];        /*m++; ?*/        p_entry = p;  /* set the btck_error reentry pt */        p_enargs= m;        memcpy(p_eargv, a, m * sizeof(PARAM));        va_end(ap);        pushEXIT;        pc=0;        pc=p_evaluate ();        pc=0;   /* we have to write the next program in the right place */        if (yytchar!=EOF && 0==*pstr) /* then we can ask */            /* if (getatoken(buffer,lvbuff)==0) */            if (get1token() != EOF)            {                /* now we restart */                realignbuffer();            }        passcount++;        return SUCCESS;}STATUS  p_iter0n (int repeat, PARSER *p, ...){    static va_list(ap);    static int m;    static status tok;    static int k;    MARK;    k = repeat;    while(k-->0){        va_start(ap,p);        CALL(tok=(*p),m,a);        va_end(ap);        if (BADSTATUS(tok)) {            REWIND;            return FAILURE;        }    }# ifdef STACKMANIPS    switch(repeat)    {        case 0: pushINCR; break;        case 1: break;        default:pushMANIP(repeat-1);    }# endif    RELEASE;    return SUCCESS;}STATUS p_prepend0n (ACTION *f, ...){    static PARSER *p;    static status tok;    static int m;    va_list(ap);    MARK;    va_start(ap,f);        m=va_arg(ap,int);        a=(PARAM*)ap;        ap=(va_list)&a[m];        m++;    while(--m>0)           pushPARAM(a[m-1]);    pushACTION(f);    p = va_arg(ap,PARSER *);    CALL(tok=(*p),m,a);    va_end(ap);    if (GOODSTATUS(tok)){        RELEASE;        return tok;    }    REWIND;    return tok;}STATUS  p_some0n (PARSER *p, ...)/*At least one repetition of parser p*/{    static va_list(ap);    int m;    status  tok;    va_start(ap,p);    /* this should really be a call of p_many0v(p,ap) */    CALL(tok=(*p),m,a);    va_end(ap);                if (GOODSTATUS(tok)) {        switch(m-1){        case 0: tok = p_many0n (p,0); break;        case 1: tok = p_many0n (p,1,a[0]); break;        case 2: tok = p_many0n (p,2,a[0],a[1]); break;        case 3: tok = p_many0n (p,3,a[0],a[1],a[2]); break;        case 4: tok = p_many0n (p,4,a[0],a[1],a[2],a[3]); break;        case 5: tok = p_many0n (p,5,a[0],a[1],a[2],a[3],a[4]); break;        case 6: tok = p_many0n (p,6,a[0],a[1],a[2],a[3],a[4],a[5]); break;        case 7: tok = p_many0n (p,7,a[0],a[1],a[2],a[3],a[4],a[5],a[6]); break;        case 8: tok = p_many0n (p,8,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]);                break;        case 9: tok = p_many0n (p,9,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],                a[8]); break;        case 10:tok = p_many0n (p,10,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],                a[8],a[9]); break;        case 11:tok = p_many0n (p,11,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],                a[8],a[9],a[10]); break;        case 12:tok = p_many0n (p,12,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],                a[8],a[9],a[10],a[11]); break;        case 13:tok = p_many0n (p,13,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],                a[8],a[9],a[10],a[11],a[12]); break;        case 14:tok = p_many0n (p,14,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],                a[8],a[9],a[10],a[11],a[12],a[13]); break;        case 15:tok = p_many0n (p,15,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],                a[8],a[9],a[10],a[11],a[12],a[13],a[14]); break;        case 16:tok = p_many0n (p,16,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],                a[8],a[9],a[10],a[11],a[12],a[13],a[14],a[15]); break;        default:printf("error: too many (%d) args in CALL\n",m-1);\                p_exit(100); break;        }        pushDECR;    }    return tok;}STATUS  p_test0 (x)/* succeed if x is 1, fail if x is 0 */int x;{    if (x){        pushVALUE((VALUE)x);        return OK(x);    }    return FAILURE;}STATUS p_attach0n (PARSER *p, ...)/*attach an action to a parse.*/{    va_list(ap);    status tok;    static int m;    static ACTION *f;    va_start(ap,p);        CALL(tok=(*p),m,a);    f=va_arg(ap,ACTION*);    m=va_arg(ap,int);    a=(PARAM*)ap;    ap=(va_list)&a[m];    m++;    va_end(ap);    if (GOODSTATUS(tok)){        while(--m>0){            pushPARAM(a[m-1]);        }        pushACTION(f);    }    return tok;}STATUS p_range0n (PREDICATE *p, ...){    static va_list(ap);    boolean tok;    /* could make this static, but range is always a leaf */    static int m;        /* so it's hardly worth the bother. */        TOKEN c; VALUE v;    va_start(ap,p);    m=va_arg(ap,int);    a=(PARAM*)ap;    ap=(va_list)&a[m];    m++;    va_end(ap);            c = *pstr;    v = lvbuff[(int)(pstr-buffer)];    switch(m-1) {    case 0: tok = (*p)(c); break;    case 1: tok = (*p)(a[0],c); break;    case 2: tok = (*p)(a[0],a[1],c); break;    case 3: tok = (*p)(a[0],a[1],a[2],c); break;    case 4: tok = (*p)(a[0],a[1],a[2],a[3],c); break;    case 5: tok = (*p)(a[0],a[1],a[2],a[3],a[4],c); break;    case 6: tok = (*p)(a[0],a[1],a[2],a[3],a[4],a[5],c); break;    case 7: tok = (*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],c); break;    case 8: tok = (*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]);            break;    case 9: tok = (*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],            a[8]); break;    case 10:tok = (*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],            a[8],a[9]); break;    case 11:tok = (*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],            a[8],a[9],a[10]); break;    case 12:tok = (*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],            a[8],a[9],a[10],a[11]); break;    case 13:tok = (*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],            a[8],a[9],a[10],a[11],a[12]); break;    case 14:tok = (*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],            a[8],a[9],a[10],a[11],a[12],a[13]); break;    case 15:tok = (*p)(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],            a[8],a[9],a[10],a[11],a[12],a[13],a[14]); break;    default: printf("error: too many (%d) args in predicate\n",m-1);             p_exit(100);    }    if (GOODSTATUS(tok))    {        MOVEON;        pushVALUE(v);        return OK(v);    }    return FAILURE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -