sslrule.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 303 行

C
303
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <stdio.h>

#include "ssl.h"
#include "sslint.h"

extern token            CurrToken;

static void Action( symbol *, instruction * );

static void Cycle( symbol *rule )
{
    instruction      *top;
    instruction      *bot;

    Scan();
    top = GenNewLbl();
    GenLabel( top );
    bot = GenNewLbl();
    do {
        Action( rule, bot );
    } while( CurrToken != T_RITE_BRACE );
    GenJump( top );
    GenLabel( bot );
    Scan();
}


static void SemCall( symbol *call )
{
    symbol      *parm;

    Scan();
    if( call->v.sem.parm != NULL ) {
        if( CurrToken != T_LEFT_PAREN ) Error( "expecting '('" );
        Scan();
        parm = Lookup( CLASS_ENUMS );
        if( call->v.sem.parm != parm->v.enums.type ) {
            Error( "improper type for semantic parm" );
        }
        GenSetParm( parm->v.enums.value );
        Scan();
        if( CurrToken != T_RITE_PAREN ) Error( "expecting ')'" );
        Scan();
    }
    GenSemCall( call->v.sem.value );
}


static void Choice( symbol *rule, instruction *exit )
{
    instruction *choice;
    instruction *def_lbl;
    char        def;
    class       typ;
    unsigned    first_value;
    instruction *first_lbl;
    instruction *bot;
    instruction *lbl;
    symbol      *ret;
    symbol      *call;
    symbol      *sym;

    Scan();
    switch( CurrToken ) {
    case T_OR:
        choice = GenInpChoice();
        ret = NULL;
        typ = CLASS_INPUT;
        break;
    case T_AT:
        Scan();
        call = Lookup( CLASS_RULE );
        ret = call->v.rule.ret;
        if( call->v.rule.defined & (ret == NULL) ) {
            Error( "rule has no return type" );
        }
        Scan();
        GenLblCall( call->v.rule.lbl );
        choice = GenChoice();
        typ = CLASS_ENUMS;
        break;
    case T_NAME:
        call = Lookup( CLASS_SEM );
        ret = call->v.sem.ret;
        if( ret == NULL ) Error( "semantic action has no return type" );
        SemCall( call );
        choice = GenChoice();
        typ = CLASS_ENUMS;
        break;
    }
    bot = GenNewLbl();
    def_lbl = GenNewLbl();
    GenJump( def_lbl );
    def = 0;
    first_lbl = NULL;
    while( CurrToken == T_OR ) {
        lbl = GenNewLbl();
        Scan();
        for( ;; ) {
            if( CurrToken == T_STAR ) {
                if( def ) Error( "default case already processed" );
                def = 1;
                GenLabel( def_lbl );
            } else {
                sym = Lookup( typ );
                if( typ == CLASS_INPUT ) {
                    GenTblLabel( choice, lbl, sym->v.token );
                    if( first_lbl == NULL ) {
                        first_lbl = lbl;
                        first_value = sym->v.token;
                    }
                } else if( sym->v.enums.type == ret ) {
                    GenTblLabel( choice, lbl, sym->v.enums.value );
                    if( first_lbl == NULL ) {
                        first_lbl = lbl;
                        first_value = sym->v.enums.value;
                    }
                } else if( ret == NULL ) {
                    /* forward referenced rule */
                    ret = sym->v.enums.type;
                    call->v.rule.ret = ret;
                } else {
                    Error( "choice label is improper type" );
                }
            }
            Scan();
            if( CurrToken != T_COMMA ) break;
            Scan();
        }
        WantColon();
        GenLabel( lbl );
        while( CurrToken != T_OR && CurrToken != T_RITE_BRACKET ) {
            Action( rule, exit );
        }
        if( CurrToken == T_RITE_BRACKET ) break;
        GenJump( bot );
    }
    if( !def ) {
        GenJump( bot );
        GenLabel( def_lbl );
        if( typ == CLASS_INPUT ) {
            GenInput( first_value );
            GenJump( first_lbl );
        } else {
            GenKill();
        }
    }
    GenLabel( bot );
    Scan();
}

static void Action( symbol *rule, instruction *exit )
{
    symbol      *sym;
    symbol      *call;
    symbol      *ret;

    switch( CurrToken ) {
    case T_NAME:
    case T_LITERAL:
        sym = Lookup( CLASS_ANY );
        if( sym->typ == CLASS_INPUT ) {
            GenInput( sym->v.token );
            Scan();
        } else if( sym->typ == CLASS_SEM ) {
            SemCall( sym );
        } else {
            Error( "expecting token or semantic action" );
        }
        break;
    case T_QUESTION:
        GenInputAny();
        Scan();
        break;
    case T_DOT:
        Scan();
        sym = Lookup( CLASS_OUTPUT );
        GenOutput( sym->v.token );
        Scan();
        break;
    case T_POUND:
        Scan();
        sym = Lookup( CLASS_ERROR );
        GenError( sym->v.token );
        Scan();
        break;
    case T_LEFT_BRACE:
        Cycle( rule );
        break;
    case T_GT:
        if( exit == NULL ) Error( "no cycle to exit from" );
        GenJump( exit );
        Scan();
        break;
    case T_LEFT_BRACKET:
        Choice( rule, exit );
        break;
    case T_AT:
        Scan();
        call = Lookup( CLASS_RULE );
        GenLblCall( call->v.rule.lbl );
        Scan();
        break;
    case T_GT_GT:
        Scan();
        if( rule->v.rule.ret != NULL ) {
            if( CurrToken != T_NAME ) Error( "expecting name" );
            ret = Lookup( CLASS_ENUMS );
            if( ret->v.enums.type != rule->v.rule.ret ) {
                Error( "improper return type" );
            }
            GenSetResult( ret->v.enums.value );
            Scan();
        }
        GenReturn();
        break;
    default:
        Error( "unknown action" );
        break;
    }
}

void Rules(void)
{
    symbol      *sym;
    symbol      *ret;
    int         exported;

    exported = 1;       /* first rule always exported */
    do {
        sym = Lookup( CLASS_RULE );
        if( sym->v.rule.defined ) {
            Error( "multiple definitions" );
        }
        sym->v.rule.defined = 1;
        Scan();
        if( CurrToken == T_GT_GT ) {
            Scan();
            ret = Lookup( CLASS_TYPE );
            if( sym->v.rule.ret != NULL && sym->v.rule.ret != ret ) {
                Error( "return type does not match previous usage" );
            }
            sym->v.rule.ret = ret;
            Scan();
        } else if( sym->v.rule.ret != NULL ) {
            Error( "expecting return type" );
        }
        WantColon();
        if( CurrToken == T_COLON ) {
            Scan();
            sym->v.rule.exported = 1;
            exported = 1;
        }
        if( exported ) {
            GenExportLabel( sym->v.rule.lbl );
        } else {
            GenLabel( sym->v.rule.lbl );
        }
        while( CurrToken != T_SEMI ) {
            Action( sym, NULL );
        }
        Scan();
        if( sym->v.rule.ret == NULL ) {
            GenReturn();
        } else {
            GenKill();
        }
        exported = 0;
    } while( CurrToken != T_EOF );
  }

⌨️ 快捷键说明

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