📄 parser.cpp
字号:
ReadToken ( TOKEN_TYPE_DELIM_CLOSE_BRACE );
}
// Add the identifier and size to the symbol table
if ( AddSymbol ( pstrIdent, iSize, g_iCurrScope, SYMBOL_TYPE_VAR ) == -1 )
ExitOnCodeError ( "Identifier redefinition" );
// Read the semicolon
ReadToken ( TOKEN_TYPE_DELIM_SEMICOLON );
}
/******************************************************************************************
*
* ParseHostAPIFuncImport ()
*
* Parses the importing of a host API function.
*
* host <Identifier> ();
*/
void ParseHost ()
{
// Read the host API function name
ReadToken ( TOKEN_TYPE_IDENT );
// Add the function to the function table with the host API flag set
if ( AddFunc ( GetCurrLexeme (), TRUE ) == -1 )
ExitOnCodeError ( "Function redefinition" );
// Make sure the function name is followed with ()
ReadToken ( TOKEN_TYPE_DELIM_OPEN_PAREN );
ReadToken ( TOKEN_TYPE_DELIM_CLOSE_PAREN );
// Read the semicolon
ReadToken ( TOKEN_TYPE_DELIM_SEMICOLON );
}
/******************************************************************************************
*
* ParseFunc ()
*
* Parses a function.
*
* func <Identifier> ( <Parameter-List> ) <Statement>
*/
void ParseFunc ()
{
// Make sure we're not already in a function
if ( g_iCurrScope != SCOPE_GLOBAL )
ExitOnCodeError ( "Nested functions illegal" );
// Read the function name
ReadToken ( TOKEN_TYPE_IDENT );
// Add the non-host API function to the function table and get its index
int iFuncIndex = AddFunc ( GetCurrLexeme (), FALSE );
// Check for a function redefinition
if ( iFuncIndex == -1 )
ExitOnCodeError ( "Function redefinition" );
// Set the scope to the function
g_iCurrScope = iFuncIndex;
// Read the opening parenthesis
ReadToken ( TOKEN_TYPE_DELIM_OPEN_PAREN );
// Use the look-ahead character to determine if the function takes parameters
if ( GetLookAheadChar () != ')' )
{
// If the function being defined is _Main (), flag an error since _Main ()
// cannot accept paraemters
if ( g_ScriptHeader.iIsMainFuncPresent &&
g_ScriptHeader.iMainFuncIndex == iFuncIndex )
{
ExitOnCodeError ( "_Main () cannot accept parameters" );
}
// Start the parameter count at zero
int iParamCount = 0;
// Crete an array to store the parameter list locally
char ppstrParamList [ MAX_FUNC_DECLARE_PARAM_COUNT ][ MAX_IDENT_SIZE ];
// Read the parameters
while ( TRUE )
{
// Read the identifier
ReadToken ( TOKEN_TYPE_IDENT );
// Copy the current lexeme to the parameter list array
CopyCurrLexeme ( ppstrParamList [ iParamCount ] );
// Increment the parameter count
++ iParamCount;
// Check again for the closing parenthesis to see if the parameter list is done
if ( GetLookAheadChar () == ')' )
break;
// Otherwise read a comma and move to the next parameter
ReadToken ( TOKEN_TYPE_DELIM_COMMA );
}
// Set the final parameter count
SetFuncParamCount ( g_iCurrScope, iParamCount );
// Write the parameters to the function's symbol table in reverse order, so they'll
// be emitted from right-to-left
while ( iParamCount > 0 )
{
-- iParamCount;
// Add the parameter to the symbol table
AddSymbol ( ppstrParamList [ iParamCount ], 1, g_iCurrScope, SYMBOL_TYPE_PARAM );
}
}
// Read the closing parenthesis
ReadToken ( TOKEN_TYPE_DELIM_CLOSE_PAREN );
// Read the opening curly brace
ReadToken ( TOKEN_TYPE_DELIM_OPEN_CURLY_BRACE );
// Parse the function's body
ParseBlock ();
// Return to the global scope
g_iCurrScope = SCOPE_GLOBAL;
}
/******************************************************************************************
*
* ParseExpr ()
*
* Parses an expression.
*/
void ParseExpr ()
{
int iInstrIndex;
// The current operator type
int iOpType;
// Parse the subexpression
ParseSubExpr ();
// Parse any subsequent relational or logical operators
while ( TRUE )
{
// Get the next token
if ( GetNextToken () != TOKEN_TYPE_OP ||
( ! IsOpRelational ( GetCurrOp () ) &&
! IsOpLogical ( GetCurrOp () ) ) )
{
RewindTokenStream ();
break;
}
// Save the operator
iOpType = GetCurrOp ();
// Parse the second term
ParseSubExpr ();
// Pop the first operand into _T1
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_POP );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar1SymbolIndex );
// Pop the second operand into _T0
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_POP );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
// ---- Perform the binary operation associated with the specified operator
// Determine the operator type
if ( IsOpRelational ( iOpType ) )
{
// Get a pair of free jump target indices
int iTrueJumpTargetIndex = GetNextJumpTargetIndex (),
iExitJumpTargetIndex = GetNextJumpTargetIndex ();
// It's a relational operator
switch ( iOpType )
{
// Equal
case OP_TYPE_EQUAL:
{
// Generate a JE instruction
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JE );
break;
}
// Not Equal
case OP_TYPE_NOT_EQUAL:
{
// Generate a JNE instruction
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JNE );
break;
}
// Greater
case OP_TYPE_GREATER:
{
// Generate a JG instruction
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JG );
break;
}
// Less
case OP_TYPE_LESS:
{
// Generate a JL instruction
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JL );
break;
}
// Greater or Equal
case OP_TYPE_GREATER_EQUAL:
{
// Generate a JGE instruction
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JGE );
break;
}
// Less Than or Equal
case OP_TYPE_LESS_EQUAL:
{
// Generate a JLE instruction
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JLE );
break;
}
}
// Add the jump instruction's operands (_T0 and _T1)
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar1SymbolIndex );
AddJumpTargetICodeOp ( g_iCurrScope, iInstrIndex, iTrueJumpTargetIndex );
// Generate the outcome for falsehood
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 0 );
// Generate a jump past the true outcome
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JMP );
AddJumpTargetICodeOp ( g_iCurrScope, iInstrIndex, iExitJumpTargetIndex );
// Set the jump target for the true outcome
AddICodeJumpTarget ( g_iCurrScope, iTrueJumpTargetIndex );
// Generate the outcome for truth
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 1 );
// Set the jump target for exiting the operand evaluation
AddICodeJumpTarget ( g_iCurrScope, iExitJumpTargetIndex );
}
else
{
// It must be a logical operator
switch ( iOpType )
{
// And
case OP_TYPE_LOGICAL_AND:
{
// Get a pair of free jump target indices
int iFalseJumpTargetIndex = GetNextJumpTargetIndex (),
iExitJumpTargetIndex = GetNextJumpTargetIndex ();
// JE _T0, 0, True
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JE );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 0 );
AddJumpTargetICodeOp ( g_iCurrScope, iInstrIndex, iFalseJumpTargetIndex );
// JE _T1, 0, True
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JE );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar1SymbolIndex );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 0 );
AddJumpTargetICodeOp ( g_iCurrScope, iInstrIndex, iFalseJumpTargetIndex );
// Push 1
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 1 );
// Jmp Exit
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JMP );
AddJumpTargetICodeOp ( g_iCurrScope, iInstrIndex, iExitJumpTargetIndex );
// L0: (False)
AddICodeJumpTarget ( g_iCurrScope, iFalseJumpTargetIndex );
// Push 0
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 0 );
// L1: (Exit)
AddICodeJumpTarget ( g_iCurrScope, iExitJumpTargetIndex );
break;
}
// Or
case OP_TYPE_LOGICAL_OR:
{
// Get a pair of free jump target indices
int iTrueJumpTargetIndex = GetNextJumpTargetIndex (),
iExitJumpTargetIndex = GetNextJumpTargetIndex ();
// JNE _T0, 0, True
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JNE );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 0 );
AddJumpTargetICodeOp ( g_iCurrScope, iInstrIndex, iTrueJumpTargetIndex );
// JNE _T1, 0, True
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JNE );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar1SymbolIndex );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 0 );
AddJumpTargetICodeOp ( g_iCurrScope, iInstrIndex, iTrueJumpTargetIndex );
// Push 0
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 0 );
// Jmp Exit
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JMP );
AddJumpTargetICodeOp ( g_iCurrScope, iInstrIndex, iExitJumpTargetIndex );
// L0: (True)
AddICodeJumpTarget ( g_iCurrScope, iTrueJumpTargetIndex );
// Push 1
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 1 );
// L1: (Exit)
AddICodeJumpTarget ( g_iCurrScope, iExitJumpTargetIndex );
break;
}
}
}
}
}
/******************************************************************************************
*
* ParseSubExpr ()
*
* Parses a sub expression.
*/
void ParseSubExpr ()
{
int iInstrIndex;
// The current operator type
int iOpType;
// Parse the first term
ParseTerm ();
// Parse any subsequent +, - or $ operators
while ( TRUE )
{
// Get the next token
if ( GetNextToken () != TOKEN_TYPE_OP ||
( GetCurrOp () != OP_TYPE_ADD &&
GetCurrOp () != OP_TYPE_SUB &&
GetCurrOp () != OP_TYPE_CONCAT ) )
{
RewindTokenStream ();
break;
}
// Save the operator
iOpType = GetCurrOp ();
// Parse the second term
ParseTerm ();
// Pop the first operand into _T1
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_POP );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar1SymbolIndex );
// Pop the second operand into _T0
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_POP );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
// Perform the binary operation associated with the specified operator
int iOpInstr;
switch ( iOpType )
{
// Binary addition
case OP_TYPE_ADD:
iOpInstr = INSTR_ADD;
break;
// Binary subtraction
case OP_TYPE_SUB:
iOpInstr = INSTR_SUB;
break;
// Binary string concatenation
case OP_TYPE_CONCAT:
iOpInstr = INSTR_CONCAT;
break;
}
iInstrIndex = AddICodeInstr ( g_iCurrScope, iOpInstr );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -