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

📄 parser.cpp

📁 < Game Script Mastery>> source code
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*

    Project.

        XSC - The XtremeScript Compiler Version 0.8

    Abstract.

        Parser module

    Date Created.

        8.21.2002

    Author.

        Alex Varanese

*/

// ---- Include Files -------------------------------------------------------------------------

    #include "parser.h"
    #include "error.h"
    #include "lexer.h"
    #include "symbol_table.h"
    #include "func_table.h"
    #include "i_code.h"

// ---- Globals -------------------------------------------------------------------------------

    // ---- Functions -------------------------------------------------------------------------

        int g_iCurrScope;                               // The current scope

    // ---- Loops -----------------------------------------------------------------------------

        Stack g_LoopStack;                              // Loop handling stack

// ---- Functions -----------------------------------------------------------------------------

    /******************************************************************************************
    *
    *   ReadToken ()
    *
    *   Attempts to read a specific token and prints an error if its not found.
    */

    void ReadToken ( Token ReqToken )
    {
        // Determine if the next token is the required one

        if ( GetNextToken () != ReqToken )
        {
            // If not, exit on a specific error

            char pstrErrorMssg [ 256 ];
            switch ( ReqToken )
            {   
                // Integer

                case TOKEN_TYPE_INT:
                    strcpy ( pstrErrorMssg, "Integer" );
                    break;

                // Float

                case TOKEN_TYPE_FLOAT:
                    strcpy ( pstrErrorMssg, "Float" );
                    break;

                // Identifier

                case TOKEN_TYPE_IDENT:
                    strcpy ( pstrErrorMssg, "Identifier" );
                    break;

                // var

                case TOKEN_TYPE_RSRVD_VAR:
                    strcpy ( pstrErrorMssg, "var" );
                    break;

                // true

                case TOKEN_TYPE_RSRVD_TRUE:
                    strcpy ( pstrErrorMssg, "true" );
                    break;

                // false

                case TOKEN_TYPE_RSRVD_FALSE:
                    strcpy ( pstrErrorMssg, "false" );
                    break;

                // if

                case TOKEN_TYPE_RSRVD_IF:
                    strcpy ( pstrErrorMssg, "if" );
                    break;

                // else

                case TOKEN_TYPE_RSRVD_ELSE:
                    strcpy ( pstrErrorMssg, "else" );
                    break;

                // break

                case TOKEN_TYPE_RSRVD_BREAK:
                    strcpy ( pstrErrorMssg, "break" );
                    break;

                // continue

                case TOKEN_TYPE_RSRVD_CONTINUE:
                    strcpy ( pstrErrorMssg, "continue" );
                    break;

                // for

                case TOKEN_TYPE_RSRVD_FOR:
                    strcpy ( pstrErrorMssg, "for" );
                    break;

                // while

                case TOKEN_TYPE_RSRVD_WHILE:
                    strcpy ( pstrErrorMssg, "while" );
                    break;

                // func

                case TOKEN_TYPE_RSRVD_FUNC:
                    strcpy ( pstrErrorMssg, "func" );
                    break;

                // return

                case TOKEN_TYPE_RSRVD_RETURN:
                    strcpy ( pstrErrorMssg, "return" );
                    break;

                // host

                case TOKEN_TYPE_RSRVD_HOST:
                    strcpy ( pstrErrorMssg, "host" );
                    break;

                // Operator

                case TOKEN_TYPE_OP:
                    strcpy ( pstrErrorMssg, "Operator" );
                    break;

                // Comma

                case TOKEN_TYPE_DELIM_COMMA:
                    strcpy ( pstrErrorMssg, "," );
                    break;

                // Open parenthesis

                case TOKEN_TYPE_DELIM_OPEN_PAREN:
                    strcpy ( pstrErrorMssg, "(" );
                    break;

                // Close parenthesis

                case TOKEN_TYPE_DELIM_CLOSE_PAREN:
                    strcpy ( pstrErrorMssg, ")" );
                    break;

                // Open brace

                case TOKEN_TYPE_DELIM_OPEN_BRACE:
                    strcpy ( pstrErrorMssg, "[" );
                    break;

                // Close brace

                case TOKEN_TYPE_DELIM_CLOSE_BRACE:
                    strcpy ( pstrErrorMssg, "]" );
                    break;

                // Open curly brace

                case TOKEN_TYPE_DELIM_OPEN_CURLY_BRACE:
                    strcpy ( pstrErrorMssg, "{" );
                    break;

                // Close curly brace

                case TOKEN_TYPE_DELIM_CLOSE_CURLY_BRACE:
                    strcpy ( pstrErrorMssg, "}" );
                    break;

                // Semicolon

                case TOKEN_TYPE_DELIM_SEMICOLON:
                    strcpy ( pstrErrorMssg, ";" );
                    break;

                // String

                case TOKEN_TYPE_STRING:
                    strcpy ( pstrErrorMssg, "String" );
                    break;
            }

            // Finish the message

            strcat ( pstrErrorMssg, " expected" );

            // Display the error

            ExitOnCodeError ( pstrErrorMssg );
        }
    }

    /******************************************************************************************
    *
    *   IsOpRelational ()
    *
    *   Determines if the specified operator is a relational operator.
    */

    int IsOpRelational ( int iOpType )
    {
        if ( iOpType != OP_TYPE_EQUAL &&
             iOpType != OP_TYPE_NOT_EQUAL &&
             iOpType != OP_TYPE_LESS && 
             iOpType != OP_TYPE_GREATER &&
             iOpType != OP_TYPE_LESS_EQUAL && 
             iOpType != OP_TYPE_GREATER_EQUAL )
            return FALSE;
        else
            return TRUE;
    }

    /******************************************************************************************
    *
    *   IsOpLogical ()
    *
    *   Determines if the specified operator is a logical operator.
    */

    int IsOpLogical ( int iOpType )
    {
        if ( iOpType != OP_TYPE_LOGICAL_AND &&
             iOpType != OP_TYPE_LOGICAL_OR &&
             iOpType != OP_TYPE_LOGICAL_NOT )
            return FALSE;
        else
            return TRUE;
    }

    /******************************************************************************************
    *
    *   ParseSourceCode ()
    *
    *   Parses the source code from start to finish, generating a complete I-code
    *   representation.
    */

    void ParseSourceCode ()
    {
        // Reset the lexer

        ResetLexer ();

        // Initialize the loop stack

        InitStack ( & g_LoopStack );

        // Set the current scope to global

        g_iCurrScope = SCOPE_GLOBAL;

        // Parse each line of code

        while ( TRUE )
        {
            // Parse the next statement and ignore an end of file marker

            ParseStatement ();

            // If we're at the end of the token stream, break the parsing loop

            if ( GetNextToken () == TOKEN_TYPE_END_OF_STREAM )
                break;
            else
                RewindTokenStream ();
        }

        // Free the loop stack

        FreeStack ( & g_LoopStack );
    }

    /******************************************************************************************
    *
    *   ParseStatement ()
    *
    *   Parses a statement.
    */

    void ParseStatement ()
    {
        // If the next token is a semicolon, the statement is empty so return

        if ( GetLookAheadChar () == ';' )
        {
            ReadToken ( TOKEN_TYPE_DELIM_SEMICOLON );
            return;
        }

        // Determine the initial token of the statement

        Token InitToken = GetNextToken ();

        // Branch to a parse function based on the token

        switch ( InitToken )
        {
            // Unexpected end of file

            case TOKEN_TYPE_END_OF_STREAM:
                ExitOnCodeError ( "Unexpected end of file" );
                break;

            // Block

            case TOKEN_TYPE_DELIM_OPEN_CURLY_BRACE:
                ParseBlock ();
                break;

            // Variable/array declaration

            case TOKEN_TYPE_RSRVD_VAR:
                ParseVar ();
                break;

            // Host API function import

            case TOKEN_TYPE_RSRVD_HOST:
                ParseHost ();
                break;

            // Function definition

            case TOKEN_TYPE_RSRVD_FUNC:
                ParseFunc ();
                break;

            // if block

            case TOKEN_TYPE_RSRVD_IF:
                ParseIf ();
                break;

            // while loop block

            case TOKEN_TYPE_RSRVD_WHILE:
                ParseWhile ();
                break;

            // for loop block

            case TOKEN_TYPE_RSRVD_FOR:
                ParseFor ();
                break;

            // break

            case TOKEN_TYPE_RSRVD_BREAK:
                ParseBreak ();
                break;

            // continue

            case TOKEN_TYPE_RSRVD_CONTINUE:
                ParseContinue ();
                break;

            // return

            case TOKEN_TYPE_RSRVD_RETURN:
                ParseReturn ();
                break;

            // Assignment or Function Call

            case TOKEN_TYPE_IDENT:
            {
                // What kind of identifier is it?

                if ( GetSymbolByIdent ( GetCurrLexeme (), g_iCurrScope ) )
                {
                    // It's an identifier, so treat the statement as an assignment

                    ParseAssign ();
                }
                else if ( GetFuncByName ( GetCurrLexeme () ) )
                {
                    // It's a function
                    
                    // Annotate the line and parse the call

                    AddICodeSourceLine ( g_iCurrScope, GetCurrSourceLine () );
                    ParseFuncCall ();

                    // Verify the presence of the semicolon

                    ReadToken ( TOKEN_TYPE_DELIM_SEMICOLON );
                }
                else
                {
                    // It's invalid

                    ExitOnCodeError ( "Invalid identifier" );
                }

                break;
            }

            // Anything else is invalid

            default:
                ExitOnCodeError ( "Unexpected input" );
                break;
        }
    }

    /******************************************************************************************
    *
    *   ParseBlock ()
    *
    *   Parses a code block.
    *
    *       { <Statement-List> }
    */

    void ParseBlock ()
    {
        // Make sure we're not in the global scope

        if ( g_iCurrScope == SCOPE_GLOBAL )
            ExitOnCodeError ( "Code blocks illegal in global scope" );

        // Read each statement until the end of the block

        while ( GetLookAheadChar () != '}' )
            ParseStatement ();

        // Read the closing curly brace

        ReadToken ( TOKEN_TYPE_DELIM_CLOSE_CURLY_BRACE );
    }

    /******************************************************************************************
    *
    *   ParseVar ()
    *
    *   Parses the declaration of a variable or array and adds it to the symbol table.
    *
    *       var <Identifier>;
    *       var <Identifier> [ <Integer> ];
    */

    void ParseVar ()
    {
        // Read an identifier token

        ReadToken ( TOKEN_TYPE_IDENT );

        // Copy the current lexeme into a local string buffer to save the variable's identifier

        char pstrIdent [ MAX_LEXEME_SIZE ];
        CopyCurrLexeme ( pstrIdent );

        // Set the size to 1 for a variable (an array will update this value)

        int iSize = 1;

        // Is the look-ahead character an open brace?

        if ( GetLookAheadChar () == '[' )
        {
            // Verify the open brace

            ReadToken ( TOKEN_TYPE_DELIM_OPEN_BRACE );

            // If so, read an integer token

            ReadToken ( TOKEN_TYPE_INT );

            // Convert the current lexeme to an integer to get the size

            iSize = atoi ( GetCurrLexeme () );

            // Read the closing brace

⌨️ 快捷键说明

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