?? ccx.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 + -