📄 parser.cpp
字号:
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar1SymbolIndex );
// Push the result (stored in _T0)
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
}
}
/******************************************************************************************
*
* ParseTerm ()
*
* Parses a term.
*/
void ParseTerm ()
{
int iInstrIndex;
// The current operator type
int iOpType;
// Parse the first factor
ParseFactor ();
// Parse any subsequent *, /, %, ^, &, |, #, << and >> operators
while ( TRUE )
{
// Get the next token
if ( GetNextToken () != TOKEN_TYPE_OP ||
( GetCurrOp () != OP_TYPE_MUL &&
GetCurrOp () != OP_TYPE_DIV &&
GetCurrOp () != OP_TYPE_MOD &&
GetCurrOp () != OP_TYPE_EXP &&
GetCurrOp () != OP_TYPE_BITWISE_AND &&
GetCurrOp () != OP_TYPE_BITWISE_OR &&
GetCurrOp () != OP_TYPE_BITWISE_XOR &&
GetCurrOp () != OP_TYPE_BITWISE_SHIFT_LEFT &&
GetCurrOp () != OP_TYPE_BITWISE_SHIFT_RIGHT ) )
{
RewindTokenStream ();
break;
}
// Save the operator
iOpType = GetCurrOp ();
// Parse the second factor
ParseFactor ();
// 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 multiplication
case OP_TYPE_MUL:
iOpInstr = INSTR_MUL;
break;
// Binary division
case OP_TYPE_DIV:
iOpInstr = INSTR_DIV;
break;
// Binary modulus
case OP_TYPE_MOD:
iOpInstr = INSTR_MOD;
break;
// Binary exponentiation
case OP_TYPE_EXP:
iOpInstr = INSTR_EXP;
break;
// Binary bitwise AND
case OP_TYPE_BITWISE_AND:
iOpInstr = INSTR_AND;
break;
// Binary bitwise OR
case OP_TYPE_BITWISE_OR:
iOpInstr = INSTR_OR;
break;
// Binary bitwise XOR
case OP_TYPE_BITWISE_XOR:
iOpInstr = INSTR_XOR;
break;
// Binary bitwise shift left
case OP_TYPE_BITWISE_SHIFT_LEFT:
iOpInstr = INSTR_SHL;
break;
// Binary bitwise shift left
case OP_TYPE_BITWISE_SHIFT_RIGHT:
iOpInstr = INSTR_SHR;
break;
}
iInstrIndex = AddICodeInstr ( g_iCurrScope, iOpInstr );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar1SymbolIndex );
// Push the result (stored in _T0)
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
}
}
/******************************************************************************************
*
* ParseFactor ()
*
* Parses a factor.
*/
void ParseFactor ()
{
int iInstrIndex;
int iUnaryOpPending = FALSE;
int iOpType;
// First check for a unary operator
if ( GetNextToken () == TOKEN_TYPE_OP &&
( GetCurrOp () == OP_TYPE_ADD ||
GetCurrOp () == OP_TYPE_SUB ||
GetCurrOp () == OP_TYPE_BITWISE_NOT ||
GetCurrOp () == OP_TYPE_LOGICAL_NOT ) )
{
// If it was found, save it and set the unary operator flag
iUnaryOpPending = TRUE;
iOpType = GetCurrOp ();
}
else
{
// Otherwise rewind the token stream
RewindTokenStream ();
}
// Determine which type of factor we're dealing with based on the next token
switch ( GetNextToken () )
{
// It's a true or false constant, so push either 0 and 1 onto the stack
case TOKEN_TYPE_RSRVD_TRUE:
case TOKEN_TYPE_RSRVD_FALSE:
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, GetCurrToken () == TOKEN_TYPE_RSRVD_TRUE ? 1 : 0 );
break;
// It's an integer literal, so push it onto the stack
case TOKEN_TYPE_INT:
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, atoi ( GetCurrLexeme () ) );
break;
// It's a float literal, so push it onto the stack
case TOKEN_TYPE_FLOAT:
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddFloatICodeOp ( g_iCurrScope, iInstrIndex, ( float ) atof ( GetCurrLexeme () ) );
break;
// It's a string literal, so add it to the string table and push the resulting
// string index onto the stack
case TOKEN_TYPE_STRING:
{
int iStringIndex = AddString ( & g_StringTable, GetCurrLexeme () );
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddStringICodeOp ( g_iCurrScope, iInstrIndex, iStringIndex );
break;
}
// It's an identifier
case TOKEN_TYPE_IDENT:
{
// First find out if the identifier is a variable or array
SymbolNode * pSymbol = GetSymbolByIdent ( GetCurrLexeme (), g_iCurrScope );
if ( pSymbol )
{
// Does an array index follow the identifier?
if ( GetLookAheadChar () == '[' )
{
// Ensure the variable is an array
if ( pSymbol->iSize == 1 )
ExitOnCodeError ( "Invalid array" );
// Verify the opening brace
ReadToken ( TOKEN_TYPE_DELIM_OPEN_BRACE );
// Make sure an expression is present
if ( GetLookAheadChar () == ']' )
ExitOnCodeError ( "Invalid expression" );
// Parse the index as an expression recursively
ParseExpr ();
// Make sure the index is closed
ReadToken ( TOKEN_TYPE_DELIM_CLOSE_BRACE );
// Pop the resulting value into _T0 and use it as the index variable
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_POP );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
// Push the original identifier onto the stack as an array, indexed
// with _T0
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddArrayIndexVarICodeOp ( g_iCurrScope, iInstrIndex, pSymbol->iIndex, g_iTempVar0SymbolIndex );
}
else
{
// If not, make sure the identifier is not an array, and push it onto
// the stack
if ( pSymbol->iSize == 1 )
{
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, pSymbol->iIndex );
}
else
{
ExitOnCodeError ( "Arrays must be indexed" );
}
}
}
else
{
// The identifier wasn't a variable or array, so find out if it's a
// function
if ( GetFuncByName ( GetCurrLexeme () ) )
{
// It is, so parse the call
ParseFuncCall ();
// Push the return value
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddRegICodeOp ( g_iCurrScope, iInstrIndex, REG_CODE_RETVAL );
}
}
break;
}
// It's a nested expression, so call ParseExpr () recursively and validate the
// presence of the closing parenthesis
case TOKEN_TYPE_DELIM_OPEN_PAREN:
ParseExpr ();
ReadToken ( TOKEN_TYPE_DELIM_CLOSE_PAREN );
break;
// Anything else is invalid
default:
ExitOnCodeError ( "Invalid input" );
}
// Is a unary operator pending?
if ( iUnaryOpPending )
{
// If so, pop the result of the factor off the top of the stack
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_POP );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
// Perform the unary operation
if ( iOpType == OP_TYPE_LOGICAL_NOT )
{
// Get a pair of free jump target indices
int iTrueJumpTargetIndex = 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, iTrueJumpTargetIndex );
// Push 0
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 0 );
// Jmp L1
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 );
}
else
{
int iOpIndex;
switch ( iOpType )
{
// Negation
case OP_TYPE_SUB:
iOpIndex = INSTR_NEG;
break;
// Bitwise not
case OP_TYPE_BITWISE_NOT:
iOpIndex = INSTR_NOT;
break;
}
// Add the instruction's operand
iInstrIndex = AddICodeInstr ( g_iCurrScope, iOpIndex );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
// Push the result onto the stack
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_PUSH );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
}
}
}
/******************************************************************************************
*
* ParseIf ()
*
* Parses an if block.
*
* if ( <Expression> ) <Statement>
* if ( <Expression> ) <Statement> else <Statement>
*/
void ParseIf ()
{
int iInstrIndex;
// Make sure we're inside a function
if ( g_iCurrScope == SCOPE_GLOBAL )
ExitOnCodeError ( "if illegal in global scope" );
// Annotate the line
AddICodeSourceLine ( g_iCurrScope, GetCurrSourceLine () );
// Create a jump target to mark the beginning of the false block
int iFalseJumpTargetIndex = GetNextJumpTargetIndex ();
// Read the opening parenthesis
ReadToken ( TOKEN_TYPE_DELIM_OPEN_PAREN );
// Parse the expression and leave the result on the stack
ParseExpr ();
// Read the closing parenthesis
ReadToken ( TOKEN_TYPE_DELIM_CLOSE_PAREN );
// Pop the result into _T0 and compare it to zero
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_POP );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
// If the result is zero, jump to the false target
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JE );
AddVarICodeOp ( g_iCurrScope, iInstrIndex, g_iTempVar0SymbolIndex );
AddIntICodeOp ( g_iCurrScope, iInstrIndex, 0 );
AddJumpTargetICodeOp ( g_iCurrScope, iInstrIndex, iFalseJumpTargetIndex );
// Parse the true block
ParseStatement ();
// Look for an else clause
if ( GetNextToken () == TOKEN_TYPE_RSRVD_ELSE )
{
// If it's found, append the true block with an unconditional jump past the false
// block
int iSkipFalseJumpTargetIndex = GetNextJumpTargetIndex ();
iInstrIndex = AddICodeInstr ( g_iCurrScope, INSTR_JMP );
AddJumpTargetICodeOp ( g_iCurrScope, iInstrIndex, iSkipFalseJumpTargetIndex );
// Place the false target just before the false block
AddICodeJumpTarget ( g_iCurrScope, iFalseJumpTargetIndex );
// Parse the false block
ParseStatement ();
// Set a jump target beyond the false block
AddICodeJumpTarget ( g_iCurrScope, iSkipFalseJumpTargetIndex );
}
else
{
// Otherwise, put the token back
RewindTokenStream ();
// Place the false target after the true block
AddICodeJumpTarget ( g_iCurrScope, iFalseJumpTargetIndex );
}
}
/******************************************************************************************
*
* ParseWhile ()
*
* Parses a while loop block.
*
* while ( <Expression> ) <Statement>
*/
void ParseWhile ()
{
int iInstrIndex;
// Make sure we're inside a function
if ( g_iCurrScope == SCOPE_GLOBAL )
ExitOnCodeError ( "Statement illegal in global scope" );
// Annotate the line
AddICodeSourceLine ( g_iCurrScope, GetCurrSourceLine () );
// Get two jump targets; for the top and bottom of the loop
int iStartTargetIndex = GetNextJumpTargetIndex (),
iEndTargetIndex = GetNextJumpTargetIndex ();
// Set a jump target at the top of the loop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -