Files
Client/GameTools/ScriptEngine/SyntaxTree.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

548 lines
13 KiB
C++

#include "SyntaxTree.h"
#include "SymbolTable.h"
#include "lex.h"
#include <assert.h>
#include <set>
///////////////////////////////////////////////////////////////////////////////
// 전역변수
CSyntaxTree * g_pSynTree = 0;
CSymbolTable * g_pSymbolTable = 0;
char szBuffer[1024];
///////////////////////////////////////////////////////////////////////////////
// Parser 함수
void yyerror( char *msg )
{
CompilerMessage( msg );
}
extern "C" int yywrap(void) {
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// 멤버 함수
SNode::SNode( int line, eSyntaxType type, SNode * pNode1, SNode * pNode2, SNode * pNode3 )
: m_iLine( line ), m_eType( type ), m_SymbolID( 0 ), m_eReturnType( T_VOID )
{
m_ArrPtrChilds[0] = pNode1;
m_ArrPtrChilds[1] = pNode2;
m_ArrPtrChilds[2] = pNode3;
}
const char * SyntaxTypeName[] =
{
"TYPE_STATEMENT_LIST",
"TYPE_EMPTY_STATEMENT",
"TYPE_ERROR_STATEMENT",
"TYPE_EXPRESSION",
"TYPE_IF_STATEMENT",
"TYPE_IF_ELSE_STATEMENT",
"TYPE_SWITCH_STATEMENT",
"TYPE_SWITCH_CASES",
"TYPE_CASE_ONE",
"TYPE_DEFAULT",
"TYPE_FOR_STATEMENT",
"TYPE_WHILE_STATEMENT",
"TYPE_FOR_EXPRESSION",
"TYPE_BREAK_STATEMENT",
"TYPE_CONTINUE_STATEMENT",
"TYPE_RETURN_STATEMENT",
"TYPE_DECLARATION",
"TYPE_SPECIFIER_VOID",
"TYPE_SPECIFIER_INT",
"TYPE_SPECIFIER_FLOAT",
"TYPE_SPECIFIER_BOOL",
"TYPE_SPECIFIER_STRING",
"TYPE_VARIABLE",
"TYPE_DECLARATOR_LIST",
"TYPE_INIT_DECLARATION",
"TYPE_NORMAL_DECLARATION",
"TYPE_ARRAY_INITIALIZE",
"TYPE_ARRAY_INITIALIZE2",
"TYPE_ARRAY_DECLARATION",
"TYPE_FUNCTION_DECLARATION",
"TYPE_INITIALIZER_LIST",
"TYPE_ARGUMENT_DECLARATION_LIST",
"TYPE_ARGUMENT_DECLARATION",
"TYPE_FUNCTION_DEFINITION",
"TYPE_CONSTANT_EXPRESSION",
"TYPE_EXPRESSION_LIST",
"TYPE_ASSIGNMENT_EXPESSION",
"TYPE_OR_EXPRESSION",
"TYPE_AND_EXPRESSION",
"TYPE_NOT_EXPRESSION",
"TYPE_EQUALITY_EXPRESSION",
"TYPE_NOTEQAUL_EXPRESSION",
"TYPE_LESSTHAN_EXPRESSION",
"TYPE_MORETHAN_EXPRESSION",
"TYPE_LESSTHANOREQUAL_EXPRESSION",
"TYPE_MORETHANOREQUAL_EXPRESSION",
"TYPE_ADDITION_EXPRESSION",
"TYPE_SUBTRACTION_EXPRESSION",
"TYPE_MULTIPLICATION_EXPRESSION",
"TYPE_DIVISION_EXPRESSION",
"TYPE_REMINDER_EXPRESSION",
"TYPE_COMPOUND_ADDITION",
"TYPE_COMPOUND_SUBTRACTION",
"TYPE_COMPOUND_MULTIPLICATION",
"TYPE_COMPOUND_DIVISION",
"TYPE_COMPOUND_REMINDER",
"TYPE_PREFIXINCREMENT",
"TYPE_PREFIXDECREMENT",
"TYPE_ARRAY_INDEXING",
"TYPE_FUNCTION_CALL",
"TYPE_POSTFIXINCREMENT",
"TYPE_POSTFIXDECREMENT"
};
void SNode::Show( int level, MESSAGE_FUNCTION2 Print, CSymbolTable * pSymbolTable )
{
const char * DataTypeString[] = { "void", "bool", "int", "float", "string" };
int nl = level;
if (!this) return;
if( m_eType != TYPE_STATEMENT_LIST )
{
Print( itoa( m_iLine, szBuffer, 10 ) );
Print( ": " );
for ( int i = 0; i < level; i++ )
Print( " " );
Print( SyntaxTypeName[m_eType] );
switch( m_eType )
{
case TYPE_CONSTANT_EXPRESSION :
Print( " ( " );
Print( pSymbolTable->GetNameOfConst( m_SymbolID ) );
Print( " : " );
Print( DataTypeString[ pSymbolTable->GetTypeOfConst( m_SymbolID ) ] );
Print( " )" );
break;
case TYPE_INIT_DECLARATION :
case TYPE_NORMAL_DECLARATION :
case TYPE_ARRAY_INITIALIZE :
case TYPE_ARRAY_INITIALIZE2 :
case TYPE_ARRAY_DECLARATION :
case TYPE_ARGUMENT_DECLARATION :
case TYPE_VARIABLE :
case TYPE_PREFIXINCREMENT :
case TYPE_PREFIXDECREMENT :
case TYPE_POSTFIXINCREMENT :
case TYPE_POSTFIXDECREMENT :
case TYPE_COMPOUND_ADDITION :
case TYPE_COMPOUND_SUBTRACTION :
case TYPE_COMPOUND_MULTIPLICATION :
case TYPE_COMPOUND_DIVISION :
case TYPE_COMPOUND_REMINDER :
Print( " ( " );
Print( pSymbolTable->GetNameOfVar( m_SymbolID ) );
Print( " : " );
Print( DataTypeString[ pSymbolTable->GetTypeOfVar( m_SymbolID ) ] );
Print( " )" );
break;
}
nl++;
Print("\n");
}
for( int i = 0; m_ArrPtrChilds[i] != 0 && i < 3; i++ )
m_ArrPtrChilds[i]->Show( nl, Print, pSymbolTable );
}
bool SNode::SemanticCheck( CSymbolTable * pSymbolTable )
{
static eDataType tempType, tempType2;
switch( m_eType )
{
case TYPE_ARRAY_INDEXING :
//첫번째 int일때만 유효하고, 심볼의 타입에 의해 타입이 결정됨.
if( m_ArrPtrChilds[0]->m_eReturnType != T_INT )
return false;
else
m_eReturnType = pSymbolTable->GetTypeOfVar( m_SymbolID );
break;
case TYPE_EXPRESSION :
m_eReturnType = m_ArrPtrChilds[0]->m_eReturnType;
break;
case TYPE_ARRAY_DECLARATION :
//첫번째 차일드가 int일때만 유효하고, 심볼 타입에 의해 타입이 결정됨.
if( m_ArrPtrChilds[0]->m_eReturnType != T_INT )
return false;
else
m_eReturnType = pSymbolTable->GetTypeOfVar( m_SymbolID );
break;
case TYPE_ARRAY_INITIALIZE2 :
//심볼 타입과 두번재 차일드의 타입이 같은지 검사하고 같을 때 심볼 타입을 리턴
//첫번째 차일드는 int형이어야 함.
m_eReturnType = pSymbolTable->GetTypeOfVar( m_SymbolID );
if( m_ArrPtrChilds[0]->m_eReturnType != T_INT )
return false;
if( m_eReturnType != m_ArrPtrChilds[1]->m_eReturnType )
return false;
break;
case TYPE_ARRAY_INITIALIZE :
//심볼 타입과 첫번째 차일드의 타입이 같아야 함.
m_eReturnType = pSymbolTable->GetTypeOfVar( m_SymbolID );
if( m_eReturnType != m_ArrPtrChilds[0]->m_eReturnType )
return false;
break;
case TYPE_INIT_DECLARATION :
case TYPE_ASSIGNMENT_EXPRESSION :
//심볼 타입과 첫번째 차일드의 타입이 같은지 검사하고 같을 때 심볼 타입을 리턴
m_eReturnType = pSymbolTable->GetTypeOfVar( m_SymbolID );
if( m_eReturnType == T_VOID )
return false;
if( m_eReturnType != m_ArrPtrChilds[0]->m_eReturnType )
{
if( m_eReturnType != T_STRING )
return false;
}
break;
case TYPE_INITIALIZER_LIST :
m_eReturnType = m_ArrPtrChilds[0]->m_eReturnType;
if( m_eReturnType == T_STRING )
{
if( m_ArrPtrChilds[1]->m_eReturnType == T_VOID )
return false;
}
else if( m_ArrPtrChilds[1]->m_eReturnType == T_STRING )
{
if( m_eReturnType == T_VOID )
return false;
m_eReturnType = T_STRING;
}
else
{
if( m_eReturnType != m_ArrPtrChilds[1]->m_eReturnType )
break;
}
break;
case TYPE_DECLARATOR_LIST :
//첫번째 차일드와 두번째 차일드의 타입이 같은지 검사하고 같을 때 첫번째 차일드 타입 리턴
if( m_ArrPtrChilds[0]->m_eReturnType != m_ArrPtrChilds[1]->m_eReturnType )
return false;
else
m_eReturnType = m_ArrPtrChilds[0]->m_eReturnType;
break;
case TYPE_ADDITION_EXPRESSION :
m_eReturnType = m_ArrPtrChilds[0]->m_eReturnType;
if( m_eReturnType == T_STRING )
{
if( m_ArrPtrChilds[1]->m_eReturnType == T_VOID )
return false;
}
else if( m_ArrPtrChilds[1]->m_eReturnType == T_STRING )
{
if( m_eReturnType == T_VOID )
return false;
m_eReturnType = T_STRING;
}
else
{
if( m_eReturnType != m_ArrPtrChilds[1]->m_eReturnType )
return false;
}
break;
case TYPE_SUBTRACTION_EXPRESSION :
case TYPE_MULTIPLICATION_EXPRESSION :
case TYPE_DIVISION_EXPRESSION :
//첫번째 차일드와 두번째 차일드가 다를 때는 무효, int나 float형이 아닐 경우에도 무효
if( m_ArrPtrChilds[0]->m_eReturnType != m_ArrPtrChilds[1]->m_eReturnType )
{
return false;
}
m_eReturnType = m_ArrPtrChilds[0]->m_eReturnType;
if( m_eReturnType != T_INT && m_eReturnType != T_FLOAT )
return false;
break;
case TYPE_REMINDER_EXPRESSION :
//첫번째 차일드와 두번째 차일드가 다를 때는 무효, int형이 아닐 경우에도 무효
if( m_ArrPtrChilds[0]->m_eReturnType != m_ArrPtrChilds[1]->m_eReturnType )
{
return false;
break;
}
m_eReturnType = m_ArrPtrChilds[0]->m_eReturnType;
if( m_eReturnType != T_INT )
return false;
break;
case TYPE_PREFIXINCREMENT :
case TYPE_PREFIXDECREMENT :
case TYPE_POSTFIXINCREMENT :
case TYPE_POSTFIXDECREMENT :
//int와 float형이 아닌 경우에는 무효.
m_eReturnType = pSymbolTable->GetTypeOfVar( m_SymbolID );
if( m_eReturnType != T_INT && m_eReturnType != T_FLOAT )
return false;
break;
case TYPE_NORMAL_DECLARATION :
case TYPE_CONSTANT_EXPRESSION :
case TYPE_VARIABLE :
//심볼의 타입이 이 노드의 타입을 결정
m_eReturnType = pSymbolTable->GetTypeOfVar( m_SymbolID );
break;
case TYPE_NOT_EXPRESSION :
//첫번째 차일드가 BOOL형일 경우에만 유효함.
if( m_ArrPtrChilds[0]->m_eReturnType != T_BOOL )
return false;
else
m_eReturnType = T_BOOL;
break;
case TYPE_OR_EXPRESSION :
case TYPE_AND_EXPRESSION :
//첫번째 차일드와 두번째 차일드가 모두 bool형일 때에만 유효함.
m_eReturnType = T_BOOL;
if( m_ArrPtrChilds[0]->m_eReturnType != T_BOOL || m_ArrPtrChilds[1]->m_eReturnType != T_BOOL )
{
return false;
}
break;
case TYPE_EQUALITY_EXPRESSION :
case TYPE_NOTEQAUL_EXPRESSION :
//왼쪽과 오른쪽의 타입이 같아야 하며, void는 허용 안됨.
tempType = m_ArrPtrChilds[0]->m_eReturnType;
if( tempType != m_ArrPtrChilds[1]->m_eReturnType || tempType == T_VOID )
return false;
else
m_eReturnType = T_BOOL;
break;
case TYPE_LESSTHAN_EXPRESSION :
case TYPE_MORETHAN_EXPRESSION :
case TYPE_LESSTHANOREQUAL_EXPRESSION :
case TYPE_MORETHANOREQUAL_EXPRESSION :
tempType = m_ArrPtrChilds[0]->m_eReturnType;
//첫 번째 차일드와 두 번째 차일드가 다를 때는 무효, int, float형이 아닐 경우에도 오류
if( tempType != m_ArrPtrChilds[1]->m_eReturnType )
return false;
if( tempType != T_INT && tempType != T_FLOAT )
return false;
m_eReturnType = T_BOOL;
break;
case TYPE_COMPOUND_ADDITION :
//심볼의 타입이 이 노드의 타입을 결정
m_eReturnType = pSymbolTable->GetTypeOfVar( m_SymbolID );
//int나 float, string형이 아닐 경우 무효
if( m_eReturnType != T_INT && m_eReturnType != T_FLOAT && m_eReturnType != T_STRING )
return false;
//심볼 타입과 첫번째 차일드가 다를 때는 심볼 타입이 string일 경우에만 유효
if( m_eReturnType != m_ArrPtrChilds[0]->m_eReturnType )
{
if( m_eReturnType != T_STRING )
return false;
else
{
if( m_ArrPtrChilds[0]->m_eReturnType == T_VOID )
return false;
}
}
break;
case TYPE_COMPOUND_SUBTRACTION :
case TYPE_COMPOUND_MULTIPLICATION :
case TYPE_COMPOUND_DIVISION :
//심볼의 타입이 이 노드의 타입을 결정
m_eReturnType = pSymbolTable->GetTypeOfVar( m_SymbolID );
//심볼 타입과 첫번째 차일드가 다를 때는 무효, int나 float형이 아닐 경우에도 무효
if( m_eReturnType != m_ArrPtrChilds[0]->m_eReturnType )
{
return false;
}
if( m_eReturnType != T_INT && m_eReturnType != T_FLOAT )
return false;
break;
case TYPE_COMPOUND_REMINDER :
//심볼의 타입이 이 노드의 타입을 결정
m_eReturnType = pSymbolTable->GetTypeOfVar( m_SymbolID );
//심볼 타입과 첫번째 차일드가 다를 때는 무효, int형이 아닐 경우에도 무효
if( m_eReturnType != m_ArrPtrChilds[0]->m_eReturnType )
{
return false;
}
if( m_eReturnType != T_INT )
return false;
break;
case TYPE_FUNCTION_CALL :
{
SFuncType type = pSymbolTable->GetTypeOfFunc( m_SymbolID );
m_eReturnType = type.GetReturnType();
break;
}
case TYPE_SWITCH_STATEMENT :
{
if( m_ArrPtrChilds[0]->m_eReturnType != T_INT )
return false;
m_eReturnType = T_VOID;
break;
}
case TYPE_CASE_ONE :
{
if( m_ArrPtrChilds[0]->m_eReturnType != T_INT )
return false;
m_eReturnType = T_VOID;
break;
}
default :
m_eReturnType = T_VOID;
break;
}
return true;
}
CSyntaxTree::CSyntaxTree()
: m_pRoot( 0 )
, m_pSymbolTable( new CSymbolTable )
, m_pPtrStorage( new PTRSTORAGE )
{
}
CSyntaxTree::~CSyntaxTree()
{
Destroy();
delete m_pSymbolTable;
delete m_pPtrStorage;
}
void CSyntaxTree::Create( const char * szFileName )
{
FILE * fp = fopen( szFileName, "rt" );
if( fp == NULL )
return;
yylloc.first_line = 1;
Create( fp );
}
void CSyntaxTree::Create( FILE * fp )
{
yyin = fp;
g_pSynTree = this;
g_pSymbolTable = m_pSymbolTable;
g_pSymbolTable->Create();
yylloc.first_line = 1;
yyparse();
}
void CSyntaxTree::Destroy()
{
typedef PTRSTORAGE::iterator ITERATOR;
for( ITERATOR i = m_pPtrStorage->begin(); i != m_pPtrStorage->end(); i++ )
{
delete (*i);
}
m_pPtrStorage->clear();
m_pSymbolTable->Destroy();
}
int CSyntaxTree::Insert( int line, eSyntaxType SynType, int childID1, int childID2, int childID3 )
{
SNode * pNode = new SNode( line, SynType, (SNode*)childID1, (SNode*)childID2, (SNode*)childID3 );
assert( m_pPtrStorage->insert( pNode ).second );
if( pNode->SemanticCheck( m_pSymbolTable ) == false )
ErrorMessage( pNode->m_iLine, "타입이 맞지 않습니다~\n" );
return (int)pNode;
}
int CSyntaxTree::Insert( int line, int symbolID, eSyntaxType SynType, int childID1, int childID2, int childID3 )
{
SNode * pNode = new SNode( line, SynType, (SNode*)childID1, (SNode*)childID2, (SNode*)childID3 );
assert( m_pPtrStorage->insert( pNode ).second );
pNode->m_SymbolID = symbolID;
if( pNode->SemanticCheck( m_pSymbolTable ) == false )
CompilerMessage2( "Error(line %d) : 타입이 맞지 않습니다~\n", pNode->m_iLine );
return (int)pNode;
}
void CSyntaxTree::SetRoot( int nodeID )
{
if( nodeID != 0 )
{
if( m_pRoot != NULL )
{
Destroy();
}
m_pRoot = (SNode*)nodeID;
}
}
void CSyntaxTree::Show( MESSAGE_FUNCTION2 Print )
{
if( m_pRoot != NULL )
{
m_pRoot->Show( 0, Print, m_pSymbolTable );
}
}