/*
* This file is part of rasdaman community.
*
* Rasdaman community is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rasdaman community is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rasdaman community. If not, see .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
*/
/*************************************************************
*
*
* PURPOSE:
*
*
* COMMENTS:
* The internal functions return 0 on error, 1 on success. Not really common,
* but it was used in some routines and so I stuck with it. Norbert 25-05-2001.
*
************************************************************/
#include "symbtbl.hh"
#include "raslib/rmdebug.hh"
#include "debug/debug.hh"
YSymbol::YSymbol()
{
TALK( "YSymbol::YSymbol default constructor" );
name =NULL;
next =NULL;
owned_by_symbol=true; // by default symbols owned by symbols
scope =NULL;
defines =NULL;
};
YSymbol::YSymbol(const char*_name)
{
TALK( "YSymbol::YSymbol constructor, name=" << name );
name =_name;
next =NULL;
owned_by_symbol=true; // by default symbols owned by symbols
scope =NULL;
defines =NULL;
};
YSymbolTable::YSymbolTable()
{
TALK( "YSymbolTable::YSymbolTable default constructor" );
scope =NULL;
global_scope =NULL;
};
void YSymbolTable::push_scope(YSymbol*owner)
{
Scope *new_scope=new Scope;
new_scope->up =scope;
new_scope->son =NULL;
new_scope->symbols =NULL;
new_scope->last_symbol =NULL;
new_scope->owner =owner;
if(scope!=NULL)
{
new_scope->next =scope->son;
scope->son =new_scope;
owner->defines =new_scope;
}
else
{
new_scope->next =NULL;
};
if(owner==NULL)
global_scope=new_scope;
scope=new_scope;
};
const YSymbol *YSymbolTable::pop_scope()
{
const YSymbol *old_symbol =scope->owner;
scope =scope->up;
return(old_symbol);
};
void YSymbolTable::insert_symbol(YSymbol*symbol)const
{
ENTER( "YSymbolTable::insert_symbol" );
if(scope!=NULL)
{
TALK( "adding symbol " << symbol->get_name() );
if(scope->last_symbol==NULL)
scope->symbols=symbol;
else
scope->last_symbol->next=symbol;
scope->last_symbol = symbol;
symbol->next = NULL;
symbol->scope = scope;
}
LEAVE( "YSymbolTable::insert_symbol" );
};
bool YSymbolTable::search_this_scope(const char*name,const Scope*this_scope,YSymbol*&result)const
{
ENTER( "YSymbolTable::search_this_scope" );
bool found = false;
if((name==NULL)||(this_scope==NULL))
found = false; /* no name or no scope */
else
{
for(YSymbol*scan=this_scope->symbols;scan!=NULL && found!=true;scan=scan->next)
{
if(!strcmp(name,scan->name))
{
result=scan;
found = true;
}
}
}
LEAVE( "YSymbolTable::search_this_scope -> " << found );
return( found );
};
bool YSymbolTable::search_scope(const char*name,YSymbol*&result)const
{
return(search_this_scope(name,scope,result));
};
bool YSymbolTable::search_scopes(const char*name,YSymbol*&result)const
{
for(Scope*scan=scope;scan!=NULL;scan=scan->up)
{
if(search_this_scope(name,scan,result))
return(true);
};
return(false);
};
bool YSymbolTable::search_scopes_above(const YSymbol*symbol,YSymbol*&result)const
{
const char*name=symbol->get_name();
if(symbol->scope==NULL)
return(false);
for(Scope*scan=scope->up;scan!=NULL;scan=scan->up)
{
if(search_this_scope(name,scan,result))
return(true);
};
return(false);
};
bool YSymbolTable::search_my_scope(const char*name,const YSymbol*symbol,YSymbol*&result)const
{
return(search_this_scope(name,symbol->defines,result));
};
bool YSymbolTable::search_global_scope(const char*name,YSymbol*&result)const
{
if(scope==NULL)
return(false); /* no scope at all */
Scope*global;
for(global=scope;global->up!=NULL;global=global->up)
; /* get up to the global scope */
return(search_this_scope(name,global,result));
};
//****************************************************************************
//
// name : get_symbol
// purpose : returns symbol of name in current scope
// remarks : returns NULL if no such symbol defined
//
//****************************************************************************
const YSymbol *YSymbolTable::get_symbol(const char*name)const
{
YSymbol*result;
if(search_scope(name,result))
return(result);
else
return(NULL);
};
//****************************************************************************
//
// name : scoped_symbol
// purpose : creates symbol name within current scope
// remarks : returns true if success full and false if name already exists
// *result is always been changed to new or defined symbol
//
//****************************************************************************
bool YSymbolTable::scoped_symbol(YSymbol**result,const char*name,const YWhere&where)
{
if(search_scope(name,*result))
return(false); // duplicate identifier
*result=new YSymbol(name);
(*result)->where =where;
insert_symbol(*result);
return(true);
};
const YSymbol *YSymbolTable::get_defining_symbol()const
{
if(scope==NULL)
return(NULL);
else
return(scope->owner);
};
void YSymbolTable::Scope::output(FILE*out)const
{
ENTER( "YSymbolTable::Scope::output" );
YSymbol *scan=symbols;
while (scan!=NULL)
{
if(!scan->owned_by_symbol)
{
fprintf(out,"/*[%li,%i]*/",scan->where.line,scan->where.column);
switch(scan->type)
{
case YSymbol::dParse_Type:
scan->Type->output(out);
break;
case YSymbol::dParse_Enumerator:
scan->enumerator->output(out);
break;
default:
RMDBGONCE(0, RMDebug::module_rasdl, "YSymbolTable::Scope", "output() bad YSymbol_type " << scan->type);
break;
}
}
scan=(YSymbol*)scan->next;
}
LEAVE( "YSymbolTable::Scope::output" );
};
void YSymbolTable::Scope::insertData() const
{
ENTER( "YSymbolTable::Scope::insertData" );
YSymbol *scan=symbols;
while(scan!=NULL)
{
if(!scan->owned_by_symbol)
{
switch(scan->type)
{
case YSymbol::dParse_Type:
scan->Type->insertData();
break;
case YSymbol::dParse_Enumerator:
// scan->enumerator->output(out);
break;
default:
RMDBGONCE(0, RMDebug::module_rasdl, "YSymbolTable::Scope", "output() bad YSymbol_type " << scan->type);
break;
}
}
scan=(YSymbol*)scan->next;
}
LEAVE( "YSymbolTable::Scope::insertData" );
};