parse.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,148 行 · 第 1/3 页

C
1,148
字号
                if( ch == '\n' ) {
                    msg( "string literal was not terminated by \" before end of line\n" );
                    break;
                }
                if( ch == '\\' ) {
                    addbuf( ch );
                    nextc();
                    addbuf( ch );
                } else {
                    if( ch == '"' ) break;
                    addbuf( ch );
                }
            }
        }
        if( ch == '\'' ) {
            /* copy a character constant */
            addbuf( ch );
            for(;;) {
                nextc();
                if( ch == EOF ) break;
                if( ch == '\n' ) {
                    msg( "character literal was not terminated by \" before end of line\n" );
                    break;
                }
                if( ch == '\\' ) {
                    addbuf( ch );
                    nextc();
                    addbuf( ch );
                } else {
                    if( ch == '\'' ) break;
                    addbuf( ch );
                }
            }
        }
        if( ch == '{' ) {
            ++depth;
        } else if( ch == '}' ) {
            --depth;
        }
    } while( depth > 0 && ch != EOF );
    addbuf( ch );
    addbuf( '\0' );
    nextc();
}

static void lineinfo( void )
{
    if( lineflag )
        fprintf( actout, "\n#line %d \"%s\"\n", lineno, srcname );
}

static void addstr( char *p ) {
    while( *p ) {
        addbuf( *p );
        ++p;
    }
}

typedef struct xlat_entry {
    int         c;
    char        *x;
} xlat_entry;
static xlat_entry xlat[] = {
    { '~',      "TILDE" },
    { '`',      "BACKQUOTE" },
    { '!',      "EXCLAMATION" },
    { '@',      "AT" },
    { '#',      "SHARP" },
    { '$',      "DOLLAR" },
    { '%',      "PERCENT" },
    { '^',      "XOR" },
    { '&',      "AND" },
    { '*',      "TIMES" },
    { '(',      "LPAREN" },
    { ')',      "RPAREN" },
    { '-',      "MINUS" },
    { '+',      "PLUS" },
    { '=',      "EQUAL" },
    { '[',      "LSQUARE" },
    { ']',      "RSQUARE" },
    { '{',      "LBRACE" },
    { '}',      "RBRACE" },
    { '\\',     "BACKSLASH" },
    { '|',      "OR" },
    { ':',      "COLON" },
    { ';',      "SEMICOLON" },
    { '\'',     "QUOTE" },
    { '"',      "DQUOTE" },
    { '<',      "LT" },
    { '>',      "GT" },
    { '.',      "DOT" },
    { ',',      "COMMA" },
    { '/',      "DIVIDE" },
    { '?',      "QUESTION" },
    { '\0',     NULL }
};

static int xlat_char( int special, int c ) {
    xlat_entry *t;
    auto char buff[16];

    if( isalpha( c ) || isdigit( c ) || c == '_' ) {
        if( special ) {
            addbuf( '_' );
        }
        addbuf( c );
        return( FALSE );
    }
    /* NYI: add %translate 'c' XXXX in case user doesn't like our name */
    addbuf( '_' );
    for( t = xlat; t->x != NULL; ++t ) {
        if( t->c == c ) {
            addstr( t->x );
            return( TRUE );
        }
    }
    warn( "'x' token contains unknown character '%c' (\\x%x)\n", c, c );
    addbuf( 'X' );
    sprintf( buff, "%x", c );
    addstr( buff );
    return( TRUE );
}

static void xlat_token( void )
{
    int special;

    addbuf( 'Y' );
    special = TRUE;
    for(;;) {
        nextc();
        if( ch == EOF || ch == '\n' ) {
            msg( "invalid 'x' token" );
            break;
        }
        if( ch == '\'' ) break;
        if( ch == '\\' ) {
            special = xlat_char( special, ch );
            nextc();
        }
        special = xlat_char( special, ch );
    }
    addbuf( '\0' );
    value = 0;
    token = IDENTIFIER;
}

static int scan( unsigned used )
{
    bufused = used;
    eatcrud();
    if( isalpha( ch ) ) {
        for(;;) {
            addbuf( ch );
            nextc();
            if( isalpha( ch ) ) continue;
            if( isdigit( ch ) ) continue;
            if( ch == '_' ) continue;
            if( ch == '.' ) continue;
            if( ch == '-' ) continue;
            break;
        }
        addbuf( '\0' );
        if( eatcrud() == ':' ) {
            nextc();
            token = C_IDENTIFIER;
        } else {
            token = IDENTIFIER;
        }
        value = 0;
    } else if( isdigit( ch ) || ch == '-' ) {
        do {
            addbuf( ch );
        } while( isdigit( nextc() ) );
        addbuf( '\0' );
        token = NUMBER;
        value = atoi( buf );
    } else {
        switch( ch ) {
        case '\'':
            if( denseflag && ! translateflag ) {
                msg( "cannot use '+' style of tokens with the dense option\n" );
            }
            if( ! translateflag ) {
                addbuf( '\'' );
                nextc();
                addbuf( ch );
                if( ch == '\\' ) {
                    nextc();
                    addbuf( ch );
                    switch( ch ) {
                    case 'n':  ch = '\n'; break;
                    case 'r':  ch = '\r'; break;
                    case 't':  ch = '\t'; break;
                    case 'b':  ch = '\b'; break;
                    case 'f':  ch = '\f'; break;
                    case '\\': ch = '\\'; break;
                    case '\'': ch = '\''; break;
                    }
                }
                addbuf( '\'' );
                value = ch;
                token = IDENTIFIER;
                need( "'" );
            } else {
                xlat_token();
            }
            break;
        case '{':
            token = ch;
            copybal();
            break;
        case '<': case '>': case '|': case ';': case ',':
        case EOF:
            token = ch;
            break;
        case '%':
            switch( nextc() ) {
            case '%':
                token = MARK;
                break;
            case '{':
                token = LCURL;
                break;
            case '}':
                token = RCURL;
                break;
            case 'a':
                need( "mbig" );
                token = AMBIG;
                break;
            case 'k':
                need( "eyword_id" );
                token = KEYWORD_ID;
                break;
            case 'l':
                need( "eft" );
                token = LEFT;
                value = L_ASSOC;
                break;
            case 'n':
                need( "onassoc" );
                token = NONASSOC;
                value = NON_ASSOC;
                break;
            case 'p':
                need( "rec" );
                token = PREC;
                break;
            case 'r':
                need( "ight" );
                token = RIGHT;
                value = R_ASSOC;
                break;
            case 's':
                need( "tart" );
                token = START;
                break;
            case 't':
                nextc();
                if( ch == 'o' ) {
                    need( "ken" );
                    token = TOKEN;
                } else if( ch == 'y' ) {
                    need( "pe" );
                    token = TYPE;
                } else {
                    msg( "Expecting %%token or %%type.\n" );
                }
                break;
            case 'u':
                need( "nion" );
                token = UNION;
                break;
            default:
                msg( "Unrecognized %% token.\n" );
            }
            break;
        default:
            msg( "Bad token.\n" );
        }
        addbuf( '\0' );
        nextc();
    }
    return( token );
}

static void need( char *pat )
{
    while( *pat ) {
        if( nextc() != *pat++ ) {
            msg( "Expected '%c'\n", pat[-1] );
        }
    }
}

static int eatcrud( void )
{
    int prev;

    for(;;) {
        switch( ch ) {
        case ' ':
        case '\t':
        case '\r':
        case '\n':
        case '\f':
            nextc();
            break;
        case '/':
            if( nextc() != '*' ) {
                if( ch == '\n' ) {
                    --lineno;
                }
                ungetc( ch, yaccin );
                ch = '/';
                return( ch );
            }
            prev = '\0';
            for(;;) {
                if( nextc() == '/' && prev == '*' ) {
                    break;
                }
                if( ch == EOF ) {
                    return( EOF );
                }
                prev = ch;
            }
            nextc();
            break;
        default:
            return( ch );
        }
    }
}

static int nextc( void )
{
    if( (ch = fgetc( yaccin )) == '\r' ) {
        ch = fgetc( yaccin );
    }
    if( ch == '\n' ) {
        ++lineno;
    }
    return( ch );
}

static int lastc( void )
{
    if( bufused > 1 ) {
        return( buf[bufused-1] );
    }
    return( '\0' );
}

static void addbuf( int ch )
{
    if( bufused == bufmax ) {
        bufmax += BUF_INCR;
        if( buf )
            buf = REALLOC( buf, bufmax, char );
        else
            buf = MALLOC( bufmax, char );
    }
    buf[bufused++] = ch;
}

static char *dupbuf( void )
{
    char *str;

    str = MALLOC( bufused, char );
    memcpy( str, buf, bufused );
    bufused = 0;
    return( str );
}

void parsestats( void )
{
    dumpstatistic( "actions combined", actionsCombined );
}

⌨️ 快捷键说明

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