📄 stdinterpreter.cpp
字号:
/*=========================================================
StdInterpreter.cpp
Copyright (C) 2001, ClearJump, All Rights Reserved
=========================================================*/
#include "StdInterpreter.h"
#include <math.h>
//LOCAL DEFINITIONS
//=================
#define HEXMAXLEN (8)
#define DECMAXLEN (10)
//IMPLEMENTATION
//==============
StdInterpreter::StdInterpreter()
{
}
StdInterpreter::~StdInterpreter()
{
}
//'node' is of nid_String type
//this method appends the new string to 'str'
//it returns FALSE if there is an error
BOOL StdInterpreter::process_string( HPTNODE node, string& str )
{
HPTNODE child;
SPtnInfo info;
CPERR err;
string esc;
str="";
//enumerate children
child = m_parser->GetFirstChild( node );
for( ; child; child = m_parser->GetNextSibling(child) )
{
//the child node info
err = m_parser->GetNodeInfo( child, info );
if( err != CPERR_OK ) return error( child, err );
//look for esc codes and identifiers
//identifiers represent parts of the string
//between esc codes
switch( info.nNodeType )
{
case CPT_NONTERMINAL:
//correct strings should not contain any nonterminals
//except esc codes
if( info.nSymbolID != nid_EscCode )
return error( child, InterpreterError::E_BADTREE );
//get the esc code
if( !process_esccode(child, esc) )
return FALSE;
//append the code
str += esc;
break;
case CPT_IDENTIFIER:
//append the string chunk
str += info.pszIdentifier;
break;
default:
return error( child, InterpreterError::E_BADTREE );
}
}
return TRUE;
}
//nid_Integer
BOOL StdInterpreter::process_integer( HPTNODE node, UINT& num )
{
CPERR err;
HPTNODE child;
SPtnInfo info;
//get the child node
child = m_parser->GetFirstChild( node );
if( !child ) return error( node, InterpreterError::E_BADTREE );
//get the child info
err = m_parser->GetNodeInfo( child, info );
if( err != CPERR_OK ) return error( child, err );
//must be nonterminal
if( info.nNodeType != CPT_NONTERMINAL )
return error( child, InterpreterError::E_BADTREE );
switch( info.nSymbolID )
{
//hex integer
case nid_HexInteger:
return process_hexint( child, num );
//decimal integer
case nid_DecInteger:
return process_decint( child, num );
}
return error( child, InterpreterError::E_BADTREE );
}
//nid_HexInteger
BOOL StdInterpreter::process_hexint( HPTNODE node, UINT& num )
{
CPERR err;
HPTNODE child;
SPtnInfo info;
//get the child node
child = m_parser->GetFirstChild( node );
if( !child ) return error( node, InterpreterError::E_BADTREE );
//get the child info
err = m_parser->GetNodeInfo( child, info );
if( err != CPERR_OK ) return error( child, err );
//must be an identifier with the number
if( info.nNodeType != CPT_IDENTIFIER || !info.pszIdentifier )
return error( child, InterpreterError::E_BADTREE );
if( strlen(info.pszIdentifier) > HEXMAXLEN ) //the number is too long
//notify but don't stop
error( child, InterpreterError::E_NUMBER_TOOLONG );
CPCHAR *pdum;
string tmp;
tmp = "0x"; //hex number
tmp += info.pszIdentifier;
num = strtoul( tmp.data(), &pdum, 16 );
return TRUE;
}
//nid_DecInteger
BOOL StdInterpreter::process_decint( HPTNODE node, UINT& num )
{
CPERR err;
HPTNODE child;
SPtnInfo info;
//get the child node
child = m_parser->GetFirstChild( node );
if( !child ) return error( node, InterpreterError::E_BADTREE );
//get the child info
err = m_parser->GetNodeInfo( child, info );
if( err != CPERR_OK ) return error( child, err );
//must be an identifier with the number
if( info.nNodeType != CPT_IDENTIFIER || !info.pszIdentifier )
return error( child, InterpreterError::E_BADTREE );
if( strlen(info.pszIdentifier) > DECMAXLEN ) //the number is too long
//notify but don't stop
error( child, InterpreterError::E_NUMBER_TOOLONG );
CPCHAR *pdum;
num = strtoul( info.pszIdentifier, &pdum, 10 );
return TRUE;
}
//nid_SignedInteger
BOOL StdInterpreter::process_signed_integer( HPTNODE node, INT& num )
{
HPTNODE child;
//get the number sign
//-------------------
BOOL minus;
//get the child node
child = m_parser->GetFirstChild( node );
if( !child ) return error( node, InterpreterError::E_BADTREE );
//must be NumberSign symbol
if( !process_number_sign( child, minus ) )
return FALSE;
//get the number
//--------------
//the next child
child = m_parser->GetNextSibling( child );
if( !child ) return error( node, InterpreterError::E_BADTREE );
//get the number
//must be a decimal integer
UINT tmp;
if( !process_decint( child, tmp ) )
return FALSE;
if( tmp > INT_MAX )
//notify but don't stop
error( child, InterpreterError::E_NUMBER_TOOLONG );
//finally set the sign
if( minus ) num = (INT)tmp;
else num = -((INT)tmp);
return TRUE;
}
//nid_FloatNumber
BOOL StdInterpreter::process_float( HPTNODE node, double& num )
{
return process_number( node, num );
}
//nid_Number
BOOL StdInterpreter::process_number( HPTNODE node, double& num )
{
string numstr;
//we reconstruct the string in order to use strtod()
if( !reconstruct_number(node, numstr) )
return FALSE;
if( numstr.empty() )
return error( node, InterpreterError::E_BADTREE );
//convet the string
CPCHAR *end;
double x;
x = strtod( numstr.data(), &end );
if( x == HUGE_VAL ) //the number is too big
return error( node, InterpreterError::E_NUMBER_TOOLONG );
num = x;
return TRUE;
}
//nid_Symbol
BOOL StdInterpreter::process_symbol( HPTNODE node, CPCHAR& sym )
{
CPERR err;
HPTNODE child;
SPtnInfo info;
//get the child node
child = m_parser->GetFirstChild( node );
if( !child ) return error( node, InterpreterError::E_BADTREE );
//get the child info
err = m_parser->GetNodeInfo( child, info );
if( err != CPERR_OK ) return error( child, err );
//must be a terminal
if( info.nNodeType != CPT_TERMINAL )
return error( child, InterpreterError::E_BADTREE );
CPCSTR ps;
ps = get_match( info );
if( !ps ) return error( child, InterpreterError::E_BADTREE );
sym = ps[0];
return TRUE;
}
//nid_Identifer
BOOL StdInterpreter::process_identifier( HPTNODE node, CPCSTR *pid )
{
*pid = get_child_identifier( node );
if( !*pid ) return FALSE;
return TRUE;
}
//an empty error handler
void StdInterpreter::error_notify( InterpreterError& err )
{
}
//process string esc codes
//nid_EscCode
BOOL StdInterpreter::process_esccode( HPTNODE node, string& code )
{
HPTNODE child;
SPtnInfo info;
CPERR err;
UINT num_code;
CPCHAR tmp[2]={0,0};
//get the child node
child = m_parser->GetFirstChild( node );
if( !child ) return error( node, InterpreterError::E_BADTREE );
//get the child info
err = m_parser->GetNodeInfo( child, info );
if( err != CPERR_OK ) return error( child, err );
//process the child
switch( info.nNodeType )
{
//numeric code
case CPT_NONTERMINAL:
//numeric nonterminals only
if( info.nSymbolID != nid_Integer )
return error( child, InterpreterError::E_BADTREE );
//process the numeric code
if( !process_integer( child, num_code ) )
return FALSE;
//the number is too big?
if( num_code > (CPCHAR)(-1) )
//notify but don't stop
error( child, InterpreterError::E_NUMBER_TOOLONG );
//create the string
tmp[0] = (CPCHAR)num_code;
code = tmp;
break;
//get the code
case CPT_TERMINAL:
switch( info.nSymbolID ) //symbol id
{
case tid_esc_t:
code = "\t";
break;
case tid_esc_n:
code = "\n";
break;
case tid_esc_r:
code = "\r";
break;
//use the grammar item data to get
//the actual codes for these symbols
//as it was defined by the grammar
case tid_esc_open:
case tid_str_close:
case tid_str_open:
{
CPCSTR ps;
ps = get_match( info );
if( !ps ) return error( child, InterpreterError::E_BADTREE );
code = ps;
}
break;
default:
return error( child, InterpreterError::E_BADTREE );
}
break;
default:
return error( child, InterpreterError::E_BADTREE );
}
return TRUE;
}
//nid_NumberSign
BOOL StdInterpreter::process_number_sign( HPTNODE node, BOOL& minus )
{
CPERR err;
HPTNODE child;
SPtnInfo info;
//the sign is plus by default
minus = FALSE;
//get the child node
child = m_parser->GetFirstChild( node );
if( !child )
//no children, the sign is plus by default
return TRUE;
//get the child info
err = m_parser->GetNodeInfo( child, info );
if( err != CPERR_OK ) return error( child, err );
//must be a terminal
if( info.nNodeType != CPT_TERMINAL )
return error( node, InterpreterError::E_BADTREE );
//is it minus?
if( info.nSymbolID == tid_minus )
minus = TRUE;
return TRUE;
}
CPCSTR StdInterpreter::get_child_identifier( HPTNODE node )
{
CPERR err;
HPTNODE child;
SPtnInfo info;
//get the child node
child = m_parser->GetFirstChild( node );
if( !child )
{
error( node, InterpreterError::E_BADTREE );
return NULL;
}
//get the child info
err = m_parser->GetNodeInfo( child, info );
if( err != CPERR_OK )
{
error( child, err );
return NULL;
}
//must be an identifier
if( info.nNodeType != CPT_IDENTIFIER || !info.pszIdentifier )
{
error( child, InterpreterError::E_BADTREE );
return NULL;
}
return info.pszIdentifier;
}
//nid_FloatNumber & nid_Number
//we don't really check the grammar rules here,
//it should have already been done by the parser
BOOL StdInterpreter::reconstruct_number( HPTNODE node, string& numstr )
{
CPERR err;
HPTNODE child;
SPtnInfo info;
BOOL minus;
//reconstruct the number string
//---------------------------------------------------
child = m_parser->GetFirstChild( node );
if( !child ) return error( node, InterpreterError::E_BADTREE );
for( ; child; child = m_parser->GetNextSibling( child ) )
{
//get the child info
err = m_parser->GetNodeInfo( child, info );
if( err != CPERR_OK ) return error( child, err );
if( info.nNodeType == CPT_NONTERMINAL )
{
switch( info.nSymbolID )
{
case nid_DecInteger:
if( !append_decint( child, numstr ) )
return FALSE;
break;
case nid_ExpPoint:
numstr += "e";
break;
case nid_NumberSign:
if( !process_number_sign( child, minus ) )
return FALSE;
if( minus ) numstr += "-";
break;
case nid_FloatNumber:
if( !reconstruct_number( child, numstr ) )
return FALSE;
break;
case nid_Number:
if( !reconstruct_number( child, numstr ) )
return FALSE;
break;
}
}
//decimal point
else if( info.nNodeType == CPT_TERMINAL && info.nSymbolID == tid_dec_point )
{
numstr += ".";
}
else
{
return error( child, InterpreterError::E_BADTREE );
}
}
return TRUE;
}
//nid_DecInteger
BOOL StdInterpreter::append_decint( HPTNODE node, string& numstr )
{
CPCSTR ps;
ps = get_child_identifier( node );
if( !ps ) return error( node, InterpreterError::E_BADTREE );
numstr += ps;
return TRUE;
}
//get matching string for the terminal node
CPCSTR StdInterpreter::get_match( const SPtnInfo& info )
{
CPERR err;
SGramItem item;
//get grammar item for this node
err = m_parser->GramGetItemInfo( info.hGramItem, item );
if( err != CPERR_OK ) return NULL;
//the item must be a terminal
if( item.nItemType != GIT_TERMINAL )
return NULL;
return item.Term.pszMatch;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -