cc.c

来自「編譯器的辭法分析器工具」· C语言 代码 · 共 259 行

C
259
字号
/*                 parser suite - and / or / nothing / something  parsers   parser = [token] -> ([token],status)       implemented as sideeffecting on [token], returns status.*/# include "cc.h"STATUS  p_andparse0 (p, q)/*Serial composition of parsers. Doesfirst p then q. 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.*/PARSER  *p, *q;{    static status tok;    /* why can't this be static? */    MARK;    tok = (*p) ();    if (BADSTATUS (tok)){    /* error */            RELEASE;        return tok;    }    tok = (*q) ();    if (BADSTATUS (tok))    /* error */    {        REWIND;        /* remove this line for 1-token LA parsing */        return tok;        /* fail */    }    pushDECR;    RELEASE;    return tok;            /* succeed */}STATUS  p_orparse0 (p, q)/*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.*/PARSER  p, q;{	static status  tok;     /* I don't see why this can't be static */	tok = p ();	if (BADSTATUS (tok))	/* error */		tok = q ();	/* retry */	return tok;		/* whatever */}STATUS p_many0 (p)/*parser which tries p any number of timesuntil p fails, but returns success anyhow.*/PARSER *p;{    int repeat = 0;    while (GOODSTATUS((*p) ()))        repeat++;/* we no longer need stack manipulations */# ifdef STACKMANIPS    switch(repeat)    {      case 0: pushINCR; break;      case 1: break;      default:pushMANIP(-(repeat-1)); break;    }# endif    return (SUCCESS);}STATUS p_iter0 (repeat, p)/*parser which tries p repeat number of times exactly*/PARSER *p;int repeat;{    static int k;    static status tok;    MARK;    k = repeat;    while (k-->0) {        tok = (*p) ();        if (BADSTATUS(tok)) {            REWIND;            return tok;        }    }#ifdef STACKMANIPS    switch(repeat)    {      case 0: pushINCR; break;      case 1: break;      default:pushMANIP(-(repeat-1)); break;    }#endif    RELEASE;    return tok;}STATUS   p_until0(p)/* This parser skips until p succeeds, when it returns with p's value.   It's equivalent to a  foo = p | ? foo, but more efficient by a small   bit of the call stack for each fail of p. */PARSER *p;{    static STATUS tok;    while (*pstr) {        tok = (*p)();        if GOODSTATUS(tok)            return tok;        MOVEON;    }    return FAILURE;}STATUS  p_some0 (p)/*At least one repetition of parser p*/PARSER *p;{    status tok;    tok = (*p) ();    if (GOODSTATUS(tok)){        tok = p_many0 (p);        pushDECR; /* bound to succeed */        return(tok);    }    return tok;}STATUS p_option0 (p)/* optionally p */PARSER *p;{    static status tok;    tok = (*p) ();    if (GOODSTATUS(tok))        return tok;    pushINCR;    return(SUCCESS);}STATUS p_range0 (p)/*checks whether *pstr satisfies predicate p.p must take a TOKEN as arg. That is a mistake. It should bean int (a PARAM).*/PREDICATE *p;{    VALUE v;    if ((*p) (*pstr))    {        v = lvbuff[(int)(pstr-buffer)];        MOVEON;        pushVALUE(v);        return (OK(v));    }    return (FAILURE);}STATUS p_attach (p,f)PARSER *p;ACTION *f;{    static status tok;    tok = (*p) ();    if (GOODSTATUS(tok)) {        pushACTION(f);        return tok;    }    return tok;}STATUS p_prepend (f,p)PARSER *p;ACTION *f;{    static status tok;    MARK;    pushACTION(f);    tok = (*p) ();    if (GOODSTATUS(tok)) {        RELEASE;    return tok;    }    REWIND;    return tok;}STATUS  p_hidden0 (p)PARSER *p;/*parser which tries p, but doesnt moveon, just reports the resultof p.*/{    static status tok;    MARK;    tok = (*p) ();    REWIND;    if(GOODSTATUS(tok)) {   /* we have to show we were here to keep in V(n) step */           pushVALUE(tok);           return tok;    }    return tok;}

⌨️ 快捷键说明

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